휴 ,,, 드디어 성공했다..
큐브맵 자체를 만드는 건 어렵지 않다.
하지만 이전 프로젝트와 큐브맵 프로젝트에서 달라지는 것이 많았다.
매 장 새로운 걸 받아들이는 부분에서 제공해 주는 코드와 비교해 보면 달라지는 부분이 많다
directX12 문법을 이해하고 연관성을 알아야만 큐브맵을 완성할 수 있었다.
1. 큐브맵 cubeMap / 입방체 매핑
큐브맵의 텍스처는 단지 텍스처 여섯 장을 담은 배열이다.
2. 큐브맵 적용하기
🔸1) RootSignature
Texture Cube를 쉐이더와 연결하기 위해 table을 만들어준다.
여기서 빨간색으로 표시한 RootParameterIndex(3)을 Texture Cube로 만들 거고 Init 매개변수 3번째 인자 0이므로 shader에서 t0으로 사용된다.

🔸2). 큐브맵 텍스처/매터리얼 로드하기
🔸3) 서술자 만들기 (DescriptorHeap)

- 계속해서 프로젝트를 새로 만들지 않고 있다면 NumDescriptors의 개수가 늘어나고 있을것이다 .. 쉐이더 리소스 뷰의 개수를 잘 세어서 크기를 지정해 주자.

차원 속성을 D3D12 SRV DIMENSION TEXTURECUBE로 해줘야 한다.
큐브맵만 따로 서술자 힙을 만들어서 할당할 게 아니면 몇 번째 서술자가 TextureCube인지 알아야 하므로 mSkyTexHeapIndex으로 큐브맵 서술자 인덱스를 맵버변수로 가지고 있어야 한다.
🔸4) 파이프라인 만들기

sky pso 만들기
개별적인 셰이더 프로그램들이 쓰이므로 따로 만들어준다.
CullMode: 카메라가 구의 내부에 있기 때문에 후면 선별을 비활성화해야 한다.
skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
DepthFunc: LESS_EQUAL 하늘 구가 깊이 판정을 통과한다.
🔸5) Draw 함수

3번에서 본 mSkyTexHeapIndex 인덱스 7번 DescriptorHeap을 1번에서 본 (RootParameterIndex 3번) 에 연결하겠다. 즉 t0에 디퓨즈 텍스쳐 mSkyTexHeapIndex에 있는 매터리얼 정보를 넣겠다고 받아들이면 된다.
🔸6) 연결한 쉐이더 코드
중요 코드는 아래와 같다.

카메라가 세계 안의 어느 지점으로 가든 하늘 구의 표면에 가까워지거나 멀어지는 일은 없다.
세계 공간에서 하늘 구의 중심을 카메라 위치에 둔다. 그러면 카메라가 움직일 때 하늘 구도 따라 움직이므로 카메라가 하늘 구의 표면에 가까워지지도 멀어지지도 않는다.
3. StructuredBuffer
이제부터 매터리얼을 structuredBuffer에 담아서 관리한다.
(1) - Texture2D gDiffuseMap[8] : register(t1);
(2) - StructuredBuffer<MaterialData> gMaterialData : register(t0, space1);
(1) - Texture2D gDiffuseMap[8] : register(t1);
(2) - StructuredBuffer gMaterialData : register(t0, space 1);
위의 (2)같이 structuredBuffer을 표현할 수 있다. 배열처럼 인덱스 접근해서 사용하고, 위 문법은 재질 자료를 space 1에 배정한다는 뜻이다.
(1) 번의 텍스처 배열은 space 0의 레지스터 t0, t1, t2, ....., t7을 차지한다.
그럼 쉐이더 코드에 StructuredBuffer 매터리얼을 연결하는 방법을 알아보자. (나는 여기서 하루를 다 써버렸다.. 계속되는 오류 때문에.. 해보면 별거 없음.)
1) StructuredBuffer는 constantBuffer가 아니다.
constrantBuffer는 CreateCommittedResource을 만들 때 상수 버퍼의 크기는 하드웨어의 최소 메모리 할당 크기에 배수가 되어야 한다. 그러므로 256배의 수로 올림 해야 한다. 버퍼 크기를 할당하는 부분이 다르니 이 부분을 꼭 !! 챙기자.
(만약, 같은 책으로 공부하시는 분이라면 FrameResource.cpp// std::make_unique(device, materialCount, false); false!! 꼭 false로 바꿔주세요. ~~)
2) RootSignature로 space 1에 연결해 주자.
t0부터 사용하고 싶은데 사용하고 있는 테이블이 있다면, space N에 연결해 준다.

slotRootParameter[2].InitAsShaderResourceView(0, 1);
3) 각 그리는 오브젝트마다 인덱스를 가지고 있는다.
이를 사용하기 위해서는 인덱스 접근을 해야 한다.

- 오브젝트 정보가 담겨있는 업로드 버퍼 정보에 매터리얼 인덱스 정보를 추가한다.

- 매터리얼 빌드시 matCBIndex을 지정하여 내가 사용할 텍스처 즉, 재질 정보가 몇번째 매터리얼인지 지정해 준다.

현재 그려 줄 오브젝트에 매터리얼정보를 업데이트해 주며 hlsl에 연결한다.
환경매핑 해야해서 아직 이 파트 한 발 남았다.
'🎯 game engine > ◽ directX12' 카테고리의 다른 글
[DirectX12] 섀도우 매핑 (shadow mapping), 섀도우 알고리즘 상세 정리 (0) | 2024.12.18 |
---|---|
[DirectX12] 스텐실(stencil) 거울 만들기 (0) | 2024.11.07 |
[DirectX12] 조명의 종류 (0) | 2023.12.19 |
[DirectX12] 조명 연산을 위한 법선 벡터, 법선 벡터의 변환 (0) | 2023.12.14 |
[DirectX12] 원기둥의 정점 찍기/렌더링 과정 이해하기 (1) | 2023.12.12 |
안 하는 것 보다 낫겠지
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!