C++ GLSL-SSAO:在获取深度位置时获取不需要的结果

C++ GLSL-SSAO:在获取深度位置时获取不需要的结果,c++,opengl,glsl,post-processing,ssao,C++,Opengl,Glsl,Post Processing,Ssao,我正在尝试基于本教程实现SSAO:。我似乎不明白如何实现这一点,我一直在我的片段着色器中得到不想要的结果 首先,我将着色器设置为传入深度缓冲区、摄影机的投影矩阵和4x4噪波纹理。ssao内核已经初始化并传递到着色器中。我还从深度缓冲区中采样法线 编辑:起初我认为我获取的深度位置不正确,所以我添加了一个名为positionFromDepth的新函数,但它似乎仍然不起作用 我的片段着色器: uniform sampler2D uDepthBuffer; uniform sampler2D uNois

我正在尝试基于本教程实现SSAO:。我似乎不明白如何实现这一点,我一直在我的片段着色器中得到不想要的结果

首先,我将着色器设置为传入深度缓冲区、摄影机的投影矩阵和4x4噪波纹理。ssao内核已经初始化并传递到着色器中。我还从深度缓冲区中采样法线

编辑:起初我认为我获取的深度位置不正确,所以我添加了一个名为positionFromDepth的新函数,但它似乎仍然不起作用

我的片段着色器:

uniform sampler2D uDepthBuffer;
uniform sampler2D uNoiseTexture;

uniform mat4 uProjection; // camera's projection matrix
uniform mat4 uInverseMatrix; // inverse of projection matrix
uniform vec2 uNoiseScale; // vec2(1024.0 / 4.0, 768.0 / 4.0)

const int MAX_KERNEL_SIZE = 128;

uniform int uSampleKernelSize;
uniform vec3 uSampleKernel[MAX_KERNEL_SIZE];

uniform float uRadius;

const float zNear = 0.1;
const float zFar = 2579.5671;

float linearizeDepth(float near, float far, float depth) {
    return 2.0 * near / (far + near - depth * (far - near));
}

vec3 positionFromDepth(vec2 texcoords) {
    float d = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords).r);
    vec4 pos = uInverseMatrix * vec4(texcoords.x * 2.0 - 1.0,
                                     texcoords.y * 2.0 - 1.0,
                                     d * 2.0 - 1.0, 1.0);

    pos.xyz /= pos.w;

    return pos.xyz;
}

vec3 normal_from_depth(float depth, vec2 texcoords) {
  const vec2 offset1 = vec2(0.0, 0.001);
  const vec2 offset2 = vec2(0.001, 0.0);

  float depth1 = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords + offset1).r);
  float depth2 = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords + offset2).r);

  vec3 p1 = vec3(offset1, depth1 - depth);
  vec3 p2 = vec3(offset2, depth2 - depth);

  vec3 normal = cross(p1, p2);
  normal.z = -normal.z;

  return normalize(normal);
}

