SSAO 구현으로 원하는 결과를 얻지 못함


12

지연 렌더링을 구현 한 후이 Tutorial을 사용하여 SSAO 구현으로 운을 시험해 보았습니다 . 불행히도 SSAO와 같은 것을 얻지 못했습니다. 아래에서 내 결과를 볼 수 있습니다.

실패한 사오 시도

이상한 패턴 형성이 있고 필요한 곳에 (즉, 오브젝트 사이와지면에) 폐색 음영이없는 것을 볼 수 있습니다. 내가 구현 한 셰이더는 다음과 같습니다.


#VS
#version 330 core

uniform mat4 invProjMatrix;

layout(location = 0) in vec3 in_Position;
layout(location = 2) in vec2 in_TexCoord;

noperspective out vec2 pass_TexCoord;
smooth out vec3 viewRay;

void main(void){
    pass_TexCoord = in_TexCoord;
    viewRay = (invProjMatrix * vec4(in_Position, 1.0)).xyz;
    gl_Position = vec4(in_Position, 1.0);
}

#FS
#version 330 core

uniform sampler2D DepthMap;
uniform sampler2D NormalMap;
uniform sampler2D noise;

uniform vec2 projAB;
uniform ivec3 noiseScale_kernelSize;
uniform vec3 kernel[16];
uniform float RADIUS;
uniform mat4 projectionMatrix;

noperspective in vec2 pass_TexCoord;
smooth in vec3 viewRay;

layout(location = 0) out float out_AO;

vec3 CalcPosition(void){
    float depth = texture(DepthMap, pass_TexCoord).r;
    float linearDepth = projAB.y / (depth - projAB.x);
    vec3 ray = normalize(viewRay);
    ray = ray / ray.z;
    return linearDepth * ray;
}

mat3 CalcRMatrix(vec3 normal, vec2 texcoord){
    ivec2 noiseScale = noiseScale_kernelSize.xy;
    vec3 rvec = texture(noise, texcoord * noiseScale).xyz;
    vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
    vec3 bitangent = cross(normal, tangent);

    return mat3(tangent, bitangent, normal);
}

void main(void){

    vec2 TexCoord = pass_TexCoord;
    vec3 Position = CalcPosition();
    vec3 Normal = normalize(texture(NormalMap, TexCoord).xyz);

    mat3 RotationMatrix = CalcRMatrix(Normal, TexCoord);

    int kernelSize = noiseScale_kernelSize.z;

    float occlusion = 0.0;

    for(int i = 0; i < kernelSize; i++){
        // Get sample position
        vec3 sample = RotationMatrix * kernel[i];
        sample = sample * RADIUS + Position;
        // Project and bias sample position to get its texture coordinates
        vec4 offset = projectionMatrix * vec4(sample, 1.0);
        offset.xy /= offset.w;
        offset.xy = offset.xy * 0.5 + 0.5;
        // Get sample depth
        float sample_depth = texture(DepthMap, offset.xy).r;
        float linearDepth = projAB.y / (sample_depth - projAB.x);
        if(abs(Position.z - linearDepth ) < RADIUS){
            occlusion += (linearDepth <= sample.z) ? 1.0 : 0.0;
        }
    }
    out_AO = 1.0 - (occlusion / kernelSize);
}

전체 화면 쿼드를 그리고 깊이 및 법선 텍스처를 전달합니다. 노멀은 RGBA16F에 있으며 알파 채널은 블러 패스에서 AO 팩터를 위해 예약되어 있습니다. 비선형 깊이 버퍼 (32F)에 깊이를 저장하고 다음을 사용하여 선형 깊이를 복구합니다.


float linearDepth = projAB.y / (depth - projAB.x);

여기서는 projAB.y다음과 같이 계산됩니다.

여기에 이미지 설명을 입력하십시오

projAB.x같은 :

여기에 이미지 설명을 입력하십시오

이들은 glm :: perspective (gluperspective) 매트릭스에서 파생됩니다. z_n 및 z_f는 근거리 및 원거리 클립 거리입니다.

상단에 게시 된 링크에 설명 된대로이 방법은 중앙에 가까운 분포가 더 높은 반구에서 샘플을 만듭니다. 그런 다음 텍스처에서 임의의 벡터를 사용하여 반구를 Z 방향으로 무작위로 회전하고 마지막으로 주어진 픽셀에서 법선을 따라 방향을 지정합니다. 결과에 노이즈가 발생하기 때문에 SSAO 패스 다음에 흐림 패스가 있습니다.

어쨌든, 내 위치 재구성은 똑같이 시도했지만 위치가 재구성되지 않고 텍스처에서 전달되었으므로 잘못된 것 같습니다.

또한 Radius, 노이즈 텍스처 크기 및 샘플 수 및 다양한 종류의 텍스처 형식을 가지고 놀아 보았습니다. Radius를 변경할 때 어떤 이유로 든 변경되지 않습니다.

누구든지 제안이 있습니까? 무엇이 잘못 될 수 있습니까?


블러는 별도의 패스 여야한다고 생각합니다. 블러없이 셰이더의 스크린 샷을 게시 할 수 있습니까?
knight666

블러 패스는 별개이며 프리 블러 스크린 샷을 확인할 수 있습니다 .
Grieverheart 2016 년

답변:


6

나는 문제를 발견했다. 정말 바보 같은 실수였습니다. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);정확한 깊이 값을 얻기 위해 지정해야 한다는 것을 몰랐으므로 깊이 값을 샘플링하지 않았습니다. 이제 멋진 SSAO 효과를 얻습니다.

여기에 이미지 설명을 입력하십시오


사람들이 당신이 당신의 해결책을 찾았 음을 알 수 있도록 이것을 정답으로 표시하십시오 : P
SomeGuy

예, 불행히도 내 답변을 올바른 것으로 표시 할 수 있도록 하루를 기다려야합니다.
Grieverheart 2016 년

내 실수는 타임 스탬프를 확인하지 않았습니다.
SomeGuy 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.