(사실 이해했는지 모르겠다. 어렴풋이 느껴질 뿐... 그래도 그 느낌을 정리한다.)
1. CubeMap과 환경 매핑
- 플레이어(카메라) 가까이 Mesh들이 있는 Level이 아니라, 예제 사진처럼 환경을 그려주고, 반사되는 물체에도 적절히 환경 반사상을 그려주어서, 심미적인 효과를 주는 것이 이번 예제의 목표이다.
- 이를 위해서는(예제와 같은 결과가 나오기 위해서는) 주변 환경을 나타내는 6장의 Texture를 가진 환경맵이 필요하고, 해당 텍스쳐의 포맷인 D3D12_SRV_DIMENSION_TEXTURECUBE에서 픽셀을 참조하기 위해 필요한, LookUp 벡터로 샘플링을 해야 한다.
2. TextureCube 맵 과 LookUp Vector
- 일단 환경 자체를 그리는 방법을 먼저 보면, 예제에서는 Player가 있는 Level을 감싸고도 한참 남들 정도로 커다란 Sphere Mesh를 생성하였고, 그 위에 환경 맵을 매핑 하였다.
- CubeMap 포멧 특성을 이용해서 Sphere의 Vertex의 Local Position 자체를 룩업 벡터로 이용하여 Sampling을 하였다.
(벡터의 방향, 성분을 이용해서 6개 중의 텍스쳐에 Cube 위치에 맞는 픽셀을 가져오게 된다.)
- 만약 이것이 무한의 크기를 가진 천구의 역할을 하고 싶다면, NDC 평면에서 항상 먼 평면에 찍히도록 쉐이더에서 Z값을 조정해 주면 된다. (Z = W)
- 이제 물체의 반사상을 그리는 방법의 아이디어는 카메라가 바라보는 방향과, 그 방향이 Model Normal에 따라 반사되는 방향에 따라 Shader에서 계산하고, 그 친구를 LookUp 벡터로 천구에서 Sample을 하는 것이다.
- PassCB로 넘어온 카메라 위치와 hlsl의 reflect() 함수를 이용해서 LookUp Vector를 구할 수 있다.
- 그 벡터로 Sample을 하고 Shader와 Material 정보 (Texture, Fresnel, Roughness 등)에 따라, 의도한 반사상을 Mesh위에 그려준다.
3. CubeMap을 위해 App에서 해줘야 하는 것
- Shader에서는 TextureCube 타입으로 환경 맵 텍스쳐를 받는다. 이를 위해서 Root Signature에서는 새로운 테이블을 만들어주고, 해당 Texture Resource에 대한 View의 ViewDimension은 D3D12_SRV_DIMENSION_TEXTURECUBE으로 새로 생성을 해줘야 한다.
- 환경을 그리는 Shader도 2번에서 언급했듯이, 따로 그려준다.
4. Dynamic CubeMap
- 이미 그려져서 파일로 존재하는 환경 맵 말고도, DrawCall로 그려지는 Model들에 대한 반사상을 그려보는 예제이다.
- 아이디어는 매 프레임 CubeMap을 그리는 것이다. (포맷에 맞게, 상하전후좌우 총 6개의 장면을 그리는 것)
- 간단하게 단계를 정리하면
1) 반사상을 그릴 물체를 중심으로 6개의 방향으로, 모든 물체들을 렌더링 한다.
2) 렌더링 된 결과를 CubeMap으로 이용해서 반사상을 그린다.
3) 이후 다시 메인 카메라에 보이는 물체들을 렌더링 한다.
(만약 Dynamic CubeMap을 이용할 물체가 여러 개라면... 그리고 그 물체들이 서로 반사된다면?? 흠...)
5. Dynamic CubeMap을 위해 App에서 해줘야 하는 것
- ID3D12Resource를 Rtv로는 6개의 Texture2D로 6개의 View를 가지게 하고, Srv으로는 TextureCube로 포맷을 가지도록 view를 생성해줘야 한다.
- 상하전후좌우 방향으로 Render Target으로 하여서 환경맵과 모든 물체의 렌더링을 6번 걸어줘야 한다.
- 카메라의 방향은 6개이고, 반사상을 띄울 물체 또한 카메라의 위치와 다를 수 있기 때문에 Camera 위치가 담긴 PassCB정보 또한 렌더링마다 따로 생성해 주고, 바인드를 해줘야 한다.
- 동적 반사상을 이용하는 모델을 그릴 때는, 6개의 렌더링 된 결과를 쉐이더의 TextureCube에 걸리도록 TextureCube 포맷을 가진 Srv를 SetGraphicsRootDescriptorTable으로 걸어주고 drawcall을 걸면 된다.
- 나머지 정적 반사상을 이용하는 모델을 그릴 때는, 3번처럼 환경 맵이 있는 View를 걸어주고 렌더링을 하면 된다.
6. 언급할 만한 예제에서 사용한 방법(구조)
- 예제에서는 각 방향에 대한 텍스쳐(ID3D12Resource, View Handle)와 레스터라이저 정보(ViewPort, ScissorRect)를 클래스 인스턴스로 관리를 해주었다.
7. 연습 문제
(클릭하면 커집니다.)
연습문제 1
- Roughness와 Fresnel 값을 변경하면서 연습해 보는 것이다.
연습 문제 2
- 새로운 환경맵 이미지로 연습해보는 것이다.
- 여기서 다운로드한 거 적용해 보았다. (Image Source)
Skybox Texture png download - 3600*2700 - Free Transparent Sky png Download. - CleanPNG / KissPNG
- 그리고 Texassemble · microsoft/DirectXTex Wiki (github.com)을 이용했다.
- texassemble을 cmd에서 사용하기 위한 환경변수 설정
- 설정 -> 고급 시스템 설정 -> 고급(탭) -> 환경변수 -> User에 대한 사용자 변수에서 Path -> 편집-> 새로 만들기 --> texassemble.exe가 있는 폴더경로를 추가
연습 문제 3
- reflection이 아니라 refraction을 연습해 보는 예제이다.
- 왼쪽부터 굴절률 비율 (1.0 -> 0.95 -> 0.9)
- 쉐이더 코드 + App 코드
연습 문제 4
- 환경 맵을 이용한 Blurry Reflection이 뭔지 알아보라는 연습문제다.
- Blurry Reflection을 구글에 검색해 보면
- 물에 젖은 바닥이나.. 무튼 울퉁불퉁한 (매끈하지 않은) 곳에서 반사가 일어나는 것을 표현하는 기법을 말하는 듯하다.
- 일단 예전에 Blur예제처럼 BlurRadius에 해당하는 환경맵 픽셀을 샘플링해와서 blurrey reflection을 나타내는 방법이 있다. (이것 말고 더 똑똑한 방법은 나중에 내 실력이 늘면 시도해 보도록 하자.)
8. 메모용
- Chapter 10. Real-Time Computation of Dynamic | NVIDIA Developer
- koulikova.pdf (graphicon.ru)
- CubeMap의 모든 면이 Culling이 적게 이루어지고, 실시간으로 변하는 모습이 다른 모델들과 상호작용 필요가 적은 환경맵으로서 사용하기 좋은 방법이 교재에 소개가 되었다. (지오메트리 쉐이더를 이용한 Dynamic Cube Mapping)
- Texture2DArray 포맷과 SV_RenderTargetArrayIndex를 이용해서 6개의 방향의 Texture를 하나의 CS로직에서 그릴 수 있다고 한다. (책에 있으니 궁금하면 나중에 찾아보자)
- 환경 반사상을 모델 위에 그릴 때 아쉬운 점은, reflect로 계산하여 사용하는 LookUp Vector는 그 Origin이 (0, 0, 0)이다.
- 예제의 경우는 매우 먼 환경을 나타내고, 구의 형태를 하고 있기 때문에 이렇게 대강 계산하여도 어색함이 없지만
- 그다지 크지 않은 육면체 모양의 방의 형태 같은 경우는, 어색한 결과가 나오게 될 수 있다.
- 이를 방지하기 위해서는 reflect로 구한 벡터가 해당 Model에서 쏘아졌을 때로 LookUp 벡터를 다시 계산해서 Sampling을 해야 할 것이다. ( Model의 환경 반사와 Slab Method )
책 : DirectX 12를 이용한 3D 게임 프로그래밍 입문
'Programming > D3D12' 카테고리의 다른 글
[책공부] Shadow Mapping + chap 20 연습 문제 (0) | 2024.03.04 |
---|---|
[책공부] Normal Mapping + chap 19 연습 문제 (0) | 2024.02.27 |
[책공부] Picking + chap 17 연습 문제 (0) | 2024.02.22 |
[책공부] Instancing / Frustum Culling + chap 16 연습 문제 (0) | 2024.02.21 |
[책공부] Dynamic Indexing / FPS Camera + chap 15 연습 문제 (0) | 2024.02.19 |