我尝试基于此处找到的R5 Demo来实现基于屏幕空间的环境光遮蔽(Screen Space Ambient Occlusion,SSAO):http://blog.nextrevision.com/?p=76
事实上,我试图将他们的SSAO-Linear着色器改编适应我的引擎。
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
与原版不同的是,我只使用了两个输入纹理,因为我的一个纹理将法线存储为RGB和线性深度为Alpha。
我的第二个纹理——随机法线纹理,看起来像这样:http://www.gamerendering.com/wp-content/uploads/noise.png
我使用的几乎完全相同的实现,但结果却是错误的。
在进一步讨论之前,我想先澄清一些问题:
1) ssao着色器使用投影矩阵及其逆矩阵。
由于它是通过正交投影渲染到屏幕对齐的四边形上的后处理效果,所以投影矩阵是正交矩阵。正确还是错误?
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;
正确还是错误?