프로그래밍 2017. 7. 6. 20:07
728x90

 

shimmering shadow edges == stable shadow == stable csm

안정적인 그림자 구현

 

 

 

 

 

 

뭐, 결국은 다 같은 표현

 

깊이 그림자를 구현하면은,

카메라가 이동, 회전할때,

실시간으로 라이트뷰가 변하므로써
그림자의 외곽이 지글거리게 보이는 현상이 생긴다

(뷰영역이 작으면 티가 잘나지않으나, 뷰영역이 커질수록 더욱 심해짐)


 

이 현상을 해결해보자!

 

 

그런데, 사실,

그리 어렵지 않다

 

매우 복잡스러워 보이는

문서와 코드들도 꽤 본것 같은데,

 

그냥...

결과론적으로는


 

-> _matLightVP 의 _41, _42 값을 안정화시키면, 지글거림 현상은 사라진다!
-> _matLightVP 의 _41, _42 값을 조금만 단순화시켜주면, (작은 소수점값들을 잘라내고)
-> 지글거림 현상이 없어진다


-> matLightVP 는 그림자계산에 사용되는 라이트뷰를 말한다

-> (뷰변환, 프로젝션변환이 모두 끝난 최종 상태)

 

예를 들면,

그냥 이렇게만 해도 대충은 결과를 볼수 있다

 

_matLightVP._41 = round( _matLightVP._41, 2 );
_matLightVP._42 = round( _matLightVP._42, 2 );

 

자르는 소수점 자리수에 따라, 그림자 깜박임 결과가 달라진다

 

 

-----------------------------------------------------------------------------------------------

정확한 구현에 대해서 살펴보자

 

여기서 보여지는 코드는, 최종변환이 적용된 라이트뷰의 이동값을 수정하는 것이고,

여기와는 다르게,

뷰나 프로젝션 단계에서 값을 단순화 시키는 것도 가능할 것이다

 

쉐이더 코드에서 특별히 할일은 없다

소스 코드에서, 그림자를 생성하기 위한 라이트뷰를 만들때

추가해주면 된다

 

*zMatrix 는 우리가 일반적으로 사용하는 matrix 구조체이다

*_matLightVP[_iIdx] 는 뷰와 프로젝션 변환이 이미 적용된 matrix

 

//
zMatrix* pM = &(_matLightVP[_iIdx]);
Vector3 vP;

 

//REF CODE
//vP = Vector3(0,0,0)
//D3DXVec3TransformCoord( &vP, &vP, &_matLightVP[_iIdx] );
vP.x = pM->_41;
vP.y = pM->_42;

 

//라이트뷰의 이동치를, 그림자 텍스쳐 텍셀에 맞추어 준다
//이렇게하니, 카메라 이동,회전할때 그림자 외곽이 지글거리는 현상이 없어졌다

//미세한 소수점값들의 변동으로 인해서, 지글거려 보이는 것이 두드러져 보였던 것!
float texCoordX = fShadowMapSize * 0.5f * vP.x;
float texCoordY = fShadowMapSize * 0.5f * vP.y;

float floorTexCoordX = floor( texCoordX ); //floor(=소수점 이하 모두 버림), 또는 round
float floorTexCoordY = floor( texCoordY );
 
float dx = floorTexCoordX - texCoordX;
float dy = floorTexCoordY - texCoordY;
dx /= fShadowMapSize * 0.5f;
dy /= fShadowMapSize * 0.5f;

 

zMatrix xRounding;
D3DXMatrixTranslation( &xRounding, dx, dy, 0.f ); 
(*pM) *= xRounding;

 

 

소스코드는 여기에서 참고하였다

https://www.gamedev.net/forums/topic/497259-stable-cascaded-shadow-maps/

 

 

 

 

728x90
posted by BK dddDang
: