2012-05-28 3 views
7

전 방향 포인팅 라이트로 작업하고 있습니다. 이미 큐브 맵 텍스쳐를 6 프레임 버퍼의 컬러 첨부 파일로 사용하고 쉐도우 맵핑을 구현했으며 각 픽셀에서 빛과 프래그먼트 사이의 거리를 인코딩했습니다. 이 가능한 경우 깊이 큐브 맵을 사용한 무지 향 그림자 매핑

지금 내 구현이 방법을 변경하려면, 싶습니다

  • 1) 대신 색상으로, 내 프레임 버퍼의 깊이 버퍼에 깊이 큐브 맵 텍스처를 연결합니다.
  • 2) 렌더링 깊이 만이 패스에 색상을 쓰지 마십시오.
  • 3) 메인 패스에서 큐브 맵 텍스처의 깊이를 읽고 거리로 변환 한 다음 현재 조각이 가벼운가.

큐브 맵에서 깊이 값을 거리로 변환하면 문제가 발생합니다. 나는 큐브 맵에서 깊이 값을 가져 오기 위해 light-to-fragment 벡터를 사용했다. 이 시점에서, 나는 6 개의 얼굴 중 어느 것이 사용되고 있는지, 2D 텍스처 좌표가 내가 읽고있는 깊이 값과 일치하는지 알지 못합니다. 그렇다면 어떻게 깊이 값을 거리로 변환 할 수 있습니까?

여기 내 코드의 조각을 설명하기 위해 다음과 같습니다

깊이 텍스처 :

glGenTextures(1, &TextureHandle); 
glBindTexture(GL_TEXTURE_CUBE_MAP, TextureHandle); 
for (int i = 0; i < 6; ++i) 
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, 
       Width, Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); 

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

프레임 버퍼 건설 :

for (int i = 0; i < 6; ++i) 
{ 
    glGenFramebuffers(1, &FBO->FrameBufferID); 
    glBindFramebuffer(GL_FRAMEBUFFER, FBO->FrameBufferID); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
      GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, TextureHandle, 0); 
    glDrawBuffer(GL_NONE); 
} 

내가 달성하기 위해 쓰기 위해 노력하고있어 조각 쉐이더의 조각 내 코드 :

float ComputeShadowFactor(samplerCubeShadow ShadowCubeMap, vec3 VertToLightWS) 
{ 
    float ShadowVec = texture(ShadowCubeMap, vec4(VertToLightWS, 1.0)); 
    ShadowVec = DepthValueToDistance(ShadowVec); 
    if (ShadowVec * ShadowVec > dot(VertToLightWS, VertToLightWS)) 
     return 1.0; 

    return 0.0; 
} 

DepthValueToDistance 함수가 실제 문제입니다.

+0

"문제가 해결 되었습니까?" 거리를 깊이로 변환하고 큐브 맵에 저장된 깊이와 비교합니다. "큐브 맵 그림자에 적용 할 수 없다"5.7 년 전에는 "ron frazier"라는 누군가가 쉐도우 맵핑을 위해 큐브 맵을 사용하는 방법에 관한 기사를 썼다. – SigTerm

+0

@SigTerm http://www.ronfrazier.net/apparition/index.html?appmain=research/index.html 내가 당신이 말하는 것 같아요. –

+0

@ 존린 셀바 토 : 네. 나는 ** 그것이 ** [this] (http://www.ronfrazier.net/apparition/index.html?appmain=research/index.html) 기사라고 생각합니다. 분명히 현대 OpenGL/더 나은 정밀도 (부동 소수점 텍스처, GLSL,'shadow 'samplers 등)와 비슷한 것을 할 수 있습니다. - 나는 단지 근처에 일하는 발췌 문장이 없으며, 하나의 글을 쓰고 싶지 않습니다. . – SigTerm

답변

10

그래서 솔루션은 큐브 맵에서 읽은 깊이를 거리로 변환하는 대신에 라이트 - 프래그먼트 벡터를 깊이 값으로 변환하는 것이 었습니다.

float VectorToDepthValue(vec3 Vec) 
{ 
    vec3 AbsVec = abs(Vec); 
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z)); 

    const float f = 2048.0; 
    const float n = 1.0; 
    float NormZComp = (f+n)/(f-n) - (2*f*n)/(f-n)/LocalZcomp; 
    return (NormZComp + 1.0) * 0.5; 
} 

