我尝试根据此处的R5演示实施屏幕空间环境遮挡(SSAO):http://blog.nextrevision.com/?p=76
事实上,我尝试调整他们的SSAO - 线性着色器以适应我自己的小引擎。
1)我计算View Space曲面法线和线性深度值。 我使用以下着色器将它们存储在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和线性Depht als Alpha。
我的第二个纹理,随机正常纹理,如下所示: http://www.gamerendering.com/wp-content/uploads/noise.png
我使用几乎完全相同的实现,但我的结果是错误的。
在详细介绍之前,我想首先澄清一些问题:
1)ssao着色器使用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;
正确还是错?
答案 0 :(得分:11)
你的正常纹理似乎错了。我的猜测是你的vmtInvTranspMatrix
是一个模型视图矩阵。但它应该是模型 - 视图 - 投影矩阵(注意您需要屏幕空间法线,而不是视图空间法线)。深度计算是正确的。
我已经实现了一次SSAO,普通纹理看起来像这样(注意这里没有蓝色):
1)ssao着色器使用projectionMatrix和它的逆矩阵。 由于它是通过正投影渲染到对准四边形的屏幕上的后处理效果,因此投影矩阵是正交矩阵。正确还是错?
如果你的意思是你要渲染四边形以计算实际SSAO的第二遍,是的。您可以完全避免正交投影矩阵的乘法。如果渲染屏幕四边形的[x,y]尺寸范围从-1到1,您可以使用非常简单的顶点着色器:
const vec2 madd=vec2(0.5,0.5);
void main(void)
{
gl_Position = vec4(in_Position, -1.0, 1.0);
texcoord = in_Position.xy * madd + madd;
}
不,那不会引起问题。这是一种常见的做法。2)具有组合的法线和深度纹理而不是两个单独的纹理 的。