【问题标题】:Projection matrix implementation投影矩阵实现
【发布时间】: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


【解决方案1】:

所以我在休息一段时间后回到这个项目,我意识到我的投影划分(又名 /w)只是划分 xyz 坐标。因此,当我应用屏幕空间矩阵时,转换列正乘以“大于一”的 W 值,导致三角形随着 Z 减小而移动到右上角。

【讨论】:

    猜你喜欢
    • 2012-03-27
    • 1970-01-01
    • 2015-04-11
    • 2015-11-01
    • 2013-08-03
    • 1970-01-01
    • 2019-12-14
    • 2019-03-05
    • 2011-08-31
    相关资源
    最近更新 更多