【发布时间】:2015-02-06 10:54:59
【问题描述】:
我正在尝试从头开始构建自己的光栅/图形管道(模仿 OpenGL),但在实现工作透视投影矩阵时遇到了问题。这是我目前的尝试:
template<typename T>
Matrix<T,4,4> Perspective(T fov,T aspect, T near, T far)
{
T mat00 = 1 / (aspect*tan(0.5f*fov));
T mat11 = 1 / tan(0.5f*fov);
T mat22 = (-near-far)/(near-far);
T mat32 = (2*near*far)/(near-far);
T data[] =
{
mat00, 0, 0, 0,
0 , mat11, 0, 0,
0 , 0, mat22,mat32,
0 , 0, 1, 0
};
return Matrix<T,4,4>(data);
}
然后将其传递给执行以下操作的顶点处理:
printf("Vertex inital:");vert.Print();
vert = vert* m_ModelMatrix;
printf("Vertex model:");vert.Print();
vert = vert* m_ProjectionMatrix;
printf("Vertex projection:");vert.Print();
其输出是(对于随机选择的顶点):
Vertex inital:(1.000000,0.000000,-1.000000,1.000000)
Vertex model:(-1.900000,-2.300000,2.599999,1.000000)
Vertex projection:(-3.669604,-5.552692,2.405004,2.599999)
上面的顶点对应这个三角形中的一个顶点:
我的问题是投影矩阵似乎完全错误。当我增加 Z 平移时,三角形沿对角线向右上角 移动,同时看起来更小,当我减小 Z 值时,三角形移动斜向左下角,同时显得更大。有没有其他人遇到过这个问题?
作为参考,我对vector*matrix操作的实现:
template<typename T,unsigned int length>
Vector<T,length> Vector<T,length>::operator* (const Matrix<T,length,length> & matrix) const
{
T temp[length];
memset(temp,0,length*sizeof(T));
const T * matrixData = matrix.GetData();
//For each row in the matrix & in the returned vector...
for(unsigned int iRow = 0; iRow < length; ++iRow)
{
//For each column in this vector & matrix...
for(unsigned int iColumn = 0; iColumn < length; ++iColumn)
{
temp[iRow] += m_Data[iColumn]*matrixData[iRow*length + iColumn];
}
}
return Vector<T,length>(temp);
}
【问题讨论】:
-
为什么不直接使用glm 而不是从头开始编写所有内容?
-
投影(剪辑空间)顶点不是您在屏幕截图中显示的内容。坐标
(-3.669604,-5.552692,2.405004,2.599999)实际上在您的视口之外(因此,这个三角形的一部分应该被剪裁)——您可以告诉这一点,因为 X 和 Y 都是 -2.599999 在这个案子)。听起来你也忘了除以 W,这是透视缩放的原因。 -
@Davors72:是的,但是如果您确实有一个有效的视口变换,那么该三角形将在左下方。只要看看剪辑空间坐标,我就可以告诉你很多。
(-1.41, -2.136, 0.925)远远超出标准化设备坐标范围。 -
@Davors72:假设一切都按列优先顺序排列,这实际上看起来是正确的。但是您的投影矩阵是行优先的。您是否尝试过转置视口矩阵?
-
我不知道出了什么问题。我真正能说的是,如果你想模仿 OpenGL,你正在做的一些事情实际上更像 D3D 而不是 OpenGL:行主矩阵,NDC Z 应该从 -1 到 1,而不是 0到 1(正如您的视口矩阵所建议的那样),传统的 OpenGL 投影矩阵具有 m23 = -1(这会翻转 Z 轴并将右手视图空间更改为左手剪辑空间)。
标签: c++ opengl math matrix projection