원래 작업하던 (reflection, gi)이 있었기 때문에 그리 많이 바꿀 필요는 없었다.
대신 .pbrt 파일을 파싱하는 과정이 필요했는데
모든 파일을 전부 대응하게 하는것은 예외도 많고 엄청나게 고생할 거 같아
원래 레퍼런스로 잡은 bathroom.pbrt 만 대응하도록 방향을 바꿨다.
.pbrt파일 자체가 게임 오브젝트처럼 모든 재질에 대해 동일한 파라미터(roughness, metalic) 로 표현되는게 아니라
재질자체의 속성이 이미 정해져있어서 그거에 맞는 파라미터만 있거나 파라미터가 재질에 따라 다르다
예)
# small bottle by the tub
MakeNamedMaterial "etiquette"
"float uroughness" [ 0.0104080001 ]
"float vroughness" [ 0.0104080001 ]
"string type" [ "glass" ]
# black seam around top of tub
MakeNamedMaterial "jointure_noire"
"float roughness" [ 0.1 ]
"string type" [ "plastic" ]
"rgb Kd" [ .04 .04 .04 ]
"rgb Ks" [ 0.5 0.5 0.5 ]
# walls
MakeNamedMaterial "latte"
#"string type" "fourier" "string bsdffile" "bsdfs/ceramic.bsdf"
"string type" "matte"
"color Kd" [ .55 .5 .5 ]
"float sigma" 20
bathroom.pbrt 파일안의 일부이고
각각 유리, 플라스틱, 매트 재질이다. 또 다른 재질들도 있다.
이걸 파싱해 gpu로 올리는 과정에 꽤나 애를 먹었는데
모든 재질을 통합적으로 관리하면 재질마다 쓸모없는 메모리가 생겨버리니깐
struct MaterialGPU {
int type;
int index;
float pad0;
float pad1;
};
struct MirrorGPU {
vec3 Kr;
float pad0;
int KrIdx;
float pad1;
float pad2;
float pad3;
};
struct PlasticGPU {
vec3 Kd;
float pad0;
vec3 Ks;
float pad1;
int KdIdx;
int KsIdx;
float roughness;
int roughnessIdx;
int remaproughness;
float pad2;
float pad3;
float pad4;
};
struct ShapeGPU {
mat4 modelMatrix;
uint64_t vertexAddress;
uint64_t indexAddress;
int materialIdx;
int areaLightIdx;
int alphaIdx;
int shadowAlphaIdx;
int reverseOrientation;
float pad0;
float pad1;
float pad2;
};
layout(set = 1, binding = 0) readonly buffer instanceBuffer {
ShapeGPU instances[];
};
layout(set = 2, binding = 0) readonly buffer AreaLightBuffer {
AreaLightGPU lights[];
};
layout(set = 2, binding = 1) readonly buffer MaterialBuffer {
MaterialGPU materials[];
};
layout(set = 2, binding = 2) readonly buffer UberBuffer {
UberGPU ubers[];
};
layout(set = 2, binding = 3) readonly buffer MatteBuffer {
MatteGPU mattes[];
};
이런식으로 각 재질에 대한 구조체 배열로 적재한 후
제일 윗단(Shape)에서 material 인덱스를 참조해 그 정보를 가져오는 형식으로 했다.
shape 구조체는 .pbrt파일에서 있는 정보인데 모양을 가지고 있는 모든 오브젝트에 대응되고
이게 재질이 있는 오브젝트 뿐만 아니라 areaLight도 있어서 결국 이 방식을 그대로 채용할 수 밖에 없었다.
현재는 완전 나이브하게 화면에서 레이를 쏘고 코싸인 헤미스피어 샘플링만 사용하여 렌더링을 해봤다.
결과적으로 모든 오브젝트가 매트하게 나오는 결과가 나왔고 예상했던 결과였다.


앞으로 방향)
- 샘플링 개선 예정
현재는 미러를 제외한 모든 재질에서 코사인 헤미스피어 샘플링만 사용하고 있는데
앞으로 각 재질의 반사 모델에 맞춰 BRDF에 맞는 샘플링으로 개선할 예정 - 스펙트럼 데이터 보정 문제
.pbrt 파일을 읽어오는 라이브러리를 직접 구현하지 않고 외부 라이브러리(minipbrt)를 사용했는데,
이 파서에서 스펙트럼 → XYZ → RGB 변환이 잘못되어 받아오는 조명 데이터가 정확하지 않은 문제가 있는거 같다.
현재는 임시 보정을 통해 사용 중- 정면 조명 (6500K, 100) = 차가운 밝은 조명
- 천장 조명 (2700K, 10) = 따뜻하고 약한 조명
으로 설정되었지만,
내 결과에선 천장 조명이 과하게 강조되어 레퍼런스보다 붉은 느낌이다.
정확한 스펙트럼 변환 및 보정을 통해 해결할 예정
'Computer Graphics > VulkanPT' 카테고리의 다른 글
| pt - 3. rendering equation 개념 정리 + 현재 문제들 (0) | 2025.04.29 |
|---|---|
| pt - 2. 재질에 따른 brdf 공식 적용 (0) | 2025.04.29 |
| pt - 0. path tracing 렌더러 시작 (2) | 2025.04.25 |
| BRDF 정리 (1) | 2025.04.22 |
| The Rendering Equation 정리 (0) | 2025.04.21 |