오늘은 오랜만에 재미있는 3D 그래픽에 대해서 이야기 해보겠습니다. 주제는 Bloom Effect, 블룸 효과 입니다.
먼저 블룸 효과에 대해서 간단히 이해해 보자면,
빛을 받는 물체는 그 주위에 빛을 발산하는 것과 같은 효과를 나타냅니다.
뭐 예를 들면, 태양이 쩅쨍 찌는 사막의 한가운데서 먼 사막의 모래 산등성이를 바라보면 마치 모래 산등성이가 태양 빛을 반사하여 희미하게 빛을 발산하는 것처럼 보이는 풍경을 상상할 수 있을 겁니다.
상상이 안되면 사진을 직접 보죠. 뭐. ( 진작에 보여줘야 했었나? ㅋ )
-블룸 효과 미적용(왼쪽) : 블룸 효과 적용(오른쪽)
이미지 출처: http://cafe.naver.com/raisonblue/379 -
확연히 차이가 나죠. 오른쪽 같은 경우는 빛이 은은하게 퍼지는 것처럼 보입니다. 따라서 블룸 효과를 일종 뽀샤시 효과라고도 합니다만
뭐, 최근 3D 게임 같은 경우는 블룸 효과를 대부분 지원하고 엘더스크롤과 같은 좀 고급 게임은 HDR 효과까지 지원하더군요. HDR 효과는 여기서 논할 거리가 아니기에 생략.
자, 이제 블룸 효과가 뭔지는 이해했을 겁니다. 바로 구현 들어가 보죠 -_-
그런데 블룸 효과 적용에 앞서 2차원 가우스 분포 함수에 대해서 공부해 볼 필요가 있습니다. 가우스 분포 함수를 이용하면 번짐 효
과를 구현할 수 있기 때문이죠.
1차원 가우스 분포 함수의 식이 다음과 같으며
여기서 б 표준 편차입니다. 표준 편차가 1일 때 1차원 가우스 분포 함수는 다음과 같은 모양을 갖죠
그래프 모양을 봐선 뭔가 좌우 대칭으로 증폭이 됨을 알 수 있습니다. 즉, 빛을 발산하는 색상이 증폭이 되는 것이며 화면은 x, y 2차원이기 때문에 2차원 가우스 분포 함수를 사용해야 하는 것이죠.
-2차원 가우스 분포 함수 모양-
식에서 설명하지 않았던 상수 부분 W(x) =
에서 x가 б 이면 pow( e, 0.5 ) 와 같은 결과므로 대략 0.6065가 됩니다. 이걸로 얻은 W(x)로 가중치 값을 얻어내서 이 값들을 마스크로 사용하면 됩니다.
class BloomResource {
LPD3DXEFFECT lpD3DEffect; //다이렉트 이펙트 핸들
}; |
BOOL BloomResource ::InitBloomResource( LPDIRECT3DDEVICE9 lpD3DDevice ) {
//스크린 사이즈 구하기
//텍스처 정점 설정 vertices[ 0 ].vPosition = D3DXVECTOR4( ptScreen.x - 0.5f, ptScreen.y - 0.5f, 0, 1 );
HRESULT hResult = E_FAIL; UINT vertexSize = sizeof( vertices ); hResult = lpD3DDevice->CreateVertexBuffer( vertexSize, 0, vertices[ 0 ].FVF, D3DPOOL_DEFAULT, &lpD3DTexVB, NULL );
if( FAILED( hResult ) ) { return FALSE; }
VOID* pVertices = NULL;
hResult = lpD3DTexVB->Lock( 0, vertexSize, static_cast< VOID** >( &pVertices ), 0 );
if( FAILED( hResult ) ) { return FALSE; }
memcpy( pVertices, vertices, vertexSize );
lpD3DTexVB->Unlock();
hTechBloom = lpD3DEffect->GetTechniqueByName( "GOneBloom" ); FLOAT fTexSizeX = static_cast< FLOAT >( ptScreen.x ); D3DXHANDLE hMapCX = lpD3DEffect->GetParameterByName( NULL, "map_cx" ); D3DXHANDLE hMapCY = lpD3DEffect->GetParameterByName( NULL, "map_cy" );
//서피스 및 텍스처 생성 D3DXCreateTexture(lpD3DDevice, TEXTURE_SIZE, TEXTURE_SIZE, 0, D3DUSAGE_RENDERTARGET, d3ddm.Format, D3DPOOL_DEFAULT, &lpD3DTexture[ 0 ] ); lpD3DTexture[ 0 ]->GetSurfaceLevel( 0, &lpD3DSurface[ 0 ] );
D3DPOOL_DEFAULT, &lpD3DTexture[ 1 ] ); lpD3DTexture[ 1 ]->GetSurfaceLevel( 0, &lpD3DSurface[ 1 ] );
return TRUE;
}//BOOL InitBloomResource( LPDIRECT3DDEVICE9 lpD3DDevice ) |
VOID BloomResource ::RenderBloom( LPDIRECT3DDEVICE9 lpD3DDevice ) { LPDIRECT3DSURFACE9 lpCurrentSurface = NULL; //현재 화면 장치 lpD3DDevice->SetRenderTarget( 0, lpCurrentSurface );
lpD3DDevice->SetFVF( FTexture ::FVF );
lpD3DEffect->SetTechnique( hTechBloom ); UINT iPass = 0; lpD3DEffect->Begin( &iPass, NULL ); }//IF
lpD3DEffect->End(); } |
VOID Render() {
LPDIRECT3DDEVICE9 lpD3DDevice = m_lpD3DDevice;
//카메라 변환에 의한 뷰행렬 설정
//기본 화면 렌더링 lpD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 255, 255, 255 ), 1.0f, 0 );
lpD3DDevice->EndScene();
//블룸 효과를 마지막 렌더링 m_pBloomResource는 BloomResource 객체.
lpD3DDevice->Present( NULL, NULL, m_hWnd, NULL );
|
float map_cx; //텍스처 크기 가로 sampler Sampler0;
//텍스처 의 임의의 위치의 픽셀에 접근하귀 위한 좌표 ( 가로 방향)
//텍스처의 임의의 위치의 픽셀에 접근하기 위한 좌표 ( 세로 방향) float2 PixelKernelV[13] =
//미리 계산해 둔 가우스 필터의 마스크 값 };
float4 PSBlur( float2 Tex : TEXCOORD ) : COLOR {
float4 Color = tex2D( Sampler0, Tex ); return Color + Color2 + Color3;
technique GOneBloom { pass P0 { |
-블룸 효과 적용 전-
[출처] Bloom Effect (블룸 효과)|작성자 Hermet
'Visualization Programming > Basic Knowledge' 카테고리의 다른 글
Basic Knowledge - Dithering (디더링) (0) | 2018.07.25 |
---|---|
Basic Know - Pixel Bleeding (0) | 2018.03.12 |
Basic Knowledge - 짐벌락 (Gimbal Lock) (0) | 2017.04.19 |
Basic Knowledge - Z-Fighting (0) | 2017.04.19 |
Basic Knowledge - Pitch , Yaw , and Roll Systems (0) | 2017.04.19 |