void main() {
    vec2 texcoord = gl_TexCoord[0].st;

    vec3 origin = positionFromDepth(texcoord);

    float d = texture2D(uDepthBuffer, texcoord).r;
    vec3 normal = normal_from_depth(linearizeDepth(zNear, zFar, d), texcoord) * 2.0 - 1.0;
    normal = normalize(normal);

    vec3 rvec = texture2D(uNoiseTexture, texcoord * uNoiseScale).rgb * 2.0 - 1.0;
    vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
    vec3 bitangent = cross(normal, tangent);
    mat3 tbn = mat3(tangent, bitangent, normal);

    float occlusion = 0.0;

    for(int i = 0; i < uSampleKernelSize; i++) {
        vec3 sample = tbn * uSampleKernel[i];
        sample = sample * uRadius + origin.xyz;

        vec4 offset = vec4(sample, 1.0);
        offset = uProjection * offset;
        offset.xy /= offset.w;
        offset.xy = offset.xy * 0.5 + 0.5;

        float sampleDepth = positionFromDepth(offset.xy).z;
        occlusion += (sampleDepth <= sample.z ? 1.0 : 0.0);
    }

    occlusion = 1.0 - (occlusion / float(uSampleKernelSize));
    gl_FragColor = vec4(pow(occlusion, 4.0));
}
uniform-sampler-2d-uDepthBuffer;
纹理均匀;
一致mat4反射;//摄像机投影矩阵
均匀mat4 uInverseMatrix;//投影矩阵的逆
统一的vec2比例;//vec2(1024.0/4.0768.0/4.0)
常量int MAX_KERNEL_SIZE=128;
统一的int-uSampleKernelSize;
统一vec3 USAMPLECRENELL[最大内核大小];
均匀浮动脐尿管;
常数浮点数zNear=0.1;
常数浮点zFar=2579.5671;
浮动线性深度(浮动近、浮动远、浮动深度){
返回2.0*近/(远+近深度*(远-近));
}
vec3位置自深度(vec2 texcoords){
float d=线性化深度(zNear、zFar、texture2D(uDepthBuffer、texcoords).r);
vec4 pos=uInverseMatrix*vec4(texcoords.x*2.0-1.0,
texcoords.y*2.0-1.0,
d*2.0-1.0,1.0);
位置xyz/=位置w;
返回位置xyz;
}
vec3正常\u自\u深度(浮动深度,vec2 texcoords){
常数vec2 offset1=vec2(0.0,0.001);
常数vec2 offset2=vec2(0.001,0.0);
浮动深度1=线性化深度(zNear、zFar、texture2D(uDepthBuffer、texcoords+offset1).r);
浮动深度2=线性化深度(zNear、zFar、texture2D(uDepthBuffer、texcoords+offset2).r);
vec3 p1=vec3(偏移量1,深度1-深度);
vec3 p2=vec3(偏移量2,深度2-深度);
vec3正常=交叉(p1,p2);
normal.z=-normal.z;
返回正常化(正常);
}
void main(){
vec2 texcoord=gl_texcoord[0].st;
vec3原点=位置自深度(texcoord);
浮动d=纹理2D(uDepthBuffer,texcoord).r;
vec3 normal=从深度(线性化深度(zNear,zFar,d),texcoord)*2.0-1.0;
正常=正常化(正常);
vec3 rvec=纹理2D(无纹理,texcoord*无纹理比例)。rgb*2.0-1.0;
vec3切线=规格化(rvec-法线*点(rvec,法线));
vec3双切线=交叉(法线、切线);
mat3 tbn=mat3(切线、双切线、法线);
浮动闭塞=0.0;
for(int i=0;i遮挡+=(SAMPraceDe>P>这里有两件事要考虑。你已经用原来不同的代码替换了原来的代码>线性化深度> /代码>方程。原来的<代码>线性化深度> /代码>函数是基于此的。

请注意,如果您尝试根据此公式推导函数,您将看到
linearizeDepth
函数返回的不仅仅是Z,而是Z的倒数

我不能说这会在多大程度上影响SSAO算法,但考虑到我自己从研究代码中学到的知识,我会非常小心地修补我不完全理解的部分等式。本质上,我不确定代码是否会继续使用它


具体地说,我相信在这个例子中,
linelinearedepth
的目的不是在z轴上均匀地分布明暗(我相信,这就是你在这里所做的),而是廉价地取消投影z'坐标。

这甚至不应该编译,
main(…)中的第三个非空白行
引用了一个变量
d
,该变量在该范围内不存在。很抱歉,上次更新着色器时我输入了一个错误。重新添加了缺少的行。从外观上看,
d
的值在传递给该函数之前需要进行线性化。看起来我忘记调用linelinearedept了h函数。虽然它似乎仍然无法解决问题。也许是线性深度函数本身错误地计算了线性化深度?这是一种可能性,但我指的是您对问题中代码所做的更改--
d
未线性化。