bit of a refactoring
This commit is contained in:
parent
4c82bbe275
commit
cf7b42b95c
|
@ -1,3 +1,8 @@
|
|||
[fmt]
|
||||
src.github = "fmtlib/fmt"
|
||||
fetch.github = "fmtlib/fmt"
|
||||
|
||||
[imgui]
|
||||
src.git = "https://github.com/ocornut/imgui.git"
|
||||
src.branch = "docking"
|
||||
fetch.github = "ocornut/imgui"
|
||||
|
|
301
src/main.cpp
301
src/main.cpp
|
@ -23,6 +23,7 @@
|
|||
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||
|
||||
// Include custom utility headers
|
||||
#include "util/constants.hpp" // Constants definitions
|
||||
#include "util/crosshair.hpp" // Crosshair definitions
|
||||
#include "util/shaders.hpp" // Compiled shader code
|
||||
#include "util/types.hpp" // Custom type definitions
|
||||
|
@ -38,34 +39,7 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
|||
#define VKFW_NO_STRUCT_CONSTRUCTORS // Use aggregate initialization for GLFW structs
|
||||
#include "vkfw.hpp" // Include GLFW C++ bindings
|
||||
|
||||
// Constants for window dimensions
|
||||
constexpr i32 WIDTH = 1920;
|
||||
constexpr i32 HEIGHT = 1080;
|
||||
|
||||
// CAMERA_SPEED of camera movement
|
||||
constexpr f64 CAMERA_SPEED = 1.0;
|
||||
|
||||
// Maximum number of frames that can be processed concurrently
|
||||
constexpr i32 MAX_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
// Shader file paths
|
||||
constexpr const char* VERTEX_SHADER_PATH = "shaders/vertex.glsl";
|
||||
constexpr const char* FRAGMENT_SHADER_PATH = "shaders/fragment.glsl";
|
||||
constexpr const char* CROSSHAIR_VERTEX_SHADER_PATH = "shaders/crosshair_vertex.glsl";
|
||||
constexpr const char* CROSSHAIR_FRAGMENT_SHADER_PATH = "shaders/crosshair_fragment.glsl";
|
||||
|
||||
// Validation layers for debug builds
|
||||
#ifndef NDEBUG
|
||||
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
||||
#endif
|
||||
|
||||
// Required device extensions (platform-specific)
|
||||
#ifdef __APPLE__
|
||||
constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtensionName,
|
||||
vk::KHRPortabilitySubsetExtensionName };
|
||||
#else
|
||||
constexpr std::array<const char*, 1> deviceExtensions = { vk::KHRSwapchainExtensionName };
|
||||
#endif
|
||||
using namespace constants;
|
||||
|
||||
/**
|
||||
* @brief The Vulkan application class.
|
||||
|
@ -204,9 +178,12 @@ class VulkanApp {
|
|||
bool mCursorCaptured = true; ///< Flag indicating if cursor is captured
|
||||
|
||||
// ImGui-related state
|
||||
f32 mCameraSpeed = CAMERA_SPEED; ///< Current camera speed
|
||||
f32 mFieldOfView = 90.0F; ///< Current field of view
|
||||
bool mWireframeMode = false; ///< Wireframe rendering mode
|
||||
f32 mCameraSpeed = CAMERA_SPEED; ///< Current camera speed
|
||||
f32 mFieldOfView = 90.0F; ///< Current field of view
|
||||
bool mWireframeMode = false; ///< Wireframe rendering mode
|
||||
f32 mLineWidth = 1.0F; ///< Line width for wireframe mode
|
||||
f32 mMaxLineWidth = 1.0F; ///< Maximum supported line width
|
||||
bool mWideLineSupport = false; ///< Whether wide lines are supported
|
||||
|
||||
/**
|
||||
* @brief Struct to store queue family indices.
|
||||
|
@ -551,6 +528,10 @@ class VulkanApp {
|
|||
// copy and the changes won't be saved.
|
||||
ImGuiIO& imGuiIO = ImGui::GetIO();
|
||||
|
||||
// Enable docking and viewports
|
||||
imGuiIO.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
|
||||
imGuiIO.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport
|
||||
|
||||
// Disable writing imgui.ini
|
||||
imGuiIO.IniFilename = nullptr;
|
||||
|
||||
|
@ -617,116 +598,12 @@ class VulkanApp {
|
|||
processInput(mWindow.get(), mCamera, static_cast<f32>(deltaTime), mCameraSpeed);
|
||||
mView = mCamera.getViewMatrix();
|
||||
|
||||
if (currentFrame - lastFpsUpdate > 1.0) {
|
||||
mWindow->setTitle(
|
||||
fmt::format("Vulkan - {:.0f}FPS", static_cast<f32>(frameCounter / (currentFrame - lastFpsUpdate)))
|
||||
);
|
||||
lastFpsUpdate = currentFrame;
|
||||
frameCounter = 0;
|
||||
}
|
||||
++frameCounter;
|
||||
|
||||
updateFrameStats(lastFpsUpdate, frameCounter);
|
||||
vkfw::pollEvents();
|
||||
|
||||
// Start the ImGui frame
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Create ImGui window with controls
|
||||
ImGui::Begin("Controls");
|
||||
|
||||
// Camera Position
|
||||
auto pos = mCamera.getPosition();
|
||||
ImGui::Text("Camera Position: (%.2f, %.2f, %.2f)", pos.x, pos.y, pos.z);
|
||||
|
||||
// Camera Settings
|
||||
if (ImGui::CollapsingHeader("Camera Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::SliderFloat("Camera Speed", &mCameraSpeed, 0.1F, 10.0F, "%.1f");
|
||||
ImGui::SliderFloat("Field of View", &mFieldOfView, 45.0F, 120.0F, "%.1f");
|
||||
if (ImGui::Button("Reset Camera")) {
|
||||
mCamera = Camera(); // Reset to default position
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering Settings
|
||||
if (ImGui::CollapsingHeader("Rendering Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
// Wireframe Mode
|
||||
if (ImGui::Checkbox("Wireframe Mode", &mWireframeMode)) {
|
||||
recreateSwapChain();
|
||||
}
|
||||
|
||||
// Line Width (only in wireframe mode)
|
||||
static float LineWidth = 1.0F;
|
||||
if (mWireframeMode) {
|
||||
if (ImGui::SliderFloat("Line Width", &LineWidth, 1.0F, 5.0F, "%.1f")) {
|
||||
// TODO: Update line width in pipeline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Controls Help
|
||||
if (ImGui::CollapsingHeader("Controls", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::BulletText("Use mouse to look around");
|
||||
ImGui::BulletText("WASD to move horizontally");
|
||||
ImGui::BulletText("Space/Shift to move up/down");
|
||||
ImGui::BulletText("ESC to toggle mouse capture");
|
||||
ImGui::BulletText("Tab to toggle this menu");
|
||||
}
|
||||
|
||||
// Performance Metrics
|
||||
if (ImGui::CollapsingHeader("Performance", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Text(
|
||||
"Application average %.3f ms/frame (%.1f FPS)",
|
||||
static_cast<f64>(1000.0F / ImGui::GetIO().Framerate),
|
||||
static_cast<f64>(ImGui::GetIO().Framerate)
|
||||
);
|
||||
|
||||
// Memory Usage
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Memory Usage:");
|
||||
ImGui::Text(
|
||||
"Vertex Buffer: %.2f MB",
|
||||
(static_cast<double>(mVertices.size()) * static_cast<double>(sizeof(Vertex))) / (1024.0 * 1024.0)
|
||||
);
|
||||
ImGui::Text(
|
||||
"Index Buffer: %.2f MB",
|
||||
(static_cast<double>(mIndices.size()) * static_cast<double>(sizeof(uint32_t))) / (1024.0 * 1024.0)
|
||||
);
|
||||
|
||||
// Camera Information
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Camera Information:");
|
||||
ImGui::Text(
|
||||
"Position: (%.2f, %.2f, %.2f)",
|
||||
mCamera.getPosition().x,
|
||||
mCamera.getPosition().y,
|
||||
mCamera.getPosition().z
|
||||
);
|
||||
ImGui::Text(
|
||||
"Front Vector: (%.2f, %.2f, %.2f)", mCamera.getFront().x, mCamera.getFront().y, mCamera.getFront().z
|
||||
);
|
||||
ImGui::Text("Yaw: %.2f°, Pitch: %.2f°", mCamera.getYaw(), mCamera.getPitch());
|
||||
|
||||
// Light Controls
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Light Controls:");
|
||||
|
||||
// Light Position
|
||||
ImGui::DragFloat3("Light Position", &mLightSettings.position.x, 0.1F, -10.0F, 10.0F);
|
||||
|
||||
// Light Color
|
||||
ImGui::ColorEdit3("Light Color", &mLightSettings.color.x);
|
||||
|
||||
// Light Strengths
|
||||
ImGui::SliderFloat("Ambient Strength", &mLightSettings.ambient_strength, 0.0F, 1.0F);
|
||||
ImGui::SliderFloat("Specular Strength", &mLightSettings.specular_strength, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// Render ImGui
|
||||
ImGui::Render();
|
||||
setupImGuiFrame();
|
||||
renderImGuiControls();
|
||||
finalizeImGuiFrame();
|
||||
|
||||
drawFrame();
|
||||
}
|
||||
|
@ -734,6 +611,138 @@ class VulkanApp {
|
|||
mDevice->waitIdle();
|
||||
}
|
||||
|
||||
fn renderImGuiControls() -> void {
|
||||
// Camera Settings
|
||||
if (ImGui::CollapsingHeader("Camera Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::SliderFloat("Camera Speed", &mCameraSpeed, 0.1F, 10.0F, "%.1f");
|
||||
ImGui::SliderFloat("Field of View", &mFieldOfView, 45.0F, 120.0F, "%.1f");
|
||||
if (ImGui::Button("Reset Camera")) {
|
||||
mCamera = Camera();
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering Settings
|
||||
if (ImGui::CollapsingHeader("Rendering Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
if (ImGui::Checkbox("Wireframe Mode", &mWireframeMode)) {
|
||||
recreateSwapChain();
|
||||
}
|
||||
|
||||
if (mWireframeMode) {
|
||||
if (mWideLineSupport) {
|
||||
if (ImGui::SliderFloat("Line Width", &mLineWidth, 1.0F, mMaxLineWidth, "%.1f")) {
|
||||
mDevice->waitIdle();
|
||||
createGraphicsPipeline();
|
||||
}
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1.0F, 0.5F, 0.5F, 1.0F), "Wide lines not supported on this device");
|
||||
mLineWidth = 1.0F;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderControlsHelp();
|
||||
renderPerformanceMetrics();
|
||||
}
|
||||
|
||||
static fn renderControlsHelp() -> void {
|
||||
if (ImGui::CollapsingHeader("Controls", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::BulletText("Use mouse to look around");
|
||||
ImGui::BulletText("WASD to move horizontally");
|
||||
ImGui::BulletText("Space/Shift to move up/down");
|
||||
ImGui::BulletText("ESC to toggle mouse capture");
|
||||
ImGui::BulletText("Tab to toggle this menu");
|
||||
}
|
||||
}
|
||||
|
||||
fn renderPerformanceMetrics() -> void {
|
||||
if (ImGui::CollapsingHeader("Performance", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
renderFrameMetrics();
|
||||
renderMemoryUsage();
|
||||
renderCameraInfo();
|
||||
renderLightControls();
|
||||
}
|
||||
}
|
||||
|
||||
static fn renderFrameMetrics() -> void {
|
||||
ImGui::Text(
|
||||
"Application average %.3f ms/frame (%.1f FPS)",
|
||||
static_cast<f64>(1000.0F / ImGui::GetIO().Framerate),
|
||||
static_cast<f64>(ImGui::GetIO().Framerate)
|
||||
);
|
||||
}
|
||||
|
||||
fn renderMemoryUsage() -> void {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Memory Usage:");
|
||||
ImGui::Text(
|
||||
"Vertex Buffer: %.2f MB",
|
||||
(static_cast<double>(mVertices.size()) * static_cast<double>(sizeof(Vertex))) / (1024.0 * 1024.0)
|
||||
);
|
||||
ImGui::Text(
|
||||
"Index Buffer: %.2f MB",
|
||||
(static_cast<double>(mIndices.size()) * static_cast<double>(sizeof(uint32_t))) / (1024.0 * 1024.0)
|
||||
);
|
||||
}
|
||||
|
||||
fn renderCameraInfo() -> void {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Camera Information:");
|
||||
ImGui::Text(
|
||||
"Position: (%.2f, %.2f, %.2f)",
|
||||
mCamera.getPosition().x,
|
||||
mCamera.getPosition().y,
|
||||
mCamera.getPosition().z
|
||||
);
|
||||
ImGui::Text(
|
||||
"Front Vector: (%.2f, %.2f, %.2f)", mCamera.getFront().x, mCamera.getFront().y, mCamera.getFront().z
|
||||
);
|
||||
ImGui::Text("Yaw: %.2f°, Pitch: %.2f°", mCamera.getYaw(), mCamera.getPitch());
|
||||
}
|
||||
|
||||
fn renderLightControls() -> void {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Light Controls:");
|
||||
|
||||
// Light Position
|
||||
ImGui::DragFloat3("Light Position", &mLightSettings.position.x, 0.1F, -10.0F, 10.0F);
|
||||
|
||||
// Light Color
|
||||
ImGui::ColorEdit3("Light Color", &mLightSettings.color.x);
|
||||
|
||||
// Light Strengths
|
||||
ImGui::SliderFloat("Ambient Strength", &mLightSettings.ambient_strength, 0.0F, 1.0F);
|
||||
ImGui::SliderFloat("Specular Strength", &mLightSettings.specular_strength, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
fn updateFrameStats(f64& lastFpsUpdate, i32& frameCounter) -> void {
|
||||
f64 currentFrame = vkfw::getTime();
|
||||
if (currentFrame - lastFpsUpdate > 1.0) {
|
||||
mWindow->setTitle(
|
||||
fmt::format("Vulkan - {:.0f}FPS", static_cast<f32>(frameCounter / (currentFrame - lastFpsUpdate)))
|
||||
);
|
||||
lastFpsUpdate = currentFrame;
|
||||
frameCounter = 0;
|
||||
}
|
||||
++frameCounter;
|
||||
}
|
||||
|
||||
static fn setupImGuiFrame() -> void {
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
ImGui::Begin("Controls");
|
||||
}
|
||||
|
||||
static fn finalizeImGuiFrame() -> void {
|
||||
ImGui::End();
|
||||
ImGui::Render();
|
||||
|
||||
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cleans up the swap chain resources.
|
||||
*
|
||||
|
@ -912,6 +921,16 @@ class VulkanApp {
|
|||
if (isDeviceSuitable(device)) {
|
||||
mPhysicalDevice = device;
|
||||
mMsaaSamples = getMaxUsableSampleCount();
|
||||
|
||||
// Get the device properties for line width limits
|
||||
vk::PhysicalDeviceProperties deviceProperties = device.getProperties();
|
||||
mMaxLineWidth = deviceProperties.limits.lineWidthRange[1];
|
||||
mWideLineSupport = deviceProperties.limits.lineWidthRange[1] > 1.0F;
|
||||
|
||||
#ifndef NDEBUG
|
||||
fmt::println("Maximum supported line width: {}", mMaxLineWidth);
|
||||
fmt::println("Wide lines supported: {}", mWideLineSupport ? "yes" : "no");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1249,7 +1268,7 @@ class VulkanApp {
|
|||
.cullMode = vk::CullModeFlagBits::eBack,
|
||||
.frontFace = vk::FrontFace::eCounterClockwise,
|
||||
.depthBiasEnable = vk::False,
|
||||
.lineWidth = mWireframeMode ? 2.0F : 1.0F, // Thicker lines in wireframe mode
|
||||
.lineWidth = mWireframeMode ? mLineWidth : 1.0F, // Thicker lines in wireframe mode
|
||||
};
|
||||
|
||||
vk::PipelineMultisampleStateCreateInfo multisampling {
|
||||
|
@ -2045,7 +2064,7 @@ class VulkanApp {
|
|||
attrib.vertices[static_cast<u32>((3 * index.vertex_index) + 2)],
|
||||
},
|
||||
.color = { 1.0F, 1.0F, 1.0F },
|
||||
.texCoord = {
|
||||
.tex_coord = {
|
||||
attrib.texcoords[static_cast<u32>((2 * index.texcoord_index) + 0)],
|
||||
1.0F - attrib.texcoords[static_cast<u32>((2 * index.texcoord_index) + 1)],
|
||||
},
|
||||
|
|
37
src/util/constants.hpp
Normal file
37
src/util/constants.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace constants {
|
||||
// Window dimensions
|
||||
constexpr i32 WIDTH = 1920;
|
||||
constexpr i32 HEIGHT = 1080;
|
||||
|
||||
// Camera settings
|
||||
constexpr f64 CAMERA_SPEED = 1.0;
|
||||
|
||||
// Frame processing
|
||||
constexpr i32 MAX_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
// Shader paths
|
||||
constexpr const char* VERTEX_SHADER_PATH = "shaders/vertex.glsl";
|
||||
constexpr const char* FRAGMENT_SHADER_PATH = "shaders/fragment.glsl";
|
||||
constexpr const char* CROSSHAIR_VERTEX_SHADER_PATH = "shaders/crosshair_vertex.glsl";
|
||||
constexpr const char* CROSSHAIR_FRAGMENT_SHADER_PATH = "shaders/crosshair_fragment.glsl";
|
||||
|
||||
// Validation layers
|
||||
#ifndef NDEBUG
|
||||
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
|
||||
#endif
|
||||
|
||||
// Device extensions
|
||||
#ifdef __APPLE__
|
||||
constexpr std::array<const char*, 2> deviceExtensions = { vk::KHRSwapchainExtensionName,
|
||||
vk::KHRPortabilitySubsetExtensionName };
|
||||
#else
|
||||
constexpr std::array<const char*, 1> deviceExtensions = { vk::KHRSwapchainExtensionName };
|
||||
#endif
|
||||
}
|
|
@ -27,7 +27,7 @@
|
|||
struct Vertex {
|
||||
glm::vec3 pos; ///< Position of the vertex in 3D space (x, y, z)
|
||||
glm::vec3 color; ///< RGB color values, each component in range [0, 1]
|
||||
glm::vec2 texCoord; ///< Texture coordinates (u, v) for texture mapping
|
||||
glm::vec2 tex_coord; ///< Texture coordinates (u, v) for texture mapping
|
||||
glm::vec3 normal; ///< Normal vector of the vertex
|
||||
|
||||
/**
|
||||
|
@ -51,7 +51,8 @@ struct Vertex {
|
|||
/**
|
||||
* @brief Provides attribute descriptions for vertex data interpretation.
|
||||
*
|
||||
* @return std::array<vk::VertexInputAttributeDescription, 4> Array of descriptions for position, color, texture coordinates, and normal.
|
||||
* @return std::array<vk::VertexInputAttributeDescription, 4> Array of descriptions for position, color,
|
||||
* texture coordinates, and normal.
|
||||
*
|
||||
* The attribute descriptions specify:
|
||||
* - Location indices (0 for position, 1 for color, 2 for texture coordinates, 3 for normal)
|
||||
|
@ -62,29 +63,29 @@ struct Vertex {
|
|||
static fn getAttributeDescriptions() -> std::array<vk::VertexInputAttributeDescription, 4> {
|
||||
return {
|
||||
vk::VertexInputAttributeDescription {
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, pos),
|
||||
},
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, pos),
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, color),
|
||||
},
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, color),
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32Sfloat,
|
||||
.offset = offsetof(Vertex, texCoord),
|
||||
},
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32Sfloat,
|
||||
.offset = offsetof(Vertex, tex_coord),
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, normal),
|
||||
},
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = vk::Format::eR32G32B32Sfloat,
|
||||
.offset = offsetof(Vertex, normal),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -95,7 +96,7 @@ struct Vertex {
|
|||
* @return bool True if vertices are identical in position, color, texture coordinates, and normal.
|
||||
*/
|
||||
fn operator==(const Vertex& other) const->bool {
|
||||
return pos == other.pos && color == other.color && texCoord == other.texCoord && normal == other.normal;
|
||||
return pos == other.pos && color == other.color && tex_coord == other.tex_coord && normal == other.normal;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -117,8 +118,7 @@ namespace std {
|
|||
*/
|
||||
fn operator()(Vertex const& vertex) const->size_t {
|
||||
return ((hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^
|
||||
(hash<glm::vec2>()(vertex.texCoord) << 1) ^
|
||||
(hash<glm::vec3>()(vertex.normal) << 2);
|
||||
(hash<glm::vec2>()(vertex.tex_coord) << 1) ^ (hash<glm::vec3>()(vertex.normal) << 2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue