쉐이더 그림자 vsm pcf - 01
화면을 클릭하면, 크게 보실수 있습니다!
그림자의 농도는 조절 가능 합니다.
농도차의 확인을 쉽게 하기 위해서, 되도록 그림자영역을 검게 만들었습니다.
1. depth
2. depth + pcf
pcf 4단계 적용
3. depth + vsm
4. depth + pcf + vsm
pcf 3단계 적용
5. depth + pcf + vsm
pcf 10 단계 적용
구현 방법도 많고,
테스트 방법도 많고,
이리저리 테스트를
참
많이도 해 보았습니다!
vsm 에 대한 설명은 인터넷에서 충분히 찾아 보실 수 있습니다.
깔끔한 vsm 코드는 여기!
렌더타겟 그림자에
깊이값을 저장할때
depth * depth 를 G 에 저장해 둡니다.
R, G 값을 사용.
float4 PS_Shadow_1( VS_OUTPUT _In ) : COLOR
{
float depth_color = _In.depth.z / _In.depth.w;
//r, g, b, a
return float4( depth_color, depth_color * depth_color, 0.f, 1.f );
}
//렌더타겟 텍스쳐 생성 부분
D3DDEVICE->CreateTexture( _iW, _iH, 1, D3DUSAGE_RENDERTARGET, D3DFMT_G32R32F, D3DPOOL_DEFAULT, &m_pRT_Shadow[0], NULL )
뎁스값을 비교하는 PS 함수부분
{
float2 moments = tex2D( TexShadow, uv ).rg; //뎁스갑이다, 0~1 범위의 컬러값이 아니다
//뎁스값비교로만 사용할 수 있다.
//VSM
//cur_depth 는 자기 뎁스 값입니다.
float fragDepth = cur_depth;
float fLit = 1.0f;
float E_x2 = moments.y;
float Ex_2 = moments.x * moments.x;
float variance = (E_x2 - Ex_2);
//최소값으로 보정해 두어야만
//그림자 영역 안에,
//깊이값의 미묘한 편차에 의한, 지저분한 면이 생기지 않습니다.
//이 최소값은 투영행렬의 영향(거리값 등....)을 받습니다
variance = max( variance, 0.00005f );
float mD = (fragDepth - moments.x);
float mD_2 = mD * mD;
float p = (variance / (variance + mD_2));
//쉐도우뎁스값이 자기값보다 앞에 있다면(작다면)
//가리워진것으로 판정하여 그림자 처리를 해주어야 하는데,
//원래는 이것
//max( p, fragDepth <= moments.x );
//값뒤집기
//의외로 좋은 결과
fLit = max( p, fragDepth > moments.x );
fLit = (1.f - fLit) + 0.5f;
if( fLit > 1.f )
fLit = 1.f;
//컬러에 적용
//컬러값 * fLit 으로 사용하였습니다.
//fLit 값이 작을 수록, 픽셀이 어두워 집니다.
}
'프로그래밍' 카테고리의 다른 글
텍스쳐 샘플링 필터링 (0) | 2015.04.30 |
---|---|
셀프쉐도우 depth bias (0) | 2015.04.24 |
볼륨메트릭 라이팅 Volumetric Light - 02 (0) | 2015.01.30 |
볼륨메트릭 라이팅 Volumetric Light - 01 (0) | 2015.01.30 |
셰이더로 구현한 화면 노이즈 (0) | 2015.01.23 |