인덱싱 없이 두 개의 삼각형 그리기 (인덱스 버퍼 사용 이유)
다음 그림에 표시된 쿼드를 그릴 것이라고 가정해 보겠습니다.
삼각형 목록 기본 형식을 사용하여 두 삼각형을 렌더링하는 경우 각 삼각형은 3개의 개별 꼭짓점으로 저장되므로 다음 그림과 비슷한 꼭짓점 버퍼가 생성됩니다.
그리기 호출은 매우 간단합니다. 꼭짓점 버퍼 내의 위치 0부터 시작하여 두 개의 삼각형을 그립니다. 컬링을 사용하도록 설정하면 꼭짓점의 순서가 중요합니다. 이 예제에서는 기본 시계 반대 방향 컬링 상태를 가정하므로 표시되는 삼각형을 시계 방향 순서로 그려야 합니다. 삼각형 목록 기본 형식은 단순히 각 삼각형에 대한 버퍼에서 선형 순서로 세 개의 꼭짓점을 읽으므로 이 호출은 삼각형(0, 1, 2) 및 (3, 4, 5)를 그립니다.
인덱싱을 사용하여 두 개의 삼각형 그리기
여기서 알 수 있듯이 꼭짓점 버퍼에는 위치 0 및 4, 2 및 5의 중복 데이터가 포함됩니다. 두 삼각형이 두 개의 공통 꼭짓점을 공유하기 때문에 의미가 있습니다. 이 중복 데이터는 낭비되며 인덱스 버퍼를 사용하여 꼭짓점 버퍼를 압축할 수 있습니다. 더 작은 꼭짓점 버퍼는 그래픽 어댑터로 보내야 하는 꼭짓점 데이터의 양을 줄입니다. 더욱 중요한 것은 인덱스 버퍼를 사용하면 어댑터가 꼭짓점 캐시에 꼭짓점을 저장할 수 있습니다. 그리는 기본 형식에 최근에 사용한 꼭짓점이 포함되어 있으면 꼭짓점 버퍼에서 읽는 대신 캐시에서 해당 꼭짓점을 가져올 수 있으므로 성능이 크게 향상됩니다.
각 고유 꼭짓점을 꼭짓점 버퍼에 한 번만 저장해야 하므로 인덱스 버퍼가 꼭짓점 버퍼로 '인덱스'됩니다. 다음 다이어그램은 이전 그리기 시나리오에 대한 인덱싱된 접근 방식을 보여 줍니다.
인덱스 버퍼는 꼭짓점 버퍼 내의 특정 꼭짓점을 참조하는 VB 인덱스 값을 저장합니다. 꼭짓점 버퍼는 꼭짓점 배열로 간주될 수 있으므로 VB 인덱스는 단순히 대상 꼭짓점의 꼭짓점 버퍼에 대한 인덱스입니다. 마찬가지로 IB 인덱스는 인덱스 버퍼의 인덱스입니다. 주의하지 않으면 매우 빠르게 혼동될 수 있으므로 사용 중인 어휘에 대해 명확히 확인해야 합니다. 즉, VB 인덱스 값이 꼭짓점 버퍼로 인덱싱되고, IB 인덱스 값이 인덱스 버퍼에 인덱스되고, 인덱스 버퍼 자체가 VB 인덱스 값을 저장합니다.
그리기 호출은 다음과 같습니다. 모든 인수의 의미는 다음 그리기 시나리오에 대해 길이에 따라 설명됩니다. 지금은 이 호출이 Direct3D에 인덱스 버퍼 내의 위치 0부터 시작하여 두 개의 삼각형이 포함된 삼각형 목록을 렌더링하도록 다시 지시합니다. 이 호출은 이전과 정확히 동일한 순서로 동일한 두 개의 삼각형을 그려서 적절한 시계 방향 방향을 보장합니다.
인덱스 버퍼 만들기
인덱스 버퍼를 초기화하려면
1.
인덱스 정보가 포함된 버퍼를 만듭니다.
2.
D3D11_BUFFER_DESC 구조를 입력하여 버퍼 설명을 만듭니다. D3D11_BIND_INDEX_BUFFER 플래그를 BindFlags 멤버에 전달하고 버퍼 크기를 바이트 단위로 ByteWidth 멤버에 전달합니다.
3.
4.
초기화할 ID3D11Buffer 인터페이스에 대한 D3D11_BUFFER_DESC 구조체, D3D11_SUBRESOURCE_DATA 구조체 및 포인터의 주소를 전달하면서 ID3D11Device::CreateBuffer를 호출합니다.
다음 코드 예제에서는 인덱스 버퍼를 만드는 방법을 보여 줍니다. 이 예제에서는
ID3D11Buffer *g_pIndexBuffer = NULL;
// Create indices.
unsigned int indices[] = { 0, 1, 2 };
// Fill in a buffer description.
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof( unsigned int ) * 3;
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
// Define the resource data.
D3D11_SUBRESOURCE_DATA InitData;
InitData.pSysMem = indices;
InitData.SysMemPitch = 0;
InitData.SysMemSlicePitch = 0;
// Create the buffer with the device.
hr = g_pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &g_pIndexBuffer );
if( FAILED( hr ) )
return hr;
// Set the buffer.
g_pd3dContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );
C++
복사
인덱스 버퍼도 버퍼리소스의 한종류이므로 기본적인 생성 방식은 버텍스버퍼와 마찬가지이다
틀린점은 바인드 플래그에 인덱스버퍼로써 바인드한다라는것을 알려주는
D3D11_BIND_INDEX_BUFFER 를 설정해주면 된다
또한 인덱스버퍼는 정수(UINT등)의 단순한 배열이기에 데이터 구조체를 만들 필요는 없다
아래는 인덱스 버퍼 생성 예시 코드이다
상수 버퍼 만들기
피드백
상수 버퍼는 그릴 때 셰이더 단계로 전송할 데이터를 나타냅니다. 일반적으로 모델 뷰 투영 행렬이나 색상, 슬라이더 등과 같은 특정 변수 데이터를 여기에 넣습니다.
상수 버퍼를 초기화하려면
1.
꼭짓점 셰이더 상수 데이터를 설명하는 구조를 정의합니다.
2.
1단계에서 정의한 구조체에 대한 메모리를 할당합니다. 꼭짓점 셰이더 상수 데이터로 이 버퍼를 채웁니다. malloc 또는 new를 사용하여 메모리를 할당하거나 스택에서 구조체에 대한 메모리를 할당할 수 있습니다.
3.
D3D11_BUFFER_DESC 구조를 입력하여 버퍼 설명을 만듭니다. D3D11_BIND_CONSTANT_BUFFER 플래그를 BindFlags 멤버에 전달하고 상수 버퍼 설명 구조체의 크기를 바이트 단위로 ByteWidth 멤버에 전달합니다.
참고
D3D11_BIND_CONSTANT_BUFFER 플래그는 다른 플래그와 결합할 수 없습니다.
4.
D3D11_SUBRESOURCE_DATA 구조를 입력하여 하위 리소스 데이터 설명을 만듭니다. D3D11_SUBRESOURCE_DATA 구조체의 pSysMem 멤버는 2단계에서 만든 꼭짓점 셰이더 상수 데이터를 직접 가리킵니다.
5.
초기화할 ID3D11Buffer 인터페이스에 대한 D3D11_BUFFER_DESC 구조체, D3D11_SUBRESOURCE_DATA 구조체 및 포인터의 주소를 전달하면서 ID3D11Device::CreateBuffer를 호출합니다.
이러한 코드 예제에서는 상수 버퍼를 만드는 방법을 보여 줍니다.
ID3D11Buffer* g_pConstantBuffer11 = NULL;
// Define the constant data used to communicate with shaders.
struct VS_CONSTANT_BUFFER
{
XMFLOAT4X4 mWorldViewProj;
XMFLOAT4 vSomeVectorThatMayBeNeededByASpecificShader;
float fSomeFloatThatMayBeNeededByASpecificShader;
float fTime;
float fSomeFloatThatMayBeNeededByASpecificShader2;
float fSomeFloatThatMayBeNeededByASpecificShader3;
} VS_CONSTANT_BUFFER;
// Supply the vertex shader constant data.
VS_CONSTANT_BUFFER VsConstData;
VsConstData.mWorldViewProj = {...};
VsConstData.vSomeVectorThatMayBeNeededByASpecificShader = XMFLOAT4(1,2,3,4);
VsConstData.fSomeFloatThatMayBeNeededByASpecificShader = 3.0f;
VsConstData.fTime = 1.0f;
VsConstData.fSomeFloatThatMayBeNeededByASpecificShader2 = 2.0f;
VsConstData.fSomeFloatThatMayBeNeededByASpecificShader3 = 4.0f;
// Fill in a buffer description.
D3D11_BUFFER_DESC cbDesc;
cbDesc.ByteWidth = sizeof( VS_CONSTANT_BUFFER );
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDesc.MiscFlags = 0;
cbDesc.StructureByteStride = 0;
// Fill in the subresource data.
D3D11_SUBRESOURCE_DATA InitData;
InitData.pSysMem = &VsConstData;
InitData.SysMemPitch = 0;
InitData.SysMemSlicePitch = 0;
// Create the buffer.
hr = g_pd3dDevice->CreateBuffer( &cbDesc, &InitData,
&g_pConstantBuffer11 );
if( FAILED( hr ) )
return hr;
// Set the buffer.
g_pd3dContext->VSSetConstantBuffers( 0, 1, &g_pConstantBuffer11 );
C++
복사
다음에서는 연결된 HLSL cbuffer 정의를 보여 줍니다.
cbuffer Transform : register(b0)
{
float4 position;
}
C++
복사