GameChoi
Choi Programming
GameChoi
전체 방문자
오늘
어제
  • 분류 전체보기 (468)
    • C++ Algorithm & Study (184)
      • C++ & Algorithm Strategies (45)
      • Game Math & DirectX 11 (72)
      • Server + UE5 (29)
      • Lyra Clone Coding (37)
    • Create Game (284)
      • [Window API] Game Client & .. (55)
      • [DirectX] DirectX 2D & 3D (155)
      • [UE5] BLUEPRINT & C++ (74)
    • odds and ends (0)
      • English (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • client
  • RPG Game
  • Game Server
  • core
  • GAME Client
  • Direct3D
  • server
  • UE5
  • Other Character
  • Player State
  • Direct11
  • Game Room
  • Destination Move Packet
  • Player Move Packet
  • session
  • Algorithm Strategies
  • Network Worker
  • c++
  • job queue
  • protobuf

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
GameChoi

Choi Programming

[Direct11] 33. 3D Direct Application - Instancing & Culling
C++ Algorithm & Study/Game Math & DirectX 11

[Direct11] 33. 3D Direct Application - Instancing & Culling

2023. 6. 26. 19:06

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
    'C++ Algorithm & Study/Game Math & DirectX 11' 카테고리의 다른 글
    • [Direct11] 35. 3D Direct Application - Cube Mapping System
    • [Direct11] 34. 3D Direct Application - Picking System
    • [Direct11] 32. 3D Direct Application - Camera
    • [Direct11] 31. EX App Program - Quad Tesselation
    GameChoi
    GameChoi

    티스토리툴바