我一直在 OpenGL 中工作 SSAO。我决定在 OpenGL 中为我的延迟渲染器实现本教程中的 SSAO。不幸的是,我一直无法让它正常工作。SSAO 变暗的区域会根据相机的位置而发生很大变化。我知道当相机移动时 SSAO 的输出可能会有一些变化,但这比我在其他 SSAO 实现中观察到的要大得多。
这是片段着色器代码
void main() {
vec3 origin = positionFromDepth(texture2D(gDepth, samplePosition));
vec3 normal = texture2D(gNormal, samplePosition).xyz; //multiplying this
//by 2 and subtracting 1 doesn't seem to help
vec2 random = getRandom(samplePosition);
float radius = uRadius/origin.z;
float occlusion = 0.0;
int iterations = samples/4;
for (int i = 0; i<iterations; i++) {
vec2 coord1 = reflect(kernel[i], random)*radius;
vec2 coord2 = vec2(coord1.x*0.707 - coord1.y*0.707, coord1.x*0.707 + coord1.y*0.707);
occlusion += occlude(samplePosition, coord1 * 0.25, origin, normal);
occlusion += occlude(samplePosition, coord2 * 0.50, origin, normal);
occlusion += occlude(samplePosition, coord1 * 0.75, origin, normal);
occlusion += occlude(samplePosition, coord2, origin, normal);
}
color = vec4(origin, 1);
}
positionFromDepth()
功能:
vec3 positionFromDepth(float depth) {
float near = frustrumData.x;
float far = frustrumData.y;
float right = frustrumData.z;
float top = frustrumData.w;
vec2 ndc;
vec3 eye;
eye.z = near * far / ((depth * (far - near)) - far);
ndc.x = ((gl_FragCoord.x/buffersize.x) - 0.5) * 2.0;
ndc.y = ((gl_FragCoord.y/buffersize.y) - 0.5) * 2.0;
eye.x = (-ndc.x * eye.z) * right/near;
eye.y = (-ndc.y * eye.z) * top/near;
return eye;
}
和occlude()
功能:
float occlude(vec2 uv, vec2 offsetUV, vec3 origin, vec3 normal) {
vec3 diff = positionFromDepth(texture2D(gDepth,(uv+offsetUV)))-origin;
vec3 vec = normalize(diff);
float dist = length(diff)/scale;
return max(0.0,dot(normal,vec)-bias)*(1.0/(1.0+dist))*intensity;
}
我感觉问题可能出在positionFromDepth()
函数中,除了我对渲染器的照明阶段使用相同的代码,效果很好(我认为)。我已经检查了这段代码一千次,但没有发现任何明显错误的地方。我尝试了 、 、 和 的各种值bias
,radius
但这intenisty
似乎scale
不是问题。我担心我的法线或位置是错误的,所以这里有一些它们的屏幕截图:
重建位置: 和正常缓冲区:
我将包含遮挡缓冲区的图像,但问题仅在相机移动时才最明显,而图像无助于显示。
有谁知道这里有什么问题?