ID3DXEffect 추가

현재의 프레임웍에서 셰이더를 간단하게 사용하기 위해, ID3DXEffect를 추가 한다.

이펙트를 사용하는 순서는 다음과 같다.

1. 이펙트 생성

2. 이펙트 렌더링

3. 이펙트 해제

1. 이펙트 생성

이펙트를 시작하기 위해 ID3DXEffect 객체를 만든다.

HRESULT D3DXCreateEffectFromFile

    LPDIRECT3DDEVICE9 pDevice,

    LPCTSTR pSrcFile,   
    CONST D3DXMACRO * pDefines,
    LPD3DXINCLUDE pInclude,  
    DWORD Flags,
    LPD3DXEFFECTPOOL pPool,
    LPD3DXEFFECT * ppEffect,
    LPD3DXBUFFER * ppCompilationErrors

);

[in] pDevice: 이펙트를 생성하는 IDirect3DDevice9 포인터
[in] pSrcFile: 이펙트 파일명
[in] pDefines: 프리프로세서 매크로 정의로 NULL로 끝나는 D3DXMACRO 배열
               보통 NULL을 넣는다.
[in] pInclude: #include 의사 명령어로 보통 NULL을 넣는다.
[in] Flags: 셰이더를 컴파일, 어셈블링 하는 사용되는 D3DXSHADER와 D3DXFX 플래그.
     이번에 사용된 셰이더 컴파일 플래그는 아래와 같다.

D3DXSHADER_DEBUG : (컴파일 옵션 /Zi)
컴파일 하는 동안 디버그 파일이름,  라인 번호, 타입, 심볼 정보를 추가한다.

D3DXSHADER_NO_PRESHADER : (컴파일 옵션 /Op)
preshader를 실행하지 않는다. 디폴트로 Presshader를 실행한다.
         
[in] pPool: 파라 메터 공유를 위한 ID3DXFffectPool 개체의 포인터.
            NULL이면 공유하지 않는다.
[out] ppEffect:  컴파일된 ID3DXEFFECT 포인터를 돌려준다.           
[out] ppCompilationErrors: 컴파일 에러를 ID3DXBuffer를 돌려준다.
    에러값이 필요 없다면 NULL 입력

IDirect3DDevice9*    pDevice;

ID3DXEffect*         m_pEffect;       

ID3DXBuffer* errorBuffer = 0;

 

    DWORD dwShaderFlags = 0;

#if defined( _DEBUG )

    dwShaderFlags |= D3DXSHADER_DEBUG;

    dwShaderFlags |= D3DXSHADER_NO_PRESHADER;

#endif

 

    HRESULT hr = D3DXCreateEffectFromFile(

        pDevice,

        szFileName,

        0,

        0,

        dwShaderFlags,

        0,

        &m_pEffect,

        &errorBuffer);

2. 이펙트 렌더링

이펙트 렌더링시에 사용되는 명령어를 알아본다.

SetTechnique()
   Begin()
      BeginPass()
      //메트리얼 설정도 여기서 한다.
      SetTexture()
      CommitChanges()
      //여기서 메시를 그린다.
      EndPass()
   End()

SetTechnique() : 활성화된 테트닉을 셋팅한다.

HRESULT SetTechnique( D3DXHANDLE hTechnique )

[in] hTechnique : D3DXHANDLE를 입력한다.

D3DXHANDLE 의미:
a). GetParameter[ByName|Element|BySemantic] 이나 GetAnnotation[ByName]의해
반환된 값들을 사용한다.
b). 문자열을 의미 할 수도 있다.


Begin() : 활성화된 테크닉을 시작한다.

HRESULT Begin(  UINT* pPasses, DWORD Flags )
    ......
HRESULT End()

[out] pPasses : 활성화된 테크닉의 패스 수를 리턴한다.

[in] Flags : 현재의 장치 상태와 세이더 상태를 시작시(::Begin())에
보관했다가 종료(::End())시에 상태를 복구할 것인지 나타낸다.

D3DXFX_DONOTSAVESTATE :
ID3DXEffect::Begin() 호출시에 장치 state를 보관하지 않고,
ID3DXEffect::End()시에 호출시에 장치 state를 복원하지 하지 않는다.

D3DXFX_DONOTSAVESHADERSTATE :
ID3DXEffect::Begin() 호출시에 셰이더 state를 보관하지 않고
ID3DXEffect::End()시에 호출시에 셰이더 state를 복원하지 하지 않는다.


Begin() : 활성화된 테크닉의 패스를 시작한다.

HRESULT BeginPass(  UINT Pass)
    ......
HRESULT EndPass()

[in] pPasses : 테크닉안에 있는 패스를 지정한다.


SetTexture() : 이펙트에서 사용될 텍스쳐를 지정한다.
부모 클래스 ID3DXBaseEffect의 메쏘드이다.

HRESULT SetTexture(
  D3DXHANDLE hParameter,
  LPDIRECT3DBASETEXTURE9 pTexture
)

[in] hParameter : 이펙트(*.fx)에 있는 텍스쳐 핸들
[in] pTexture : IDirect3DBaseTexture의 핸들


CommitChanges() : BeginPass()와 EndPass() 사이 ID3DXEffect::Setx~~()에
의해 이펙트 상태가 바뀌면 이 메쏘드를 호출 하여 디바이스에게 변화를 알려준다.

HRESULT CommitChanges()

 

아래는 ID3DXEffect를 어떻게 사용하는지 간단하게 설명하고 있는 GpgStudy의
zupet님의 글이다.

zupet님의 글 : ID3DXEffect 사용방법

 

http://www.gpgstudy.com/forum/viewtopic.php?topic=19093

 

device->SetStreamSource(...)

device->SetVertexDeclaration(...)

device->SetIndices(...)

 

UINT pass;

if(SUCCEEDED(effect->Begin(&pass)))

{

    for(UINT i=0; i < pass; effect->BeginPass(i))

    {

        for(int j=0; j< numObject; ++j)

        {

            effect->SetTexture(objectList[i].m_texture);

            effect->CommitChanges();

            device->DrawIndexedPrimitive(...);

        }

    }

    effect->End();

}

이펙트 인스턴스가 같은 경우 SetTexture()를 호출후 CommitChanges()를 실행하여,
텍스쳐가 바뀐걸 적용 시킨다.


3. 이펙트 해제

ID3DXEFFECT * pEffect;

 

pEffect->Release()

 

끝.... 예제는 없다.
프레임웍에 ID3DXEFFECT을 추가하기 위해 지금까지 설명했다.
이펙트를 추가한 프레임웍은 여기(chacter_animation/framework/ver04.html)있다.