DirectX Graphics 프로그래밍 가이드 프로그래밍 가능한 파이프라인 정점 셰이더 정점 셰이더의 생성   [목차열람] [주소복사] [슬롯비우기]
정점 셰이더의 생성
 
Microsoft DirectX 9.0

정점 셰이더의 생성


이 예에서는, 개체에 균일한 색을 적용하는 정점 셰이더를 생성 한다. 셰이더 파일의 내용과 그 셰이더 데이터용으로 Microsoft® Direct3D® 파이프라인을 설정하는 경우에 애플리케이션내에 필요한 코드를 나타낸다.

Direct3D 샘플을 빌드 해 실행할 방법을 알 수 있는 경우는, 이 샘플의 코드를 기존의 애플리케이션에 컷 앤드 페이스트 할 수 있다.

여기에서는, 이하의 스텝에 대해 설명한다.

스텝 1: 정점 데이터를 선언하는

이 예에서는, 2 개의 삼각형으로부터 완성되는 사변형을 사용하고 있다. 정점 데이터에는, (x, y, z) 위치 좌표와 디퓨즈색이 포함된다. 정점 데이터는, 정점의 글로벌 배열 (g_Vertices)로 선언된다. 4 개의 정점이 원점을 중심으로 배치되고 있다.

// Declare vertex data structure.  
struct CUSTOMVERTEX
{
    FLOAT x, y, z;
};

// Declare the vertex position and diffuse color data.
CUSTOMVERTEX g_Vertices[]=
{
    //  x        y      z    
    { -1. 0f, -1. 0f, 0.0f }, 
    { +1. 0f, -1. 0f, 0.0f }, 
    { +1. 0f, +1. 0f, 0.0f }, 
    { -1. 0f, +1. 0f, 0.0f }, 
};

스텝 2: 셰이더 기능을 설계하는

이 셰이더는, 각 정점에 균일한 색을 적용한다. 셰이더 파일 VertexShader.vsh 를 다음에 나타낸다.

vs_1_1              // version instruction
dcl_position v0     // define position data in register v0
m4x4 oPos, v0, c0   // transform vertices by view/projection matrix
mov oD0, c4         // load constant color

이 파일은 3 개의 산술 명령과 1 개의 레지스터 정의를 포함하고 있다. 셰이더 파일내의 최초의 명령은 셰이더 버전의 선언이 아니면 안된다. vs 명령은, 정점 셰이더의 버전 (이 예에서는 1_1)을 선언한다.

dcl_position 명령은, 레지스터 v0 를 정점 위치 데이터의 입력으로서 정의한다. m4x4 명령은, 뷰 투영 행렬을 사용해 개체의 정점을 변환 한다. 이 행렬은, 다음에 가리키도록(듯이), 4 개의 정수 레지스터 c0, c1, c2, c3 에 로드 된다. mov 명령은, 레지스터 c4 내의 균일한 색을 출력 디퓨즈색레지스터 oD0 에 복사 한다. 이 결과, 출력 정점에 색을 붙일 수 있다.

스텝 3: 정점 셰이더 지원을 확인하는

정점 셰이더를 사용하기 전에, 장치 능력을 조회하는 것에 의해 정점 셰이더 지원을 확인한다.

D3DCAPS9 caps;
m_pd3dDevice->GetDeviceCaps(&caps);    // initialize m_pd3dDevice before using
if( caps.VertexShaderVersion < D3DVS_VERSION(1,1) )
	return E_FAIL;

IDirect3DDevice9::GetDeviceCaps 를 호출하면, 이 Caps 구조체로부터, 하드웨어의 기능적인 능력이 반환된다. 지원 되고 있는 버전 번호를 테스트하려면 , D3DVS_VERSION 매크로를 사용한다. 버전 번호가 1_1 보다 작은 경우, 이 호출은 실패한다. 이 메서드의 결과를 사용해, 애플리케이션이 정점 셰이더를 기동할지 어떨지를 제어한다.

스텝 4: 정점 셰이더 데이터를 선언하는

정점 선언은 정점 데이터를 기술한다.

