2015. 9. 3. 08:50

//#ifdef _DEBUG

    //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;

//#endif


이 부분을 삭제하면 된다



2015. 8. 7. 17:22

cbuffer cbPerOjbect

{

float4x4 gWorldViewProj;

};


cbuffer 형식의 객체 cbPerObject를 정의한다. 상수 버퍼(constant buffer)는 셰이더가 접근할 수 있는 다양한 자료를 저장하는 유연한 자료 블록이다.

지금 예의 상수 버퍼는 gWorldViewProj라는 4 x 4 행렬 하나만 저장한다.

이 행렬은 한 점을 국소 공간에서 동차 절단 공간으로 변환하는 데 쓰이는, 세계, 시야, 투영 행렬을 하나로 결합한 것이다

HLSL은 4 x 4 행렬을 위한 내장 형식 float4x4를 제공한다. 그 외에도 여러 행렬 형식이 있는데, 예를 들어 3 x 4 행렬이나 2 x 2 행렬을 선언하려면 float3x4 형식이나 float2x2 형식을 사용하면 된다.


상수 버퍼의 자료는 정점마다 바뀌는 것이 아니다. 그러나 C++ 응용 프로그램은 효과 프레임워크를 통해서 상수 버퍼의 내용을 실행시점에서 변경할 수 있다. 예를 들어 세계 행렬은 물체마다 다르므로 세계, 시야, 투영 행렬이 결합된 행렬도 물체마다 달라야 한다. 따라서 앞에 나온 정점 셰이더로 여러 개의 물체를 그리는 경우 각 물체를 그리기 전에 gWorldViewProj 변수를 적절히 갱신해 주어야 한다

- 내용을 얼마나 자주 갱신할 것인지

- 상수 버퍼를 나누어 만들라는 것인지

에 근거해서 상수 버퍼를 나누어 만들라는 것이다

2015. 8. 7. 16:52

다음은 간단한 정점 셰이더의 구현 코드이다


cbuffer cbPerObject

{

float4x4 gWorldViewProj;

};


void VS(float3 iPosL : POSITION,

  float4 iColor : COLOR,

  out float4 oPosH : SV_POSITION,

  out float4 oColor : COLOR)

{

// 동차 절단 공간으로 변환한다

oPosH = mul(float4(iPosL, 1.0f), gWorldViewProj);


// 정점 색상을 그대로 픽셀 셰이더에 전달한다

oColor = iColor;

}


하나의 정점 셰이더는 본질적으로 하나의 함수이다.

지금 예의 정점 셰이더는 매개변수가 4개인데, 처음 둘은 입력 매개변수이고 나머지 둘은 out 키워드가 붙어있으므로 출력 매개변수이다.

HLSL에는 참조나 포인터가 없으므로, 함수가 여러 개의 값들을 돌려주려면 구조체를 사용하거나 이처럼 out이 지정된 출력 매개변수를 사용해야 한다.

정점 셰이더의 처음 두 입력 매개변수는 정점 셰이더의 입력 서명을 형성하며, 커스텀 정점 구조체의 자료 멤버들에 대응된다. 매개변수 의미소: POSITION과 :COLOR는 정점 구조체의 멤버들을 정점 셰이더 입력 매개변수들에 대응시키는 역할을 한다.

출력 매개변수에도 의미소가 부여되어 있다. 이들은 정점 셰이더의 출력을 파이프라인의 다음단계(기하 셰이더, 픽셀 셰이더)의 해당 입력에 대응시키는 역할을 한다. SV_POSITION 의미소는 특별한 의미소임을 주목할 것. SV는 이것이 system value(시스템 값) 의미소입을 뜻한다.


행렬 변수 gWorldViewProj는 상수 버퍼에 있는 것인데, 상수 버퍼에 대해서는 다음 절에서 이야기하겠다.

mul은 HLSL의 내장함수로, 벡터, 행렬의 곱셈을 수행한다. 


다음은 이 정점 셰이더와 정확히 같은 일을 하는 정점 셰이더로, 다른 점은 반환 형식과 입력 서명에 구조체들을 사용한다는 것


cbuffer cbPerObject

