1. 3D Direct Application
1.1 Instancing
1.1.1 Instancing
- 한 장면에서 같은 물체를 여러 번 그리되 위치나 방향, 척도, 재질, Texture 등을 다르게 하여 그림
- 각 인스턴스마다 매번 정점 자료와 Index 자료를 파이프라인에 공급하는 것은 낭비
- 물체의 Local Space 공간을 기준으로 한 기하구조 자료의 복사본 하나만 저장 후 필요에 따라 그림
- 메모리가 절감되긴 하지만 물체 당 API 호출 부담을 줄어들지 않음, API 호출 부담이 없도록 인스턴싱을 구현
1.1.1.1 Vertex Shader
- 하드웨어 인스턴싱에서 정점과 Index 자료 외에 각 인스턴스별 자료도 입력 조립기에 공급
- 파이프라인은 그 자료를 이용하여 메시의 인스턴스를 그림
- 인스턴스가 그려질 때 정점 셰이더는 입력 정점, 현재 인스턴스 고유의 자료에도 접근
struct VertexIn
{
/* 기본 자료 */
row_major float4x4 World : WORLD;
float4 Color : COLOR;
uint InstanceId : SV_InstanceID;
};
- 인스턴스 별 세계 행렬, 각 인스턴스를 장면의 각기 다른 위치에 배치
- 인스턴스 별 색상 정보, 각 인스턴스를 다른 위치에 배치
- 현재 인스턴스의 ID, Texture 배열의 색인으로 사용, 각 인스턴스마다 개별적인 Texture 적용 가능
1.1.1.2 Instance Data
- 인스턴스별 자료를 입력 조립기 단계에 공급하기 위해 입력 배치를 통해 정의
typedef struct D3D11_INPUT_ELEMENT_DESC;
- 위의 구조체에서 마지막 두개의 멤버 변수가 인스턴싱과 관련
- 입력 원소를 정점별 자료로서 공급할 것인지, 인스턴스별 자료로 공급할 것인지 결정
- 인스턴스별 자료 원소 하나 당 그릴 인스턴스의 개수
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 64, D3D11_INPUT_PER_INSTANCE_DATA, 1 }
- 준비된 정점 자료와 인스턴스별 자료로 인스턴스를 그릴 때 밑의 함수 적용
void ID3D11DeviceContext::DrawlndexedInstanced;
1.1.1.3 Instance Buffer
void InstancingAndCullingDemo::BuildInstancedBuffer();
- 인스턴스별 자료를 담은 버퍼도 다른 버퍼와 마찬가지로 버퍼 인터페이스를 이용하여 생성
- 모든 인스턴스별 자료를 시스템 메모리에 담아 두고, 인스턴스 버퍼는 동적 버퍼로 생성
- 매 프레임마다 가시적인 인스턴스들의 인스턴스별 자료를 버퍼에 복사
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_DYNAMIC;
vbd.ByteWidth = sizeof(InstancedData) * _instancedData.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vbd.MiscFlags = 0; vbd.StructureByteStride = 0;
HR(_device->CreateBuffer(&vbd, 0, _instancedBuffer.GetAddressOf()));
1.2 Culling
1.2.1 Frustum Culling
- 하드웨어는 삼각형 절단 과정에서 시야 절두체 바같에 있는 삼각형들을 자동으로 폐기
- 파이프라인의 중간 부분에서 일어나므로, 폐기될 삼각형들이 그리기 호출들을 통해 렌더링 파이프라인 제출
- 삼각형들은 모두 정점 셰이더를 거쳐야 하며, 테셀레이션이나 기하 셰이더 단계를 거쳐야 할 수 있음
- 이후 절단 단계에서 폐기, 이처럼 하는 방식은 효율의 낭비
- 응용 프로그램에서 미리 삼각형들을 선별해서 제외시키되 개별 삼각형 기반이 아닌 더 높은 수준의 삼각형들을 선별
- 장면마다 각 물체마다 구나 상자같은 경계입체를 만듦
- 경계입체가 절두체와 교차하는 않는 물체는 그리기 호출을 통해 파이프라인에 제출할 필요X
- 위의 방식을 통해 보이지 않는 기하구조에 대해 계산 낭비하는 일이 줄어듦
- 대신 CPU에서 추가적인 작업을 수행해야 하지만 비용은 상대적으로 저렴
- 카메라의 시야각이 90도이고 먼 평면과의 거리가 무한하다고 할 때, 카메라 절두체는 세계 전체의 1/6만 차지
- 물체들이 장면 전체에서 고르게 배치되어 있다고 할때, 그 물체들 중 5/6가 절두체에 의해 선별
- 두개골 메시의 AABB는 국소 공간에 계산 (AABB는 GameMath Code 참조)
- 절두체와 교차하는 인스턴스에 대해 해당 인스턴스별 자료를 동적 인스턴스 버퍼의 다음 가용 슬롯에 추가 및 증가
- 모든 인스턴스에 적용하고 나면 동적 인스턴스 버퍼의 앞쪽에 모든 가시 인스턴스에 대한 자료가 들어 있는 상태
1.2.2 C++ 응용프로그램
1.2.2.1 Update Scene
- 현재 카메라 행렬에 대해 생성하여 세계 공간으로 변환하는 행렬을 생성
XMVECTOR detView = XMMatrixDeterminant(_camera.View());
XMMATRIX invView = XMMatrixInverse(&detView, _camera.View());
- 인스턴스 버퍼에 자료를 기록하기 위해 시스템 메모리에 매핑
D3D11_MAPPED_SUBRESOURCE mappedData;
_deviceContext->Map(_instancedBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedData);
- 응용프로그램에서 생성된 해골의 개수만큼 설정한 후 데이터를 구별하기 위해 생성
- 이 후 모든 해골에 대해 절두체 안에 존재하는 지 판별
InstancedData* dataView = reinterpret_cast<InstancedData*>(mappedData.pData);
for (uint32 i = 0; i < _instancedData.size(); ++i) { /* ... */ }
- 인스턴스 데이터, 즉 해골의 세계 공간에 대해 행렬을 생성해 역행렬을 하여 물체에 대한 국소 좌표계를 생성
- 카메라의 절두체 안에 포함되는지 확인하기 위해 모두 국소 좌표계로 변경 후 진행
XMMATRIX W = ::XMLoadFloat4x4(&_instancedData[i].World);
XMVECTOR D = ::XMMatrixDeterminant(W);
XMMATRIX invWorld = ::XMMatrixInverse(&D, W);
- 시야 공간에서 역행렬한 행렬로 부터 물체의 국소 공간으로 변환하고 행렬에 대해 분해
- 위의 방식을 통해 카메라의 좌표계에서 물체 즉 해골의 국소 공간의 좌표계로 변경
- 해골의 국소 공간의 좌표계에 카메라의 좌표를 분해
XMMATRIX toLocal = ::XMMatrixMultiply(invView, invWorld);
XMVECTOR scale; XMVECTOR rotQuat; XMVECTOR translation;
::XMMatrixDecompose(&scale, &rotQuat, &translation, toLocal);
- 위의 데이터를 사용하여 카메라 절두체를 시야 공간에서 물체의 국소 공간으로 변환
- 위에서도 말했듯이 국소 좌표계에서 AABB 판정을 하기 위함
BoundingFrustum localspaceFrustum;
_camFrustum.Transform(localspaceFrustum, XMVectorGetX(scale), rotQuat, translation);
- 마지막으로 국소 공간에서 AABB to 절두체 교차 판정을 수행하여 통과가 된다면 정점 버퍼에 기록
if (localspaceFrustum.Contains(_skullBox)) dataView[_visibleObjectCount++] = _instancedData[i];
- 모든 데이터를 처리하고 시스템 메모리를 닫음
_deviceContext->Unmap(_instancedBuffer.Get(), 0);
'C++ Algorithm & Study > Game Math & DirectX 11' 카테고리의 다른 글
[Direct11] 35. 3D Direct Application - Cube Mapping System (0) | 2023.06.27 |
---|---|
[Direct11] 34. 3D Direct Application - Picking System (0) | 2023.06.27 |
[Direct11] 32. 3D Direct Application - Camera (0) | 2023.06.26 |
[Direct11] 31. EX App Program - Quad Tesselation (0) | 2023.06.22 |
[Direct11] 30. Direct3D Tesselation (0) | 2023.06.22 |