// Create the shader declaration.
D3DVERTEXELEMENT9 decl[] = 
{
  { 0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  D3DDECL_END()
};

이 선언에서는 다음과 같이 지정한다. 데이터는 스트림 0 으로부터 취득되어 스트림 선두의 오프셋(offset) 0 으로부터 시작 한다. 위치 데이터를 3 개의 부동 소수점수(실수)값 (D3DDECLTYPE_FLOAT3)으로서 선언해, 정점 데이터 (D3DDECLMETHOD_DEFAULT)를 복사 하도록(듯이) 테설레이터에 지시한다. 데이터의 사용법을 위치 데이터 (D3DDECLUSAGE_POSITION)로서 정의해, 사용 방법 인덱스 0 을 지정한다.

D3DDECLEND()는, 정점 선언을 종료하기 위해서 사용하는 매크로이다.

스텝 5: 셰이더를 생성 하는

다음에, 셰이더를 어셈블(assemble) 해 생성 한다.

LPDIRECT3DPIXELSHADER9 m_pVertexShader;
TCHAR        strShaderPath[512];
LPD3DXBUFFER pCode;                  // Buffer with the assembled shader code
LPD3DXBUFFER pErrorMsgs;             // Buffer with error messages
DXUtil_FindMediaFileCb( strShaderPath, sizeof(strShaderPath), 
                        _T("VertexShader.vsh") );

D3DXAssembleShaderFromFile( strPixelShaderPath, NULL, NULL, 0,  
                            &pCode, &pErrorMsgs, NULL );   
m_pd3dDevice->CreateVertexShader((DWORD*) pCode->GetBufferPointer(),
                                  &m_pVertexShader)
pCode->Release();
pErrorMsgs->Release()

D3DXAssembleShaderFromFile 는, 셰이더 파일을 찾아내면 셰이더 명령을 읽어내 검증한다. 다음에,IDirect3DDevice9::CreateVertexShader 가 셰이더 선언과 어셈블(assemble)가 끝난 명령을 사용해, 셰이더를 생성 한다. 이것은, 드로잉(Drawing) 호출로 사용되는 셰이더 개체를 돌려준다.

CreateVertexShader 는 프로그래밍 가능한 셰이더를 생성 할 경우에 사용한다.

스텝 6: 출력 픽셀을 렌더링 하는

다음에, 렌더링 루프내에서 사용 가능한 샘플 코드를 나타낸다. 이 코드는, 정점 셰이더를 사용해 개체를 렌더링 한다. 렌더링 루프는, 3D 장면의 변경의 결과로서 정점 셰이더 정수를 갱신해,IDirect3DDevice9::DrawPrimitive 를 호출해 출력 정점을 드로잉(Drawing) 한다.


// Update vertex shader constants from view projection matrix data.
D3DXMATRIX mat, matView, matProj;
D3DXMatrixMultiply( &mat, &matView, &matProj );
D3DXMatrixTranspose( &mat, &mat );
m_pd3dDevice->SetVertexShaderConstantF( 0, (float*) &mat, 4 );

// Declare and define the constant vertex color.
float color[4] = {0,1.0, 0,0};
m_pd3dDevice->SetVertexShaderConstantF( 4, (float*) &color, 1 );

// Turn off specular light contribution because the specular value 
//   is not written in the vertex shader.
m_pd3dDevice->SetRenderState( D3DRS_SPECULAR, FALSE ); 

// Render the output.
m_pd3dDevice->SetStreamSource( 0, m_pQuadVB, sizeof(CUSTOMVERTEX) );
m_pd3dDevice->SetVertexShader( m_pVertexShader );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

뷰 행렬과 투영 행렬에는, 카메라의 위치 좌표와 방향의 데이터가 포함되어 있다. 렌더링 루프안에, 갱신된 데이터의 취득과 셰이더의 정수 레지스터의 갱신의 처리를 포함하고 있는 것은, 렌더링 하는 프레임간에 장면(scene)가 변경될 가능성이 있기 때문이다.

보통 대로,IDirect3DDevice9::DrawPrimitive 는,IDirect3DDevice9::SetStreamSource 에 의해 제공되는 정점 데이터를 사용해 출력 데이터를 렌더링 한다. IDirect3DDevice9::SetVertexShader 를 호출해, 정점 셰이더를 사용하도록(듯이) Direct3D 에 지시한다. 다음 화면은 정점 셰이더의 결과이다. 여기에는, 평면 개체 위에의 균일한 색이 나타나고 있다.

정점 셰이더의 결과



© 2002 Microsoft Corporation. All rights reserved.
↑TOP