{

float4x4 gWorldViewProj;

};


struct VertexIn

{

float3 PosL : POSITION;

float4 Color : COLOR;

};


struct VertexOut

{

float4 PosH : SV_POSITION;

float4 Color : COLOR;

};


VertexOut VS(VertexIn vin)

{

VertexOut vout;


// 동차 절단 공간으로 변환

vout.PosH = mul(float(vin.PosL, 1.0f), gWorldViewProj);


// 정점 색상을 그대로 픽셀 셰이더에 전달

vout.Color = vin.Color;


return vout;

}


* 참고

- 기하 셰이더를 사용하지 않는다면 정점 셰이더에서 투영 변환을 반드시 수행해야 한다. 기하 셰이더가 쓰이지 않는 경우 하드웨어는 정점 셰이더를 떠난 정점이 동차 절단 공간에 있다고 가정하기 때문이다. 기하 셰이더를 사용하는 경우에는 투영 변환을 기하 셰이더에게 미룰 수 있다.


* 참고

- 정점 셰이더(또는 기하 셰이더)가 원근 나누기까지 수행하지는 말아야 한다. 투영 행렬을 곱하는 부분만 책임지면 된다. 원근 나누기는 나중에 하드웨어가 수행한다.







2015. 8. 7. 16:23

GPU가 정점 배열에 접근할 수 있으려면 배열의 정점들을 버퍼라고 부르는 특별한 자원에 담아 두어야 한다. Direct3D 코드에서 버퍼는 ID3D11Buffer 인터페이스로 대표된다.


정점들을 담는 버퍼를 정점 버퍼라고 부른다. Direct3D의 버퍼들은 자료를 담을 뿐만 아니라, CPU나 GPU가 자료에 어떻게 접근할 수 있고 버퍼가 파이프라인의 어디에 묶이는지에 대한 정보도 가진다.

정점 버퍼를 생성하려면 다음과 같은 과정을 거쳐야 한다.

1. 생성할 버퍼를 서술하는 D3D11_BUFFER_DESC 구조체를 채운다.

2. 버퍼의 초기화에 사용할 자료를 서술하는 D3D11_SUBRESOURCE_DATA 구조체를 채운다

3. ID3D11Device::CreateBuffer를 호출해서 버퍼를 생성한다.


2015. 8. 7. 16:14

렌더링 파이프 라인 구성,

정점 셰이더, 픽셀 셰이더를 정의

3차원 모형을 그리기 위해 기하구조를 렌더링 파이프라인에 제출하는데

필요한 Direct3D API의 여러 인터페이스와 메서드를 중점적으로 살펴본다

다양한 기하 도형을 색을 입혀서, 또는 와이어프레임 형태로 그릴 수 있다


이 글의 목표

1. 기하 자료의 정의와 저장, 그리기(drawing)를 위한 Direct3D 인터페이스와 메서드를 파악한다

2. 기본적인 정점, 픽셀 셰이더를 작성하는 방법을 배운다

3. 렌더 상태로 렌더링 파이프라인을 구성하는 방법을 파악한다

4. Direct3D 효과 프레임워크를 이용해서 논리적으로 연관된 셰이더들과

렌더 상태들을 하나의 렌더링 기법으로 묶는 방법과 효과 프레임워크를

일종의 '셰이더 생성기'로 사용하는 방법을 배운다.


* 정점과 입력 배치


- 정점은 공간적 위치 이외에 추가적인 자료를 가질 수 있다

- 원하는 자료를 가진 커스텀 정적 형식을 만들려면 우선 그러한 자료를 담을 구조체를 정의해야 한다

- 예를 들어 다음은 서로 다른 두 종류의 정점 형식을 보여준다

- 하나는 위치와 색상

- 하나는 위치, 법선, 텍스처 좌표로 구성


struct Vertex1

{

XMFLOAT3 Pos;

XMFLOAT4 Color;

};


struct Vertex2

{

    XMFLOAT3 Pos;

    XMFLOAT3 Normal;

    XMFLOAT2 Tex0;

    XMFLOAT2 Tex1;

};


