Vulkan旋转异常问题:无法使Quad正确朝向相机
问题:Quad旋转朝向相机不符合预期
我跟着Branden Gela的教程搭建了Vulkan管线,基于他的gameobject类派生了自定义类,游戏对象的变换矩阵实现如下:
glm::mat4 TransformComponent::mat4() { { 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); return glm::mat4{ { scale.x * (c1 * c3 + s1 * s2 * s3), scale.x * (c2 * s3), scale.x * (c1 * s2 * s3 - c3 * s1), 0.0f, }, { scale.y * (c3 * s1 * s2 - c1 * s3), scale.y * (c2 * c3), scale.y * (c1 * c3 * s2 + s1 * s3), 0.0f, }, { scale.z * (c2 * s1), scale.z * (-s2), scale.z * (c1 * c2), 0.0f, }, {translation.x, translation.y, translation.z, 1.0f} }; } } glm::mat3 TransformComponent::normalMatrix() { 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 invScale = 1.0f/scale; return glm::mat3{ { invScale.x * (c1 * c3 + s1 * s2 * s3), invScale.x * (c2 * s3), invScale.x * (c1 * s2 * s3 - c3 * s1), }, { invScale.y * (c3 * s1 * s2 - c1 * s3), invScale.y * (c2 * c3), invScale.y * (c1 * c3 * s2 + s1 * s3), }, { invScale.z * (c2 * s1), invScale.z * (-s2), invScale.z * (c1 * c2), }, }; }
现在想让一个Quad朝向相机,但旋转效果始终不符合预期。当前设置旋转的代码为:
player.transform.rotation = { 190.f,0.f,0.f };
得到的侧视图既不是完全180°,也不符合设置的190°。相机未设置默认旋转,不确定是Vulkan旋转处理机制问题,还是遗漏了关键步骤?
分析与解决方案
角度单位不匹配:GLM的
cos/sin函数默认接收弧度值,但你传入的是190角度值,这会导致旋转计算完全错误。修正方法是将角度转换为弧度:player.transform.rotation = { glm::radians(190.f), 0.f, 0.f };旋转顺序不符合直觉:从你提供的
mat4()实现可以看出,旋转顺序是Z→X→Y,而不是常见的Yaw-Pitch-Roll(Y→X→Z)顺序。如果你的操作逻辑是按Y-X-Z的直觉设置旋转,实际生效的旋转会和预期偏差。比如设置X轴旋转190°,但由于Z轴先参与计算(即使值为0),最终旋转结果会和你预想的不一样。朝向相机的正确实现方式:硬编码旋转角度不是让Quad始终朝向相机的最优解,正确的做法是通过方向向量推导旋转:
- 计算相机到Quad的方向向量:
glm::vec3 lookDir = glm::normalize(cameraPosition - quadTransform.translation); - 构造朝向该方向的旋转矩阵(通过
glm::lookAt的逆矩阵实现,因为lookAt是相机看向目标的矩阵,逆矩阵就是目标看向相机的矩阵):glm::mat4 targetRot = glm::inverse(glm::lookAt(quadTransform.translation, quadTransform.translation + lookDir, glm::vec3(0, 1, 0))); - 从旋转矩阵中提取欧拉角,或者直接将矩阵分解后的旋转值赋值给你的TransformComponent(如果支持直接设置矩阵的话)。
- 计算相机到Quad的方向向量:
Vulkan坐标系差异:Vulkan采用右手坐标系,但Y轴向下(与OpenGL的Y轴向上不同)。如果你的管线没有处理好坐标系转换,可能会导致旋转视觉上的偏差。检查投影矩阵、视图矩阵是否适配了Vulkan的坐标系(比如添加Y轴翻转的处理)。
内容的提问来源于stack exchange,提问作者VChuckShunA
相关产品推荐
相关产品推荐

