我尝试根据此处找到的 R5 演示实现屏幕空间环境光遮蔽 (SSAO):http: //blog.nextrevision.com/ ?p=76
事实上,我尝试调整他们的 SSAO - 线性着色器以适应我自己的小引擎。
1)我计算视图空间表面法线和线性深度值。 我使用以下着色器将它们存储在 RGBA 纹理中:
顶点:
varNormalVS = normalize(vec3(vmtInvTranspMatrix * vertexNormal));
depth = (modelViewMatrix * vertexPosition).z;
depth = (-depth-nearPlane)/(farPlane-nearPlane);
gl_Position = pvmtMatrix * vertexPosition;
分段:
gl_FragColor = vec4(varNormalVS.x,varNormalVS.y,varNormalVS.z,depth)
对于我的线性深度计算,我参考了:http ://www.gamerendering.com/2008/09/28/linear-depth-texture/
这是正确的吗?纹理似乎是正确的,但也许不是?
2) 实际的 SSAO 实现: 如上所述,原文可以在这里找到:http: //blog.nextrevision.com/ ?p=76
或更快:在pastebin http://pastebin.com/KaGEYexK
与原始纹理相比,我只使用 2 个输入纹理,因为我的一个纹理同时存储了 RGB 和线性深度作为 Alpha 的法线。
我的第二个纹理,随机正常纹理,如下所示: http ://www.gamerendering.com/wp-content/uploads/noise.png
我使用几乎完全相同的实现,但我的结果是错误的。
在详细介绍之前,我想先澄清一些问题:
1)ssao着色器使用projectionMatrix,它是逆矩阵。
由于它是通过正交投影渲染到屏幕对齐四边形上的后处理效果,因此 projectionMatrix 是正交矩阵。正确还是错误?
2) 具有组合的法线和深度纹理,而不是两个单独的纹理。
在我看来,这是 R5 实现与我的实现尝试之间的最大区别。我认为这应该不是一个大问题,但是,由于不同的深度纹理,这最容易引起问题。
请注意 R5_clipRange 看起来像这样
vec4 R5_clipRange = vec4(nearPlane, farPlane, nearPlane * farPlane, farPlane - nearPlane);
原来的:
float GetDistance (in vec2 texCoord)
{
//return texture2D(R5_texture0, texCoord).r * R5_clipRange.w;
const vec4 bitSh = vec4(1.0 / 16777216.0, 1.0 / 65535.0, 1.0 / 256.0, 1.0);
return dot(texture2D(R5_texture0, texCoord), bitSh) * R5_clipRange.w;
}
我不得不承认我不理解代码片段。我的深度存储在我的纹理的 alpha 中,我认为这样做就足够了
return texture2D(texSampler0, texCoord).a * R5_clipRange.w;
正确还是错误?