지연 렌더링을 구현 한 후이 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를 변경할 때 어떤 이유로 든 변경되지 않습니다.
누구든지 제안이 있습니까? 무엇이 잘못 될 수 있습니까?