RendererTexture MotionBlure

셰이더 없이 모션블러를 만들어보자. 결론부터 이야기 하자면 힘들어 보인다.

이미지는 그럴듯해 보이지만 문제점은 다음과 같다.

< 문제점 >
1. 여기서는 스프라이트를 이용해 뿌려주고 있다. 특정 칼라키를 투명키로 처리하는 텍스쳐로 뿌려주는 방법을 사용해도 되겠지만 그런제한을 두는 것은 그래픽 리소스와 문제를 일으킬것이다.

2. 가려져야 하는상황에서도 보이지 않을까 하는 생각이 든다.

사용은 안하겠지만 구현 방법은 알아보자. 렌더러 텍스쳐와 스프라이트 사용 방법은 tutorial08.html을 참고한다.

< 모션블러 구현 >

1. 사용되는 렌더러 텍스쳐 만들기
InitRendererTexture( )로 렌더러 텍스쳐를 두 개 만든다.

2. 렌더러 텍스쳐에 모션블러할 오브젝트를 그린다.
RenderSpriteInSurface( )에서 주전자를 그린후 이전에 그려진 텍스쳐 이미지를 합성해서 현재  렌더링 타겟의 텍스쳐에 그린다.
현재의 렌더링타겟 이미지는 다음프레임에는 이전의 그려진 텍스쳐로 사용될것이다.

DWORD    g_motionAlpha = 0xf0ffffff;

HRESULT hr = g_pSprite->Draw( spriteTexture.pTexture, NULL, NULL, NULL, g_motionAlpha );

g_motionAlpha 알파 값이 클수록( 투명 할 수록 ) 주전자의 모션 꼬리가 길게 보인다.

3. 디바이스 백퍼에 주전자를 그릴때 렌더러 텍스쳐의 이미지를 렌더링한다.
RenderSpriteInBackbuffer( )에서 합성된 렌더러 텍스쳐를 뷰포트에 맞춰서 그린다.

void  RenderSpriteInBackbuffer( RendererTexture* pRendererTexture )

{

    g_pSprite->Begin( D3DXSPRITE_ALPHABLEND );

 

    D3DVIEWPORT9 viewport ;

    g_d3d_Device->GetViewport( &viewport );

 

    D3DXMATRIX mat;

    D3DXMatrixIdentity( &mat );

 

    //뷰크기에 맞춰 스프라이트의 텍스쳐 크기를 조정한다.

    mat._11 = (float)viewport.Width / 256.0f;

    mat._22 = (float)viewport.Height / 256.0f;

    g_pSprite->SetTransform( &mat );

 

    //가장 아래 그리기 위해서 Z 버퍼를 끈다.

    g_d3d_Device->SetRenderState( D3DRS_ZENABLE, FALSE );

    g_d3d_Device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCCOLOR );

    g_d3d_Device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );

 

    HRESULT hr = g_pSprite->Draw( pRendererTexture->pTexture, NULL, NULL, NULL, 0xffffffff );

    g_pSprite->End();

 

    //RenderState복원

    g_d3d_Device->SetRenderState( D3DRS_ZENABLE, TRUE );

    g_d3d_Device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCCOLOR );

    g_d3d_Device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );

    g_d3d_Device->SetTexture( 0, NULL );

}

스프라이트를 뷰포트에 맞추기 위해 g_pSprite->SetTransform(  ) 시킨다.
맨아래에 렌더링하기 위해서 렌더스테이트를 조정한다.

~끝

다시 쉽게 정리 하자면

1. 렌더러텍스쳐를 A, B 두 개 준비한다.

2. 렌더러 텍스쳐 A에 그리기
주전자 그리기 + 이전에 그려진 이미지 B  === 렌더러 텍스쳐 A

3. 모션블러 그리기( 실제 화면에 보이는 이미지 )
주전자 그리기 , 렌더러 텍스쳐 A의 이미지 그리기

4. 렌더러 텍스쳐 B에 그리기
주전자 그리기 + 이전에 그려진 이미지 A === 렌더러 텍스쳐 B

5. 모션블러 그리기( 실제 화면에 보이는 이미지 )
주전자 그리기, 렌더러 텍스쳐 B의 이미지 그리기

프레임 업데이트시 2, 3번과 4, 5번이 반복되면서 이전의 이미지를 알파값을 적용해서 그리기 때문에 오래된 이미지는 알파값이 계속 적용 되다 보면 사라지게 되는 것이다.

texture_motionblur.zip