본문 바로가기

예전/3D

Direct3D의 그리기 1 정점의 입력과 배치


Direct3D의 그리기 연산



오늘의 목표


1) 기하 자료의 정의. 저장. 그리기. 를 위한 Direct3D 인터페이스와 함수를 파악한다.

2) 기본적인 vertex shader, pixel shader를 작성하는 법을 배운다.

3) rendering pipeline을 구성하는 방법을 파악한다.

4) Direct3D 효과 프레임워크를 이용해서 


논리적으로 연관된 셰이더들과 

렌더 상태들을 하나의 렌더링 기법으로 묶는 방법과

효과 프레임워크를 '셰이더 생성기'로 사용하는 방법

을 배운다.



1. 정점의 입력과 배치


구조체로 정점을 표현한다. 내부에 들어있는 변수에 따라 다른 정점으로 분류된다.


struct Vertex1

{

VERTOR3 Pos,Color;

};


struct Vertex2

{

VERTOR3 Pos,Normal;

FLOAT2 Tex0,Tex1;

};


Vertex1과 2는 다른 vertex 이다. 



정점 구조체를 정의했다면, 그 구조체의 각 성분이 어떤 용도인지 Direct3D 에게 알려줘야 한다. 

그 수단이 ID3D11InputLayout 형식의 input layout 객체이다. 

input layout 객체는 D3D11_INPUT_ELEMENT_DESC 구조체로 이루어진 배열을 통해 구축한다.


정점의 성분이 2개라면  D3D11_INPUT_ELEMENT_DESC 배열의 원소도 2개여야한다. 

 D3D11_INPUT_ELEMENT_DESC를 input laout 서술 배열이라고 한다. 


typedef struct D3D11_INPUT_ELEMENT_DESC { LPCSTR                     SemanticName;             UINT                       SemanticIndex;            DXGI_FORMAT                Format; UINT                       InputSlot; UINT                       AlignedByteOffset; D3D11_INPUT_CLASSIFICATION InputSlotClass; UINT                       InstanceDataStepRate; } D3D11_INPUT_ELEMENT_DESC;



SemanticName : 문자열 이름, 정점 셰이더에서 쓰이는 유효한 변수 이름 

SemanticIndex : 인덱스, 텍스쳐 좌표의 인덱스를 구분하는데 쓰인다.

Format : 정점 성분의 자료 형식을 구분하는데 쓰인다.

InputSlot : 이 성분의 자료가 공급될 정점 버퍼 슬롯의 색인이다. 

AlignedByteOffset : 정점 위치 Offset

InputSlotClass : 인스턴싱에 쓰이는 부분으로 일단은 D3D11_INPUT_PER_VERTEX_DATA 로 쓰자.

InstanceDataStepRate : 인스턴싱에 쓰이는 부분이다. 일단은 0 으로 쓰자.



위에나온 vertex1, vertex2 은 아래와 같은 input layout 서술 배열로 쓸 수 있다. 


D3D11_INPUT_ELEMENT_DESC decs1[] = 

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}

};


D3D11_INPUT_ELEMENT_DESC decs2[] = 

{

{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},

{"TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}

};



입력 배치 서술을 완성하고, input layout을 위한 ID3D11InputLayout 인터페이스를 얻었다면, 

ID3D11Device::CreateInputLayout 함수를 호출해 input layout을 호출할 수 있다.


HRESULT CreateInputLayout(
  [in]   const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
  [in]   UINT NumElements,
  [in]   const void *pShaderBytecodeWithInputSignature,
  [in]   SIZE_T BytecodeLength,
  [out]  ID3D11InputLayout **ppInputLayout
);


pInputElementdescs : D3D11_INPUT_ELEMENT_DESC 배열

NumElements : D3D11_INPUT_ELEMENT_DESC 배열의 원소 개수

pShaderBytecodewithInputSignature : 정점 셰이더를 컴파일해서 얻은 byte 코드를 가리키는 포인터 ?!

BytecodeLength : byte 코드의 크기

ppInputlayout : 다시 돌려받을 포인터



pShaderBytecodewithInputSignature  


정점 셰이더는 입력 매개변수를 받는데, 그 입력 매개변수의 형식과 개수를 input signature라고 한다. 

custom 정점 구조체의 성분은 반드시 정점 셰이더의 매개변수에 대응 되어야 한다. 


VertexOut VS(float3 Pos : POSITION, float4 Color : COLOR, float3 Normal : NORMAL) {}


struct Vertex

{

XMFLOAT3 Pos;

XMFLOAT4 Color;

};


위 코드는 오류이다. 

개수가 틀렸다. 개수 및 변수명을 잘 써줘야 한다.



ID3D11Device::CreateInputLayout 를 호출하려면 ID3D11Effect 가 필요하다.


ID3D11Effect 는 하나 이상의 렌더링 패스들을 캡슐화 하며, 각 패스마다 정점 셰이더가 연관된다. 따라서 ID3D11Effect 로부터 패스를 서술하는 구조체 ( D3D11_PASS_DESC ) 를 얻을 수 있으며, 그 구조체로부터 정점 셰이더의 input signature에 접근할 수 있다.




[과정]


구조체를 만들고, 

input layout에 접근하고,

binding 한다. ( 사용하고자하는 장치에 묶는다. ) 




구조체를 만들고, 

// input layout에 접근하고,


ID3DX11Effect* mFX;

ID3DX1EffectTechnique* mTech;

ID3D11InputLayout* mInputLayout; 


/*         ID3D11Effect 생성         */


mTech = mFX->GetTechniqueByName("Tech");

D3DX11_PASS_DESC passDesc;

mTech->GetPassByIndex(0)->GetDesc(&passDecs);

HR(md3dDevice->

CreateInputLayout(vertexDesc, 4, 

passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &mInputLayout ));


// binding 한다. ( 사용하고자하는 장치에 묶는다. ) 


md3dImmediateContext->IASetInputLayout(mInputLayout);


/*         mInputLayout을 통해서 물체들을 그린다.         */




input layout을 한 장치에 묶었다면, 다른 input layout을 묶이 전까지는 그 것이 적용된다.



'예전 > 3D' 카테고리의 다른 글

D3D11 wireframe  (0) 2014.05.23
Direct3D의 그리기 2. 정점 버퍼  (0) 2014.04.06
DirectX11 초기화  (2) 2014.03.31
[OPENGL] quaterinion  (0) 2013.09.24
플레이어 따라다니는 카메라  (0) 2013.02.27