Direct3D 코드에서 버퍼는 ID3D11Buffer 인터페이스로 대표된다. Direct3D의 버퍼들은 자료를 담을 뿐만 아니라, CPU나 GPU가 자료에 어떻게 접근할 수 있고 버퍼가 파이프라인의 어디에 묶이는지에 대한 정보도 가진다.
정점 버퍼를 생성하고 파이프라인에 묶기까지 아래와 같은 과정을 거쳐야한다.
- 생성할 버퍼를 서술하는 D3D11_BUFFER_DESC 구조체를 채운다.
- 버퍼의 초기화에 사용할 자료를 서술하는 D3D11_SUBRESOURCE_DATA 구조체를 채운다.
- ID3D11Device::CreateBuffer를 호출해서 버퍼를 생성한다.
- ID3D11DeviceContext::IASetVertexBuffers을 호출하여 정점 버퍼를 파이프라인에 묶는다.(Input Assembler : IA)
1.생성할 버퍼를 서술하는 D3D11_BUFFER_DESC 구조체를 채운다.
D3D11_BUFFER_DESC 구조체는 d3d11.h에서 찾을 수 있다.
typedef struct D3D11_BUFFER_DESC
{
UINT ByteWidth;
D3D11_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
UINT StructureByteStride;
} D3D11_BUFFER_DESC;
1.ByteWidth : 생성할 버퍼의 크기(byte 단위)
2.Usage : 버퍼가 쓰이는 방식(*주 1)
3.BindFlags : 버퍼가 파이프라인에 바인딩되는 방법을 식별(*주 2)
4.CPUAccessFlags : CPU가 버퍼에 접근하는 방식을 식별. CPU가 버퍼를 사용하지 않는다면 0을 지정한다.
5.MiscFlags : 기타 플래그 식별
6.StructureByteStride : 구조적 버퍼에 저장된 원소 하나의 크기. 구조적 버퍼를 위해서만 필요하고, 그 외의 모든 버퍼에 대해서는 0을 지정한다.
2.버퍼의 초기화에 사용할 자료를 서술하는 D3D11_SUBRESOURCE_DATA 구조체를 채운다.
D3D11_SUBRESOURCE_DATA 구조체는 d3d11.h에서 찾을 수 있다.
typedef struct D3D11_SUBRESOURCE_DATA
{
const void *pSysMem;
UINT SysMemPitch;
UINT SysMemSlicePitch;
} D3D11_SUBRESOURCE_DATA;
1.pSysMem : 버퍼를 초기화할 자료를 담은 시스템 메모리 배열을 가리키는 포인터.
2.SysMemPitch : 텍스처의 한 줄 시작에서 다음 줄 까지의 거리(byte)이다. 2D, 3D 텍스처 데이터에서만 사용되고, 나머지에서는 사용하지 않는다.
3.SysMemSlicePitch : 한 깊이 레벨의 시작에서 다음 깊이 레벨까지의 거리(byte)이다. 3D 텍스처 데이터에만 사용된다.
3.ID3D11Device::CreateBuffer를 호출해서 버퍼를 생성한다.
CreateBuffer 함수는 d3d11.h에서 찾을 수 있다.
HRESULT CreateBuffer(
const D3D11_BUFFER_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Buffer** ppBuffer
);
1.pDesc : 생성할 버퍼를 서술하는 구조체
2.pInitialData : 버퍼를 초기화하는 데 사용할 자료
3.ppBuffer : 생성된 버퍼 반환
4.정점 버퍼를 파이프라인에 묶는다.(Input Assembler : IA)
ID3D11DeviceContext::IASetVertexBuffers을 이용하여 묶을 수 있다.
void IASetVertexBuffers(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppVertexBuffers,
const UINT* pStrides,
const UINT* pOffsets
);
1.StartSlot : 정점 버퍼들을 붙이기 시작할 입력 슬롯의 인덱스. 총 16개의 입력 슬롯이 있다.(0 ~ 15)
2.NumBuffers : 입력 슬롯들에 붙이고자 하는 버퍼들의 개수.
3.ppVertexBuffers : 정점 버퍼들을 담은 배열의 첫 원소를 가리키는 포인터
4.pStrides : stride 배열의 첫 원소를 가리키는 포인터. 정점 버퍼의 한 원소의 byte 단위 크기이다.
5.pOffsets : offset 배열의 첫 원소를 가리키는 포인터
위 과정을 코드로 써보자.
struct Vertex
{
XMFLOAT3 Pos;
XMFLOAT4 Color;
};
Vertex vertices[] =
{
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)}
}
//정점 버퍼 구조체 설정
D3D11_BUFFER_DESC desc;
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.ByteWidth = sizeof(Vertex) * 8;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
//버퍼 초기화 설정
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = vertices;
//정점 버퍼 생성
ID3D11Buffer* buffer = NULL;
HR(md3dDevice->CreateBuffer(&desc, &subResource, &buffer);
//생성한 정점 버퍼를 파이프라인에 바인드
UINT stride = sizeof(Vertex);
UINT offset = 0;
md3dImmediateContext->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
정점들의 그리기 연산을 실제로 시작하려면 ID3D11DevcieContext::Draw 메소드를 호출해야한다.
void ID3D11DeviceContext::Draw(UINT VertexCount, UINT StartVertexLocation);
1.VertexCount : 그릴 정점의 수
2.StartVertexLocation : 정점 버퍼의 첫번째 정점의 인덱스
(*주 1)D3D11_USAGE 열거형
렌더링 중 예상되는 리소스 사용을 식별한다. CPU 또는 GPU에서 리소스를 액세스할 수 있는지 여부를 반영한다.
typedef enum D3D11_USAGE
{
D3D11_USAGE_DEFAULT = 0,
D3D11_USAGE_IMMUTABLE = 1,
D3D11_USAGE_DYNAMIC = 2,
D3D11_USAGE_STAGING = 3
} D3D11_USAGE;
(*주 2)D3D11_BIND_FLAG 열거형
리소스를 파이프라인에 바인딩하는 방법을 식별한다.
typedef enum D3D11_BIND_FLAG
{
D3D11_BIND_VERTEX_BUFFER = 0x1L,
D3D11_BIND_INDEX_BUFFER = 0x2L,
D3D11_BIND_CONSTANT_BUFFER = 0x4L,
D3D11_BIND_SHADER_RESOURCE = 0x8L,
D3D11_BIND_STREAM_OUTPUT = 0x10L,
D3D11_BIND_RENDER_TARGET = 0x20L,
D3D11_BIND_DEPTH_STENCIL = 0x40L,
D3D11_BIND_UNORDERED_ACCESS = 0x80L,
D3D11_BIND_DECODER = 0x200L,
D3D11_BIND_VIDEO_ENCODER = 0x400L
} D3D11_BIND_FLAG;
D3D11_BIND_VERTEX_BUFFER : 정점 버퍼
D3D11_BIND_INDEX_BUFFER : 인덱스 버퍼
D3D11_BIND_CONSTANT_BUFFER : 상수 버퍼, 자원을 셰이더에서 사용할 수 있음
D3D11_BIND_SHADER_RESOURCE : 버퍼 혹은 텍스처, 자원을 셰이더에서 사용할 수 있음
D3D11_BIND_STREAM_OUTPUT : 스트림 출력 단계에 대한 출력 버퍼
D3D11_BIND_RENDER_TARGET : 출력 병합(OM) 단계의 결과를 렌더 타겟으로 바인딩
D3D11_BIND_DEPTH_STENCIL : 출력 병합(OM) 단계의 결과를 깊이 스텐실로 바인딩
D3D11_BIND_UNORDERED_ACCESS : 정렬되지 않은 액세스 리소스
D3D11_BIND_DECODER : 디코더 API에서 출력을 수신하는 데 2D 텍스처가 사용됨을 알림
D3D11_BIND_VIDEO_ENCODER : 비디오 인코더 API에서 입력을 수신하는 데 2D 텍스처가 사용됨을 알림
'서적 정리 > DirectX11을 이용한 3D 게임 프로그래밍 입문' 카테고리의 다른 글
48.예제 픽셀 셰이더 (0) | 2022.02.08 |
---|---|
47.상수 버퍼(Constant Buffer) (0) | 2022.02.08 |
46.예제 정점 셰이더 (0) | 2022.02.08 |
45.인덱스와 인덱스 버퍼(Index Buffer) (0) | 2022.02.08 |
43.정점과 입력 배치 (0) | 2022.01.25 |
42.렌더링 파이프라인 요약 (0) | 2022.01.25 |
41.출력 병합기(Output Merger : OM) 단계 (0) | 2022.01.25 |
40.픽셀 셰이더(Pixel Shader : PS) 단계 (0) | 2022.01.25 |
댓글