2013-12-12 2 views
2

OpenGL API로 분산 그림자 맵 기술을 구현하려고합니다. 나는 튜토리얼 (Fabien Sanglard의 Soft Shadows with VSM)을 사용하여 매 단계마다 따라했지만, 그림자 맵은 이상하게 보였다. 내가 알아 차 렸던 주요한 점은 내가 빛 (원근감) 투영 행렬의 클리핑 평면 근처에서 바뀌면 이상하게 보입니다. 가 (이 결과는 좋은으로 간주)OpenGL 분산 그림자 매핑 반전 falloff

http://postimg.org/image/rupf6wqcx/ 클리핑 근처 1.0F에 보이는 그리고 여기 http://postimg.org/image/fox04z14z/

공지 빛의 위치는 동일하게 유지 0.1F 값에 얼마나 예를 들어

여기 있어요.

나는 결과가없는 3 일 동안 잘못 된 것을 찾으려고 노력해 왔습니다. 그걸 도와 주실 수 있습니까?

다음은 그림자 조각 셰이더 코드입니다.

in vec4 v_position; 
out vec4 color; 

void main() 
{ 
    float depth = v_position.z/v_position.w; 
    depth = depth * 0.5 + 0.5; 

    float dx = dFdx(depth); 
    float dy = dFdy(depth); 

    float moment1 = depth; 
    float moment2 = depth * depth - 0.25 * (dx * dx + dy * dy); 

    color = vec4(moment1, moment2, 0.0, 1.0); 
} 

그리고

in vec4 ShadowPosition; 
out vec4 outColor; 
uniform sampler2D shadowMap; 
vec4 sc; 

float chebyshevUpperBound(float distance) 
{ 
    float p = 0.0; 

    // We retrive the two moments previously stored (depth and depth*depth) 
    vec2 moments = texture2D(shadowMap, sc.xy).rg; 

    // Surface is fully lit. as the current fragment is before the light occluder 
    if (distance <= moments.x) 
     p = 1.0; 

    // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check 
    // How likely this pixel is to be lit (p_max) 
    float variance = moments.y - (moments.x * moments.x); 
    variance = max(variance, 0.00001); 

    float d = distance - moments.x; 
    float p_max = variance/(variance + d*d); 

    return max(p, p_max); 
} 

void main() 
{ 
    /* Shadow Mapping */ 
    vec3 pixColor = vec3(1.0, 1.0, 1.0); 
    sc = ShadowPosition/ShadowPosition.w; 
    sc = sc * 0.5 + 0.5; 
    float visibility = chebyshevUpperBound(sc.z); 
    outColor = vec4(visibility * pixColor, 1.0); 
} 

버텍스 쉐이더, 조명이나 MVP를 사용하여 뷰의 카메라 점에서 정점을 계산하기 때문에 아주 간단 행렬되어 렌더링 실제 패스 프래그먼트 쉐이더에서 그림자 매핑 부분을 내가 필요가 있다고 생각하지 말아 그들을 게시하십시오.

이 코드는 초기화하고 렌더링 할 수 있습니다 :

glEnable(GL_DEPTH_TEST); 
glDepthFunc(GL_LESS); 
glEnable(GL_CULL_FACE); 
glCullFace(GL_BACK); 

glGenFramebuffers(1, &FramebufferName); 

glGenTextures(1, &light_s.shadowBO); 
glBindTexture(GL_TEXTURE_2D, light_s.shadowBO); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1024, 1024, 0, GL_RGBA, GL_FLOAT, 0); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 

glGenTextures(1, &light_s.shadowBOZ); 
glBindTexture(GL_TEXTURE_2D, light_s.shadowBOZ); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 

glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, light_s.shadowBO, 0); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, light_s.shadowBOZ, 0); 

