link : https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping
Rendering shadows
적절하게 생성된 깊이 맵을 사용해 실제 그림자를 생성 할 수 있다. 조각이 그림자에 있는지를 확인하는 코드는 조각 쉐이더에서 (분명히)
실행되지만, 우리는 정점 쉐이더에서 light-space 변환을 수행한다:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out VS_OUT {
vec3 FragPos;
vec3 Normal;
vec2 TexCoords;
vec4 FragPosLightSpace;
} vs_out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
vs_out.TexCoords = aTexCoords;
vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
여기서 새로 추가 된 것은 FragPosLightSpace라는 추가 출력 벡터이다. 우리는 동일한 lightSpaceMatrix를 가져와서 세계 공간 정점 위치를
밝은 공간으로 변환한다. 정점 쉐이더는 일반적으로 변환된 world-space 정점 위치 vs_out.FragPos와 변환된 light-space vs_out.FragPosLightSpace를
조각 쉐이더에 전달한다.
장면 렌더링에 사용할 조각 쉐이더는 Blinn-Phong 조명 모델을 사용한다. 조각 쉐이더 내에서 우리는 조각이 그림자에 있을 때 1.0이거나
그림자에 없을 때 0.0 인 그림자 값을 계산한다. 결과로 생성되는 확산 및 반사 색상에 이 그림자 구성 요소가 곱해진다. 빛의 산란으로 인해
그림자가 거의 완전히 어두워지지 않기 때문에 그림자 곱셈에서 주변 색상을 벗어나지 않는다.
#version 330 core
out vec4 FragColor;
in VS_OUT {
vec3 FragPos;
vec3 Normal;
vec2 TexCoords;
vec4 FragPosLightSpace;
} fs_in;
uniform sampler2D diffuseTexture;
uniform sampler2D shadowMap;
uniform vec3 lightPos;
uniform vec3 viewPos;
float ShadowCalculation(vec4 fragPosLightSpace)
{
[...]
}
void main()
{
vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
vec3 normal = normalize(fs_in.Normal);
vec3 lightColor = vec3(1.0);
// ambient
vec3 ambient = 0.15 * color;
// diffuse
vec3 lightDir = normalize(lightPos - fs_in.FragPos);
float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * lightColor;
// specular
vec3 viewDir = normalize(viewPos - fs_in.FragPos);
float spec = 0.0;
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
vec3 specular = spec * lightColor;
// calculate shadow
float shadow = ShadowCalculation(fs_in.FragPosLightSpace);
vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;
FragColor = vec4(lighting, 1.0);
}
조각 쉐이더는 고급 조명 튜토리얼에서 사용한 것의 사본이지만 그림자 계산이 추가되었다. 우리는 대부분의 그림자 작업을 수행하는
ShadowCalculation 함수를 선언했다. 조각 쉐이더의 종단에서 확산 및 반사 기여에 그림자 성분의 역행렬을 곱해 조각이 그림자에 없는
양을 늘린다. 이 조각 쉐이더는 첫 번째 렌더 패스에서 생성된 깊이 맵과 light-space 조각 위치를 추가 입력으로 사용한다.
조각이 그림자에 있는지 여부를 확인하기 위해 수행해야 할 첫 번째 작업은 클립 영역의 밝은 공간 조각 위치를 표준화된 장치 좌표로
변환하는 것이다. 정점 쉐이더의 gl_position에 클립 공간 정점 위치를 출력 할 때, OpenGL은 자동으로 원근법 나누기를 한다. x,y,z 구성 요소를
벡터의 w 구성 요소로 나눠서 [-w,w] 범위의 클립 공간 좌표를 [-1,1]로 변환한다. 클립 공간 FragPosLightSpace가 gl_Position을 통해 조각 쉐이더에
전달되지 않기 때문에 우리는 이 관점을 스스로 분리해야한다:
float ShadowCalculation(vec4 fragPosLightSpace)
{
// perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
[...]
}
이것은 [-1,1]의 범위에서 조각의 light-space 위치를 반환한다.
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float shadow = currentDepth > closestDepth ? 1.0 : 0.0;
float ShadowCalculation(vec4 fragPosLightSpace)
{
// perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(shadowMap, projCoords.xy).r;
// get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
// check whether current frag pos is in shadow
float shadow = currentDepth > closestDepth ? 1.0 : 0.0;
return shadow;
}
당신이 일을 제대로 했다면 바닥과 큐브에 그림자를 보아야한다. (인공물이 많다)
'Game > Graphics' 카테고리의 다른 글
Learn OpenGL - Advanced Lighting : Point Shadows (1) (0) | 2018.09.27 |
---|---|
Learn OpenGL - Advanced Lighting : Shadow Mapping (3) (0) | 2018.09.27 |
Learn OpenGL - Advanced Lighting : Shadow Mapping (1) (0) | 2018.09.19 |
Learn OpenGL - Advanced Lighting : Gamma Correction (0) | 2018.09.17 |
Learn OpenGL - Advanced Lighting : Advanced Lighting (0) | 2018.09.17 |