셰이더를 사용하여 OpenGL에서 처음으로 기본 그림자 매핑을 구현했으며 몇 가지 문제에 직면하고 있습니다. 아래에서 렌더링 된 장면의 예를 볼 수 있습니다.
내가 따르는 섀도 매핑의 과정은 라이트 렌더링 관점에서 뷰 매트릭스를 사용하고 일반 렌더링에 사용되는 투영 및 모델 매트릭스를 사용하여 장면을 프레임 버퍼로 렌더링하는 것입니다.
두 번째 단계에서는 위의 MVP 매트릭스를 조명 시점에서 정점 셰이더로 전송하여 위치를 조명 공간으로 변환합니다. 프래그먼트 셰이더는 원근 분할을 수행하고 위치를 텍스처 좌표로 변경합니다.
여기 내 버텍스 쉐이더가 있습니다.
#version 150 core
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 MVPMatrix;
uniform mat4 lightMVP;
uniform float scale;
in vec3 in_Position;
in vec3 in_Normal;
in vec2 in_TexCoord;
smooth out vec3 pass_Normal;
smooth out vec3 pass_Position;
smooth out vec2 TexCoord;
smooth out vec4 lightspace_Position;
void main(void){
pass_Normal = NormalMatrix * in_Normal;
pass_Position = (ModelViewMatrix * vec4(scale * in_Position, 1.0)).xyz;
lightspace_Position = lightMVP * vec4(scale * in_Position, 1.0);
TexCoord = in_TexCoord;
gl_Position = MVPMatrix * vec4(scale * in_Position, 1.0);
}
그리고 내 조각 쉐이더
#version 150 core
struct Light{
vec3 direction;
};
uniform Light light;
uniform sampler2D inSampler;
uniform sampler2D inShadowMap;
smooth in vec3 pass_Normal;
smooth in vec3 pass_Position;
smooth in vec2 TexCoord;
smooth in vec4 lightspace_Position;
out vec4 out_Color;
float CalcShadowFactor(vec4 lightspace_Position){
vec3 ProjectionCoords = lightspace_Position.xyz / lightspace_Position.w;
vec2 UVCoords;
UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;
float Depth = texture(inShadowMap, UVCoords).x;
if(Depth < (ProjectionCoords.z + 0.001)) return 0.5;
else return 1.0;
}
void main(void){
vec3 Normal = normalize(pass_Normal);
vec3 light_Direction = -normalize(light.direction);
vec3 camera_Direction = normalize(-pass_Position);
vec3 half_vector = normalize(camera_Direction + light_Direction);
float diffuse = max(0.2, dot(Normal, light_Direction));
vec3 temp_Color = diffuse * vec3(1.0);
float specular = max( 0.0, dot( Normal, half_vector) );
float shadowFactor = CalcShadowFactor(lightspace_Position);
if(diffuse != 0 && shadowFactor > 0.5){
float fspecular = pow(specular, 128.0);
temp_Color += fspecular;
}
out_Color = vec4(shadowFactor * texture(inSampler, TexCoord).xyz * temp_Color, 1.0);
}
그림에서 볼 수 있듯이 문제 중 하나는 자체 그림자입니다. 상자에는 자체 그림자가 있습니다. 내가 시도한 것은 다각형 오프셋 (즉, glEnable (POLYGON_OFFSET_FILL), glPolygonOffset (GLfloat, GLfloat))을 활성화하는 것이지만 많이 변경되지 않았습니다. 프래그먼트 셰이더에서 볼 수 있듯이 정적 오프셋 값은 0.001이지만 빛의 거리에 따라 값을 변경하여 더 바람직한 효과를 얻어야하므로 매우 유용하지 않습니다. 또한 프레임 버퍼로 렌더링 할 때 전면 컬링을 사용해 보았습니다.
다른 문제는 라이트의 뷰 프러스 텀 외부의 픽셀이 음영 처리된다는 것입니다. 그림자를 드리울 수있는 유일한 물체는 상자입니다. 더 적절한 투영과 뷰 매트릭스를 선택해야하지만 그 방법을 잘 모르겠습니다. 직교 투영법을 선택해야하는 일반적인 관행은 무엇입니까?
인터넷 검색에서 나는 이러한 문제가 사소한 것이 아니라는 것을 이해합니다. 누구든지 이러한 문제에 대한 솔루션을 쉽게 구현할 수 있습니까? 추가 정보를 제공해 주시겠습니까?
내 코드에 대한 자세한 정보가 필요하면 문의하십시오.
다음 은 상자 클로즈업의 그림자 매핑 유무에 대한 비교입니다. 셀프 섀도 잉이 더 잘 보입니다.