CPU与GPU MVP矩阵的浮点精度

时间:2015-07-17 09:09:14

标签: opengl math floating-accuracy glm-math shadow-mapping

我有一个问题,我认为是由于CPU上的浮点错误。

我目前正在制作阴影贴图,起初我在GPU上进行了MVP计算,例如

layout(location = 0) in vec3 inPos;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

void main(void)
{
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(inPos, 1.0);
}

这显然不是所有着色器代码, 但这些计算结果如下:

enter image description here

然后我想稍微优化代码并将MVP计算移动到CPU并将其作为统一传递给着色器,如下所示:

uniform mat4 MVP;

layout(location = 0) in vec3 inPos;

void main(void)
{
gl_Position = MVP * vec4(inPos, 1.0);
}

结果如下:

enter image description here

我一直在看我的CPU矩阵乘法几个小时,所以我> 90%确定那里的一切都是正确的。

我给一个带有set-functions的矩阵的容器类,并用一个getter检索它们。

void setModelMatrix(const glm::mat4& inModelMatrix){mModelMatrix = inModelMatrix;};
void setViewMatrix(const glm::mat4& inVewMatrix) {mViewMatrix = inVewMatrix;};
void setProjectionMatrix(const glm::mat4& inProjectionMatrix){mProjectionMatrix = inProjectionMatrix;};

//Calculates the MVP matrix and returns it
glm::mat4 getMVPMatrix() {
    return (mProjectionMatrix * mViewMatrix * mModelMatrix);
}

那么..关于可能出现什么问题的任何想法?它可能是浮点错误吗? 感谢所有回复!

1 个答案:

答案 0 :(得分:0)

这些绝对不是转换矩阵的精度问题;任何与此相关的问题都会显示为(阴影或对象的)错位,而不是渲染工件。

这看起来更像是缓冲区采样分辨率错误;你的变换矩阵在这里可能有问题,但不是由于矩阵的精度有限,而是因为当光距离通过投影矩阵时,你选择将所有深度信息压缩到很小的范围内。通常,您希望任何 投影矩阵的near参数尽可能大;由传统投影矩阵生成的深度缓冲值是非线性的(它们遵循1 / x关系),因此如果近似非常小,则大多数可用数量范围得到非常接近近剪裁平面的压缩。如果在阴影贴图中使用这样生成的缓冲区,则在反转深度压缩后,您将以这种看似随机的方式展开深度位。

两种可能的解决方案:

  • 使用更好的平衡投影矩阵进行光通过。

  • 不要将光通过(非线性)深度缓冲区用于阴影贴图,而是通过"手动生成线性深度图像"写'绝对"世界空间单位中的距离进入阴影贴图,明确地在光通道片段着色器中显示(您可以将这些值写入深度缓冲区,但这通常会带来一些性能问题)。