대망의 pbr 적용이다.
gui도 있고 카메라도 움직이니깐
아주 든든해서 편하게 변수들만 바꿔야지 생각했는데
막상 시작하려니깐 그 바꿔야할 양에 압도당했다...
추가해야할 요소가 많아서 미리 설계를 하고 들어가지 않으면 안된다!
일단 했던거 복습
Scene에 Object들이 있다.
Object는 name(imgui layer 구분용도), model (mesh), texture, position, rotate, scale이 있다.
예시코드)
m_objects.push_back(Object::createObject("box1", m_boxModel, m_sampleTexture,
glm::vec3(-2.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)));
현재 renderpass에는 두가지 subpass가 있다. geometry pass(이하 geo pass)와 lighting pass (이하 light pass)이고
각 요소들이 지금 주고 받는 attachment가 3개,
geo pass에서 position, normal, albedo를 계산해 light pass가 받아서 빛을 계산하고있고
지금은 여기에 빛의 위치만 받아서 phong shading을 구현하였다.
써보니 지금까지 했던게 초라해 보이긴 한데 여하튼
이제 우리의 목표는 pbr이고 이걸 deferred shading으로 구현하려고 하니
추가되어야 할 요소가 많다.
그래서 일단 추가 요소 정리.
설명없이 나열만 하겠다. 지금은 구조 설계가 우선이니 각 요소의 설명은 실제 구현해놓고 써야겠다.
albedo (or texture), normal (or normal map), roughness (or texture),
metallic (or texture), height map, ao map
6가지 혹은 10가지 정도이다.
괄호에 texture라 써져있는 부분은 오브젝트의 각 부분마다 다른 값을 주고 싶을 때 텍스쳐로 줄 수도 있는 부분이다.
상수값으로 전반적인 오브젝트의 속성을 결정할 수도 있고 아니면 texture를 줄 수도 있어서
flag 사용이 반 필수적일 거 같다.
첫번째로 고민한 부분은
이 모든 요소가 사실 light pass에서 사용되겠지만 light pass로 바로 값을 주지 못한다는 점에 있다.
뭐 이미 phong shading으로 적용할 때도 했지만 light pass는 그릴 물체가 어떤 물체인지 모르고 그냥 냅다 픽셀에 있는 정보만으로 색을 계산한다는 특성 때문에 geo pass에서 픽셀에 정보들을 줘야 light pass는 그걸 보고 그린다.
근데 이제 줘야할 정보들이 많으니 attachment가
position, normal, albedo, roughness, metallic, height, ao 만큼 늘어난다.
또한 position을 제외한 다른 attachment는 이걸 어떤 거를 써야할지 정보도 가지고 있어야하는데
그걸 전부 lightpass 에서 판단하면 그 flag 수만큼 lightpass에 줘야할 정보가 늘어나니
이 요소들은 geo pass에서 판단해서 light pass는 진짜 정보들만 받아서 빛을 계산하는 걸로 하고
그렇다면 attachment는 총 7개가 된다. (줄일 수 있는 방법이 있는데 가시성을 위해 일단은 이렇게 진행해야겠다.)
그래서 이제 light pass는 픽스 됐다.
* light pass는 값의 진위 여부를 판단할 필요없이 그대로 7개의 attachment들을 모두 사용해 픽셀의 색을 계산한다.
geo pass는 상수 값을 쓸지 texture를 쓸지 결정하는 역할도 해야한다.
여기서 고민한게 descriptorset을 만드는 부분에서, 그니깐 cpu에서 판단해서 미리 결정해버릴 수도 있고
아니면 descriptorset에는 값을 다 넣어주고 uniform으로 flag를 넣어 geo pass에서 판단해줄 수도 있다고 생각했는데
우리는 게임엔진이니 런타임 중 texture나 다른 요소들 교체를 고려해야 하는데
그때 cpu에서 판단하여 처리하는게 훨씬 귀찮아질거 같아
일단 상수값 + texture를 넣어두고 uniform에 flag를 넣어 flag로 geo pass에서 결정하는 것으로 결정!
그럼 geo pass는 input 요소가
albedo, albedo texture, albedo flag
normal map, normal flag
roughtness, roughness texture, roughness flag
metallic, metallic texture, metallic flag
height texture, height flag
ao texture, ao flag
+
position, normal, texcoord 가 있다.
좀 더 자세하게 보자면
normal map은 TBN 때문에 vertex shader에서 구별되어야 하고
나머지는 fragment shader에서 구별하자
또 런타임 중 flag를 잘 못 바꿨을 때 엔진자체가 터지는 걸 방지해주기위해
상수값을 쓴다해도 texture에 default texture를 넣어줘야 의도치 않은 예외를 방지해 줄 수 있겠다.
* geo pass 만들 때 위의 구성 요소 고려하자!
* default texture 만들자!
자 그럼 shader는 만들어 졌다고 치고
이 요소들이 저장될 객체가 필요하다
object를 pbr에 맞춰 변경해야한다.
구조를 짜봤을 때
- name
- transform (position, rotate, scale)
- model (mesh)
- material
로 간단화 시키고
material class가 추가 된다!
material class는
- albedo
- albedo texture
- albedo flag
- normal map
- normal flag
- roughness
- roughness flag
- metallic
- metallic texture
- metallic flag
- height map
- height flag
- ao map
- ao flag
가 있을 예정이다.
그럼 여기서 생성해줄때 default texture를 넣어줄 꺼냐 아니면 생성 때는 null 박아두고
descriptor set에서 flag를 보고 default texture을 박을꺼냐 정해야하는데..
생성 때 default texture를 박자.
+ default texture의 관리 주체를 정해야하는데 딱 생각났을 때는 renderer가 맞는데
지금 구조가 scene이 초기화 될 때 object를 만들고 이때 material를 만들게 될텐데
관리 주체가 renderer라면 scene과의 한번 소통을 또 해야돼서
일단은 scene이 관리주체가 되보자
나중에 바꾸면 되지 뭐
* 생성할 때 저 요소가 하나하나 넣어주기 어지러우니깐 구조체를 활용하자!
이제 단계별로 pbr 적용 시켜보자
1. material 클래스 만들기
2. object 클래스 수정
3. default texture 만들기 -> 기존 shader로 확인하기
4. shader 변경
5. descriptorset layout 변경 + framebuffer 변경
6. uniform buffer + descriptorset 변경
7. renderpass 변경
8. pipeline 변경 (할 게 없을 수도 있다)
9. rendering 로직 변경
하고 오겠다!
'Computer Graphics > Vulkan' 카테고리의 다른 글
Vulkan - 11. gltf 형식의 모델 로드, normal map 수정 (0) | 2025.01.14 |
---|---|
Vulkan - 10. pbr 적용 (0) | 2025.01.07 |
Vulkan - 8. 키보드 마우스 입력 추가와 imgui 적용 (1) | 2025.01.02 |
Vulkan - 7. deferred shading + phong shading 삽질 기록들 (0) | 2024.12.30 |
Vulkan - 6. deferred shading + phong shading 구현 (code) (0) | 2024.12.30 |