while (running) 
{ 
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    else 
    { 
     /* Shadow pass */ 
     glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); 
     glViewport(0, 0, 1024, 1024); 
     glDrawBuffer(GL_BACK); 
     glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 

     glUseProgram(theShadowProgram); 
     glEnableVertexAttribArray(svxposition); 

     glUniformMatrix4fv(spmatrix, 1, GL_FALSE, light_s.mProjection); 
     glUniformMatrix4fv(svmatrix, 1, GL_FALSE, light_s.mView); 
     glUniformMatrix4fv(smmatrix, 1, GL_FALSE, bunny_s.mModel); 

     glBindBuffer(GL_ARRAY_BUFFER, bunny_s.vertexBufferObject); 
     glVertexAttribPointer(svxposition, 3, GL_FLOAT, GL_FALSE, 0, NULL); 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunny_s.elementBufferObject); 
     glDrawElements(GL_TRIANGLES, bunny_s.elementBufferSize, GL_UNSIGNED_INT, NULL); 

     glBindBuffer(GL_ARRAY_BUFFER, vbplaneVert); 
     glVertexAttribPointer(svxposition, 3, GL_FLOAT, GL_FALSE, 0, NULL); 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbplaneElem); 
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL); 

     glDisableVertexAttribArray(svxposition); 

     /* Rendering pass */ 
     glBindFramebuffer(GL_FRAMEBUFFER, 0); 
     glViewport(0, 0, 1024, 768); 
     glDrawBuffer(GL_BACK); 
     glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 

     glUseProgram(theProgram); 
     glActiveTexture(GL_TEXTURE0); 
     glBindTexture(GL_TEXTURE_2D, light_s.shadowBO); 

     glEnableVertexAttribArray(vxposition); 
     glEnableVertexAttribArray(normals); 

     glUniformMatrix4fv(dpmatrix, 1, GL_FALSE, light_s.mProjection); 
     glUniformMatrix4fv(dvmatrix, 1, GL_FALSE, light_s.mView); 
     glUniformMatrix4fv(dbmatrix, 1, GL_FALSE, mDepthBias); 

     glUniformMatrix4fv(pmatrix, 1, GL_FALSE, camera_s.mProjection); 
     glUniformMatrix4fv(vmatrix, 1, GL_FALSE, camera_s.mView); 
     glUniformMatrix4fv(mmatrix, 1, GL_FALSE, bunny_s.mModel); 

     glUniform3f(campos, camera_s.x, camera_s.y, camera_s.z); 
     glUniform3f(lightpos, light_s.x, light_s.y, light_s.z); 

     glUniform1i(frsampler, 0); 

     glBindBuffer(GL_ARRAY_BUFFER, bunny_s.vertexBufferObject); 
     glVertexAttribPointer(vxposition, 3, GL_FLOAT, GL_FALSE, 0, NULL); 

     glBindBuffer(GL_ARRAY_BUFFER, bunny_s.normalBufferObject); 
     glVertexAttribPointer(normals, 3, GL_FLOAT, GL_FALSE, 0, NULL); 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunny_s.elementBufferObject); 
     glDrawElements(GL_TRIANGLES, bunny_s.elementBufferSize, GL_UNSIGNED_INT, NULL); 

     glBindBuffer(GL_ARRAY_BUFFER, vbplaneVert); 
     glVertexAttribPointer(vxposition, 3, GL_FLOAT, GL_FALSE, 0, NULL); 

     glBindBuffer(GL_ARRAY_BUFFER, vbplaneNorm); 
     glVertexAttribPointer(normals, 3, GL_FLOAT, GL_FALSE, 0, NULL); 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbplaneElem); 
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL); 

     glDisableVertexAttribArray(vxposition); 
     glDisableVertexAttribArray(normals); 
    } 
} 

이 최적화되어 있지 않습니다,하지만 지금 할 것입니다. 당신이 color.zw (BA) 이후 GL_RG32F 대신 GL_RGBA32F을 사용하는 경우

+0

코드 없이는 진단하기가 어려울 것입니다. 일부 게시 할 수 있습니까? –

+0

@ChrisMantle 일부 코드 샘플을 사용하여 제 질문을 편집했습니다. 도움이되기를 바랍니다. –

답변

2

당신은 절반에 shadowmap 저장 및 메모리 대역폭 요구 사항을 줄일 수 상수이다. 또한, 이 매우 천천히 변하는 것과 depth에 가까운 투시 투영법을 사용하여 가까운 평면에 가까이 갈 수 있다는 사실을 알고 있습니까? 이렇게하면 스크린 샷에서 볼 수있는 것처럼 정밀한 문제가 발생합니다. 이 두 가지 사항은 통합 섹션에서 간단히 논의 할 것이며 this paper입니다.

근본적으로 근거리 및 원거리 평면을보다 지능적으로 관리해야합니다 (최소/최대 거리에 더 가깝게 맞추십시오) ... 이것은 모든 섀도우 매핑 알고리즘에 대한 우수 사례이지만 VSM에 특히 중요합니다.

나는 투시 깊이를 모두 없애고 비선형 적 분포의 문제를 제거 할 것을 고려할 것입니다 (알고리즘의 예상 깊이는 필요하지 않습니다. 빛으로부터 일정한 거리를 계산하면 잘 작동합니다.). 이 과 같이 가장 큰 도움이됩니다.

+0

도움을 주셔서 대단히 감사합니다! 내 머리가 폭발 할 것입니다. 나는 무엇이 잘못되었는지를 생각하고있었습니다! –