Camera and Movementhooks are implemented but Camerarotation is faulty

This commit is contained in:
t
2025-04-07 23:01:58 +02:00
parent ce8bc3a96b
commit 76ea39b784
4 changed files with 215 additions and 26 deletions
+1
View File
@@ -53,6 +53,7 @@ add_custom_target(compile_shaders ALL DEPENDS ${SPIRV_SHADERS})
add_executable(vulkan_test add_executable(vulkan_test
main.cpp main.cpp
vulkan/vulkan_app.cpp vulkan/vulkan_app.cpp
vulkan/vulkan_glfw_events.cpp
vulkan/vulkan_app.hpp vulkan/vulkan_app.hpp
) )
+19 -4
View File
@@ -219,6 +219,7 @@ namespace vapp{
VkPhysicalDeviceFeatures deviceFeatures{}; VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.samplerAnisotropy = VK_TRUE; deviceFeatures.samplerAnisotropy = VK_TRUE;
deviceFeatures.sampleRateShading = VK_TRUE;
VkDeviceCreateInfo createInfo{}; VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@@ -554,6 +555,8 @@ namespace vapp{
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE; multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = msaaSamples; multisampling.rasterizationSamples = msaaSamples;
multisampling.sampleShadingEnable = VK_TRUE;
multisampling.minSampleShading = .8f;
VkPipelineColorBlendAttachmentState colorBlendAttachment{}; VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT
@@ -759,9 +762,8 @@ namespace vapp{
if(tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features){ if(tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features){
return format; return format;
} }
throw std::runtime_error("Func: findSupportedFormat\nError: Failed to find supported Format!\n");
} }
throw std::runtime_error("Func: findSupportedFormat\nError: Failed to find supported Format!\n");
} }
VkFormat Vulkan::findDepthFormat(){ VkFormat Vulkan::findDepthFormat(){
@@ -1435,8 +1437,8 @@ namespace vapp{
UniformBufferObject ubo{}; UniformBufferObject ubo{};
// INFO: Change here for other angles // INFO: Change here for other angles
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(60.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.view = glm::lookAt(cameraPos, cameraFront, cameraUp);
ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float)swapChainExtent.height, 0.1f, 10.0f); ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float)swapChainExtent.height, 0.1f, 10.0f);
// removing this line results in the image rendering upside down // removing this line results in the image rendering upside down
@@ -1543,6 +1545,13 @@ namespace vapp{
app->framebufferResized = true; app->framebufferResized = true;
} }
static void handleMouseInputCallback(GLFWwindow* window, double xpos, double ypos) {
Vulkan* vulkan = static_cast<Vulkan*>(glfwGetWindowUserPointer(window));
if (vulkan) {
vulkan->handleMouseInput(window, xpos, ypos);
}
}
void Vulkan::initWindow(const char *windowName){ void Vulkan::initWindow(const char *windowName){
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // tell glfw to not use opengl glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // tell glfw to not use opengl
@@ -1550,6 +1559,9 @@ namespace vapp{
this->window = glfwCreateWindow(static_cast<int>(_width), static_cast<int>(_height), windowName, nullptr, nullptr); this->window = glfwCreateWindow(static_cast<int>(_width), static_cast<int>(_height), windowName, nullptr, nullptr);
glfwSetWindowUserPointer(window, this); glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
glfwSetCursorPosCallback(window, handleMouseInputCallback);
} }
void Vulkan::initVulkan(){ void Vulkan::initVulkan(){
@@ -1584,6 +1596,9 @@ namespace vapp{
while(!glfwWindowShouldClose(this->window)){ while(!glfwWindowShouldClose(this->window)){
// glfwSwapBuffers(window); // glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
handleKeyboardInput();
drawFrame(); drawFrame();
} }
vkDeviceWaitIdle(device); vkDeviceWaitIdle(device);
+75 -22
View File
@@ -27,16 +27,35 @@
#include <chrono> #include <chrono>
#include <unordered_map> #include <unordered_map>
namespace vapp{ namespace vapp
{
class Camera
{
private:
glm::mat4 projectionMatrix{1.f};
glm::mat4 viewMatrix{1.f};
public:
void setOthographicProjection(float left, float right, float bottom, float top);
void setPerspectiveProjection(float fovy, float aspect, float zNear, float zFar);
void setViewDirection(glm::vec3 position, glm::vec3 direction, glm::vec3 up);
void setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up);
void setViewYXZ(glm::vec3 position, glm::vec3 rotation);
const glm::mat4& getProjectionMatrix();
const glm::mat4& getViewMatrix();
};
// Change here for other presentMode // Change here for other presentMode
const VkPresentModeKHR WISHED_PRESENT_MODE = VK_PRESENT_MODE_MAILBOX_KHR; const VkPresentModeKHR WISHED_PRESENT_MODE = VK_PRESENT_MODE_MAILBOX_KHR;
struct Vertex{ struct Vertex
{
glm::vec3 pos; glm::vec3 pos;
glm::vec3 color; glm::vec3 color;
glm::vec2 texCoord; glm::vec2 texCoord;
static VkVertexInputBindingDescription getBindingDescription(){ static VkVertexInputBindingDescription getBindingDescription()
{
VkVertexInputBindingDescription bindingDescription{}; VkVertexInputBindingDescription bindingDescription{};
bindingDescription.binding = 0; bindingDescription.binding = 0;
@@ -46,7 +65,8 @@ namespace vapp{
return bindingDescription; return bindingDescription;
} }
static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions(){ static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions()
{
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{}; std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};
attributeDescriptions[0].binding = 0; attributeDescriptions[0].binding = 0;
@@ -67,7 +87,8 @@ namespace vapp{
return attributeDescriptions; return attributeDescriptions;
} }
bool operator==(const Vertex &other) const{ bool operator==(const Vertex& other) const
{
return pos == other.pos && color == other.color && texCoord == other.texCoord; return pos == other.pos && color == other.color && texCoord == other.texCoord;
} }
}; };
@@ -93,22 +114,26 @@ namespace vapp{
*/ */
// END Remove // END Remove
struct UniformBufferObject{ struct UniformBufferObject
{
alignas(16) glm::mat4 model; alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view; alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj; alignas(16) glm::mat4 proj;
}; };
struct QueueFamilyIndices{ struct QueueFamilyIndices
{
std::optional<uint32_t> graphicsFamily; std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily; std::optional<uint32_t> presentFamily;
bool isComplete(){ bool isComplete()
{
return graphicsFamily.has_value(); return graphicsFamily.has_value();
} }
}; };
struct SwapChainSupportDetails{ struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities; VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats; std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes; std::vector<VkPresentModeKHR> presentModes;
@@ -118,10 +143,11 @@ namespace vapp{
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescription(); static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescription();
class Vulkan{ class Vulkan
{
private: private:
#pragma region PrivateFields #pragma region PrivateFields
GLFWwindow *window; GLFWwindow* window;
uint32_t _width, _height; uint32_t _width, _height;
VkInstance instance; VkInstance instance;
@@ -213,22 +239,28 @@ namespace vapp{
void createRenderPass(); void createRenderPass();
void createFramebuffers(); void createFramebuffers();
void createCommandPool(); void createCommandPool();
VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling,
VkFormatFeatureFlags features);
VkFormat findDepthFormat(); VkFormat findDepthFormat();
void createColorResources(); void createColorResources();
void createDepthResources(); void createDepthResources();
VkCommandBuffer beginSingleTimeCommands(); VkCommandBuffer beginSingleTimeCommands();
void endSingleTimeCommands(VkCommandBuffer commandBuffer); void endSingleTimeCommands(VkCommandBuffer commandBuffer);
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels); void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout,
uint32_t mipLevels);
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height); void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height);
void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory &imageMemory); void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples,
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels); VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage,
VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory);
void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight,
uint32_t mipLevels);
void createTextureImage(); void createTextureImage();
VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels); VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels);
void createTextureImageView(); void createTextureImageView();
void createTextureSampler(); void createTextureSampler();
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory); void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties,
VkBuffer& buffer, VkDeviceMemory& bufferMemory);
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
void copyBufferOld(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); void copyBufferOld(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
void loadModel(); void loadModel();
@@ -244,11 +276,12 @@ namespace vapp{
void drawFrame(); void drawFrame();
void cleanupSwapChain(); void cleanupSwapChain();
void recreateSwapChain(); void recreateSwapChain();
void initWindow(const char *windowName); void initWindow(const char* windowName);
void initVulkan(); void initVulkan();
void mainLoop(); void mainLoop();
void cleanup(); void cleanup();
#pragma endregion #pragma endregion
public: public:
#pragma region PublicFields #pragma region PublicFields
#ifdef DEBUG #ifdef DEBUG
@@ -262,19 +295,39 @@ namespace vapp{
std::string TEXTURE_PATH; std::string TEXTURE_PATH;
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT; VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
float yaw = -90.0f;
float pitch = 0.0f;
float lastX = 400.0f;
float lastY = 300.0f;
bool firstMouse = true;
glm::vec3 cameraPos = glm::vec3(2.0f, 2.0f, 2.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 0.0f, 1.0f);
#pragma endregion #pragma endregion
#pragma region PublicFunctions #pragma region PublicFunctions
void run(const char *windowName, const uint32_t width = 800, const uint32_t height = 600); void run(const char* windowName, const uint32_t width = 800, const uint32_t height = 600);
#pragma endregion
#pragma region GLFWFunctions
void handleKeyboardInput();
void handleMouseInput(GLFWwindow* window, double xpos, double ypos);
#pragma endregion #pragma endregion
}; };
} // vapp } // vapp
namespace std{ namespace std
template<> struct hash<vapp::Vertex>{ {
size_t operator()(vapp::Vertex const &vertex) const{ template <>
struct hash<vapp::Vertex>
{
size_t operator()(vapp::Vertex const& vertex) const
{
return ((hash<glm::vec3>()(vertex.pos) ^ return ((hash<glm::vec3>()(vertex.pos) ^
(hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^ (hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^
(hash<glm::vec2>()(vertex.texCoord) << 1); (hash<glm::vec2>()(vertex.texCoord) << 1);
} }
}; };
} }
+120
View File
@@ -0,0 +1,120 @@
#include "vulkan_app.hpp"
namespace vapp{
void Camera::setOthographicProjection(float left, float right, float bottom, float top){
}
void Camera::setPerspectiveProjection(float fovy, float aspect, float zNear, float zFar){
}
void Camera::setViewDirection(glm::vec3 position, glm::vec3 direction, glm::vec3 up) {
const glm::vec3 w{glm::normalize(direction)};
const glm::vec3 u{glm::normalize(glm::cross(w, up))};
const glm::vec3 v{glm::cross(w, u)};
viewMatrix = glm::mat4{1.f};
viewMatrix[0][0] = u.x;
viewMatrix[1][0] = u.y;
viewMatrix[2][0] = u.z;
viewMatrix[0][1] = v.x;
viewMatrix[1][1] = v.y;
viewMatrix[2][1] = v.z;
viewMatrix[0][2] = w.x;
viewMatrix[1][2] = w.y;
viewMatrix[2][2] = w.z;
viewMatrix[3][0] = -glm::dot(u, position);
viewMatrix[3][1] = -glm::dot(v, position);
viewMatrix[3][2] = -glm::dot(w, position);
}
void Camera::setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up) {
setViewDirection(position, target - position, up);
}
void Camera::setViewYXZ(glm::vec3 position, glm::vec3 rotation) {
const float c3 = glm::cos(rotation.z);
const float s3 = glm::sin(rotation.z);
const float c2 = glm::cos(rotation.x);
const float s2 = glm::sin(rotation.x);
const float c1 = glm::cos(rotation.y);
const float s1 = glm::sin(rotation.y);
const glm::vec3 u{(c1 * c3 + s1 * s2 * s3), (c2 * s3), (c1 * s2 * s3 - c3 * s1)};
const glm::vec3 v{(c3 * s1 * s2 - c1 * s3), (c2 * c3), (c1 * c3 * s2 + s1 * s3)};
const glm::vec3 w{(c2 * s1), (-s2), (c1 * c2)};
viewMatrix = glm::mat4{1.f};
viewMatrix[0][0] = u.x;
viewMatrix[1][0] = u.y;
viewMatrix[2][0] = u.z;
viewMatrix[0][1] = v.x;
viewMatrix[1][1] = v.y;
viewMatrix[2][1] = v.z;
viewMatrix[0][2] = w.x;
viewMatrix[1][2] = w.y;
viewMatrix[2][2] = w.z;
viewMatrix[3][0] = -glm::dot(u, position);
viewMatrix[3][1] = -glm::dot(v, position);
viewMatrix[3][2] = -glm::dot(w, position);
}
void Vulkan::handleKeyboardInput(){
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
cameraPos.x += 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
cameraPos.x -= 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
cameraPos.y -= 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
cameraPos.y += 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
cameraPos.x += 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
cameraPos.x -= 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS){
cameraPos.z += 0.001f;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS){
cameraPos.z -= 0.001f;
}
}
void Vulkan::handleMouseInput(GLFWwindow* window, double xpos, double ypos){
double xoffset = xpos - (_width / 2.0);
double yoffset = ypos - (_height / 2.0);
glfwSetCursorPos(window, _width / 2.0, _height / 2.0);
float sensitivity = 0.001f;
xoffset *= sensitivity;
yoffset *= sensitivity;
// Winkel aktualisieren
yaw += xoffset;
pitch += yoffset;
// Optional: pitch begrenzen
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
// Berechnung des neuen Richtungsvektors
glm::vec3 direction;
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
direction.y = sin(glm::radians(pitch));
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
direction = glm::normalize(direction);
// Der neue "Look-at"-Punkt ergibt sich aus der Kameraposition plus diesem Richtungsvektor
cameraFront = cameraPos + direction;
}
}