float ComputeShadowFactor(samplerCubeShadow ShadowCubeMap, vec3 VertToLightWS) 
{ 
    float ShadowVec = texture(ShadowCubeMap, vec4(VertToLightWS, 1.0)); 
    if (ShadowVec + 0.0001 > VectorToDepthValue(VertToLightWS)) 
     return 1.0; 

    return 0.0; 
} 

Explaination VectorToDepthValue(vec3 Vec)에 :

LocalZComp는 큐브 맵의 정합 절두체에 주어진 Vec의 Z 성분 어떨지에 대응 여기

수정 된 셰이더 코드이다. 실제로는 Vec의 가장 큰 구성 요소입니다 (예 : Vec.y가 가장 큰 구성 요소 인 경우 큐브 맵의 Y + 또는 Y- 얼굴을 찾습니다).

wikipedia article을 살펴보면 LocalZComp을 정규화 된 Z 값 ([-1.1.1] 사이)으로 변환하는 직후의 수학을 이해할 수 있습니다.) 다음 깊이 버퍼 값의 실제 범위 인 [0..1]로 매핑하십시오. (당신이 그것을 변경하지 않았다고 가정). nf은 큐브 맵을 생성하는 데 사용 된 절두체의 근거리 및 원거리 값입니다.

ComputeShadowFactor 그러면 큐브 맵의 깊이 값과 조각 - 가벼운 벡터 (여기서는 VertToLightWS)에서 계산 된 깊이 값을 비교하고 작은 깊이 바이어스 (질문에 누락 됨)를 추가 한 다음 단편이 빛에 의해 가려지지 않으면 1.

4

파생에 대한 자세한 내용을 추가하고 싶습니다.

V을 가벼운 조각 방향 벡터로 지정하십시오.

Benlitz 이미 말한 것처럼, 각각의 큐브면 절두체/"시각 공간"의 Z 값은 V의 절대 값의 최대를 취함으로써 계산 될 수의 성분.

Z = max(abs(V.x),abs(V.y),abs(V.z)) 

이어서, 정확하기 때문에 우리는 OpenGL에서, 음의 Z 축 점 화면/절두체에 Z를 부정한다.

이제 깊이 버퍼의 "호환 가능한"값인 -Z을 얻고 싶습니다. OpenGL의 관점 매트릭스 보면

...

(백업 링크)

.. 우리 모든 균질 벡터가 매트릭스 승산을 위해, 볼

http://www.songho.ca/opengl/files/gl_projectionmatrix_eq16.png

http://i.stack.imgur.com/mN7ke.png 결과 z 값은 벡터의 x 및 y 구성 요소와 완전히 독립적입니다.

그래서 우리는 단순히 균일 한 벡터를이 행렬을 곱할 수 (0,0 -Z, 1) 우리는 벡터 (구성 요소)를 얻을 :

x = 0 
y = 0 
z = (-Z * -(f+n)/(f-n)) + (-2*f*n/(f-n)) 
w = Z 

그런 다음 우리가 관점을 할 필요가 분할 그래서 우리는 우리에게 준다 (Z) w로 Z 분할 :

z' = (f+n)/(f-n) - 2*f*n/(Z* (f-n)) 

이 Z '는 OpenGL은의 정규화 디바이스 좌표 (NDC) -1,1-를]의 범위에 있고로 변환 할 필요 깊이 버퍼 호환성 전자의 범위 [0,1]

z_depth_buffer_compatible = (z' + 1.0) * 0.5 

또한 참고 :

  • 그것의 결과 (F + N)를 업로드하는 것은 의미가 수 (FN) 및 (F * 않음) 계산을 저장하기 위해 셰이더 유니폼으로. 그림자 큐브 맵은 일반적으로하여 세계 공간에서 "최대 (ABS (내지 Vx), ABS (VY), ABS (Vz의))"를 정렬 축 때문에 세계 공간에 있어야

  • V - 일부는 V이 월드 공간 방향 벡터 인 경우에만 작동합니다.

관련 문제