정점 구조체를 정의했다면, 그 정점 구조체의 각 성분이 어떤 용도인지를 Direct3D에게 알려주어야 한다. 이 정보를 알려주는 수단이 바로 ID3D11InputLayout 형식의 입력 배치(input layout) 객체이다.

이 입력 배치 객체는 D3D11_INPUT_ELEMENT_DESC 구조체들로 이루어진 배열을 통해서 구축한다. 이 D3D11_INPUT_ELEMENT_DESC 배열의 각 원소는 정점 구조체의 각 성분을 서술하는 역할을 한다. 예를 들어 정점 구조체의 성분이 두 개라고 하면 D3D11_INPUT_ELEMENT_DESC 배열의 원소도 두 개이어야 한다. 


struct D3D11_INPUT_ELEMENT_DESC{

LPCSTR SementicName;

UINT SemanticIndex;

DXGI_FORMAT Format;

UINT InputSlot;

UINT AlignedByteOffset;

D3D11_INPUT_CLASSIFICATION InputSlotClass;

UINT InstanceDataStepRate;

};


- 정점 구조체의 각 성분을 D3D11_INPUT_ELEMENT_DESC 배열의 각 원소를 통해서 서술한다.


1. SemanticName : 성분에 부여된 문자열 이름

2. SemanticIndex : 의미소에 부여된 색인

3. Format : DXGI_FORMAT 열거형의 한 멤버

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

5. AlignedByteOffset : 입력 슬롯을 하나만 사용하는 경우 이 필드는 C++ 정점 구조체의 시작 위치와 이 정점 성분의 시작 위치 사이의 오프셋이다.

6. InputSlotClass : D3D11_INPUT_PER_VERTEX_DATA를 지정

7. InstanceDataStepRate : 지금은 0으로 지정


- 입력 배치 서술 배열을 완성했으며 입력 배치를 위한 ID3D11InputLayout 인터페이스를 얻었다면, 이제 ID3D11Device::CreateInputLayout 메서드를 호출해 입력배치를 생성한다


HRESULT ID3D11Device::CreateInputLayout(

const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,

UINT NumElements,

const void* pShaderBytecodeWith InputSignature,

SIZE_T BytecodeLength,

ID3D11InputLayout** ppInputLayout);


1. pInputElementDescs : 정점 구조체를 서술하는 D3D11_INPUT_ELEMENT_DESCE들의 

2. NumElements : 그 D3D11_INPUT_ELEMENT_DESC 배열의 원소 개수

3. pShaderBytecodeWithInputSignature : 정점 셰이더를 포함한 컴파일해서 얻은 바이트 코드를 가리키는 포인터.

4. BytecodeLength : 그 바이트 코드의 크기(바이트 단위)

5. ppInputLayout : 생성된 입력 배치를 이 포인터를 통해서 돌려준다


* 입력 서명(input signature) : 정점 셰이더는 일단의 정점 성분들을 입력 매개변수들로서 받는데, 그 입력 매개 변수들의 형식과 개수를 통칭

- 커스텀 정점 구조체의 성분들은 반드시 정점 셰이더의 적절한 입력 매개변수에 대응되어야 한다















2015. 8. 1. 13:57

d3d11.lib

d3dx11d.lib

D3DCompiler.lib

Effects11d.lib

dxerr.lib

dxgi.lib

dxguid.lib

2015. 7. 9. 16:21

설정은 따로 여기서 다루지 않는다.


  • 기본 프로그램 파일
  1. Singleton.hpp
  2. Object.hpp
  3. MainGameManager.hpp
  4. Winmain.hpp
  5. MainGameManager.hpp
  6. Winmain.cpp
  7. Winmainpartial.cpp

위의 파일들이 우리가 만들 기본 틀이 될 것이다. 
네임 스페이스는 내 이름을 따서 jm으로 했다

  • Singleton.hpp



  • Object.hpp


  • MainGameManager.hpp



  • Winmain.hpp


  • Winmain.cpp
  • Winmainpartial.cpp

  • MainGameManager.cpp


2015. 7. 8. 09:39

d3d9.lib

d3dx10d.lib

d3dx9d.lib

dxerr.lib

dxguid.lib

winmm.lib

comctl32.lib