低资源系统3D渲染库开发:坐标变换后无法获取归一化坐标求助
3D图形渲染坐标流水线问题排查请求
我正在为低资源系统开发3D图形渲染库,目前在理解图形坐标系统流水线时遇到问题。我清楚流程是Local space→World space→View space→Clip space→Screen space,先对顶点应用model矩阵,再依次应用view矩阵和projection矩阵,预期得到[-1,1]范围的归一化坐标,但实际未能实现,恳请协助排查。
相关代码如下:
//vertices to create a cube from 12 triangles std::vector<linear::vector3> vertices{ vector3(-1, -1, -1), vector3(1, -1, -1), vector3(1, 1, -1), vector3(-1, 1, -1), vector3(-1, -1, 1), vector3(1, -1, 1), vector3(1, 1, 1), vector3(-1, 1, 1) }; float aspec = 1080 / 720; linear::Matrix4x4 modelMat = linear::modelMat(vector3(30, 30, 30), vector3(100, 100, 0 ), 0.0, 0.0, linear::toRadians(45.0)); linear::Matrix4x4 viewMat = linear::lookAt(vector3(0, 0, 5), vector3(0, 0, 0), vector3(0, 1, 0)); linear::Matrix4x4 projectionMat = linear::perspectiveMat(linear::toRadians(60.0f), aspec, 1.0f, 1000.0); vector3 transformAndNormalizeVertex(const vector3& vertex, const Matrix4x4& modelMat, const Matrix4x4& viewMat, const Matrix4x4& projectionMat) { vector4 vec1(vertex.x, vertex.y, vertex.z, 1.0); vec1 = matrixVector(modelMat, vec1); vec1 = matrixVector(viewMat, vec1); vec1 = matrixVector(projectionMat, vec1); if (vec1.w != 0.0) { vec1.x /= vec1.w; vec1.y /= vec1.w; vec1.z /= vec1.w; } return vector3(vec1.x, vec1.y, vec1.z); } //code block to apply the transformations. for (auto &triangle : triangles){ cout<< "triangle " << i << endl; for (auto &vertex : triangle) { vertex = transformAndNormalizeVertex(vertex, modelMat, viewMat, projectionMat); cout<< vertex.x << " " << vertex.y << " " << vertex.z << endl; } drawtriangle(linear::vertex2{round(triangle[0].x), round(triangle[0].y)}, linear::vertex2{round(triangle[1].x), round(triangle[1].y)}, linear::vertex2{round(triangle[2].x), round(triangle[2].y)}); }
可能的问题点排查:
- 宽高比计算错误:
float aspec = 1080 / 720;是整数除法,结果为1而非预期的1.5。需改成float aspec = 1080.0f / 720.0f;确保浮点运算。 - 模型位置超出相机视野:modelMat将立方体平移到(30,30,30),但相机在(0,0,5)看向原点,立方体处于相机后方(z=30 > 相机z=5),会被视锥体裁剪。建议先将模型平移改为
vector3(0, 0, 0),确保立方体在相机视野内。 - view矩阵实现正确性:确认
lookAt函数是否正确构建右手坐标系的视图矩阵,是否正确计算相机的前向、右向、上向向量(比如前向向量是否是target - eye的反方向,因为相机通常看向-z方向)。 - 透视矩阵实现验证:检查
perspectiveMat是否符合标准透视投影矩阵公式,特别是z轴映射是否正确——标准透视矩阵会将[near, far]范围内的z值映射到[-1,1](NDC空间)。 - 缺少NDC到屏幕空间的转换:当前直接将归一化坐标传入
drawtriangle,但NDC的[-1,1]需要转换为屏幕像素坐标。示例转换逻辑:
否则会导致图形显示位置异常或超出屏幕。// 假设屏幕宽高为1080和720 float screenX = (vertex.x + 1.0f) * (1080.0f / 2.0f); float screenY = (1.0f - vertex.y) * (720.0f / 2.0f);
内容的提问来源于stack exchange,提问作者Francisco Zavala
相关产品推荐
相关产品推荐

