diff --git a/examples/assets/normal_map_cornell_box/Bricks092_1K-JPG.mtlx b/examples/assets/normal_map_cornell_box/Bricks092_1K-JPG.mtlx
new file mode 100644
index 0000000..a2a41ae
--- /dev/null
+++ b/examples/assets/normal_map_cornell_box/Bricks092_1K-JPG.mtlx
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/assets/normal_map_cornell_box/Bricks092_1K-JPG.usdc b/examples/assets/normal_map_cornell_box/Bricks092_1K-JPG.usdc
new file mode 100644
index 0000000..7ab300a
Binary files /dev/null and b/examples/assets/normal_map_cornell_box/Bricks092_1K-JPG.usdc differ
diff --git a/examples/normal_map_cornell_box.cpp b/examples/normal_map_cornell_box.cpp
index ee41d70..875cc95 100644
--- a/examples/normal_map_cornell_box.cpp
+++ b/examples/normal_map_cornell_box.cpp
@@ -1,13 +1,6 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
#include
+#include
#include
#include
#include
@@ -223,31 +216,48 @@ void setup_cornell_box() {
metal_material->set_type(MaterialType::METAL);
uint metal_id = g_scene->add_material(metal_material);
- // 5: Textured material with normal map (for short box)
+ // 5: Textured material with PBR textures (for short box)
auto textured_material = std::make_shared();
- textured_material->set_albedo(Vec3(1.0f, 1.0f, 1.0f));
- textured_material->set_metallic(1.0f);
- textured_material->set_roughness(1.0f);
- // textured_material->set_type(MaterialType::DIFFUSE);
- textured_material->set_type(MaterialType::METAL);
+ textured_material->set_albedo(Vec3(1.0f, 0.0f, 1.0f));
+ metal_material->set_metallic(1.0f);
+ metal_material->set_roughness(0.0f);
+ // textured_material->set_metallic(0.0f);
+ // textured_material->set_roughness(0.0f);
+ textured_material->set_type(MaterialType::DIFFUSE);
- // Load textures
- // auto albedo_tex = std::make_shared();
- // if (albedo_tex->load_from_file("examples/assets/normal_map_cornell_box/albedo.png")) {
- // textured_material->set_albedo_texture(albedo_tex);
- // ARE_LOG_INFO("Loaded albedo texture");
- // } else {
- // ARE_LOG_WARN("Failed to load albedo texture");
- // }
+ // Load PBR textures
+ auto albedo_tex = std::make_shared();
+ if (albedo_tex->load_from_file("examples/assets/normal_map_cornell_box/Bricks092_1K-JPG_Color.jpg")) {
+ textured_material->set_albedo_texture(albedo_tex);
+ ARE_LOG_INFO("Loaded albedo texture");
+ } else {
+ ARE_LOG_WARN("Failed to load albedo texture");
+ }
auto normal_tex = std::make_shared();
- if (normal_tex->load_from_file("examples/assets/normal_map_cornell_box/normal.png")) {
+ if (normal_tex->load_from_file("examples/assets/normal_map_cornell_box/Bricks092_1K-JPG_NormalGL.jpg")) {
textured_material->set_normal_texture(normal_tex);
ARE_LOG_INFO("Loaded normal texture");
} else {
ARE_LOG_WARN("Failed to load normal texture");
}
+ auto roughness_tex = std::make_shared();
+ if (roughness_tex->load_from_file("examples/assets/normal_map_cornell_box/Bricks092_1K-JPG_Roughness.jpg")) {
+ textured_material->set_roughness_texture(roughness_tex);
+ ARE_LOG_INFO("Loaded roughness texture");
+ } else {
+ ARE_LOG_WARN("Failed to load roughness texture");
+ }
+
+ auto ao_tex = std::make_shared();
+ if (ao_tex->load_from_file("examples/assets/normal_map_cornell_box/Bricks092_1K-JPG_AmbientOcclusion.jpg")) {
+ textured_material->set_ao_texture(ao_tex);
+ ARE_LOG_INFO("Loaded AO texture");
+ } else {
+ ARE_LOG_WARN("Failed to load AO texture");
+ }
+
uint textured_id = g_scene->add_material(textured_material);
// 6: Glass/Dielectric (refraction)
@@ -298,7 +308,7 @@ void setup_cornell_box() {
Vec3(room_size, -room_size, -room_size),
Vec3(0.0f, 0.0f, 1.0f),
metal_id);
- // white_id);
+ // white_id);
back_wall->upload_to_gpu();
g_scene->add_mesh(back_wall);
diff --git a/shaders/raytracing.comp b/shaders/raytracing.comp
index 3b931b1..ae32e13 100644
--- a/shaders/raytracing.comp
+++ b/shaders/raytracing.comp
@@ -43,8 +43,8 @@ struct Material {
float roughness;
int type;
float ior;
+ float ao; // ambient occlusion
float padding1;
- float padding2;
uint texture_handles[6];
};
@@ -458,9 +458,9 @@ vec3 apply_normal_map(vec3 normal, vec2 texcoord, vec3 tangent, uint normal_hand
void apply_material_textures(inout Material mat, inout vec3 normal, vec2 texcoord, vec3 tangent) {
if (!u_enable_textures) return;
- // Albedo texture
+ // Albedo texture (replace)
if (mat.texture_handles[0] != 0) {
- mat.albedo *= sample_texture_array(0, int(mat.texture_handles[0]), texcoord).rgb;
+ mat.albedo = sample_texture_array(0, int(mat.texture_handles[0]), texcoord).rgb;
}
// Normal map
@@ -468,25 +468,24 @@ void apply_material_textures(inout Material mat, inout vec3 normal, vec2 texcoor
normal = apply_normal_map(normal, texcoord, tangent, mat.texture_handles[1]);
}
- // Metallic texture
+ // Metallic texture (replace)
if (mat.texture_handles[2] != 0) {
- mat.metallic *= sample_texture_array(2, int(mat.texture_handles[2]), texcoord).r;
+ mat.metallic = sample_texture_array(2, int(mat.texture_handles[2]), texcoord).r;
}
- // Roughness texture
+ // Roughness texture (replace)
if (mat.texture_handles[3] != 0) {
- mat.roughness *= sample_texture_array(3, int(mat.texture_handles[3]), texcoord).r;
+ mat.roughness = sample_texture_array(3, int(mat.texture_handles[3]), texcoord).r;
}
- // AO texture (multiply)
+ // AO texture (store in material, apply during lighting)
if (mat.texture_handles[4] != 0) {
- float ao = sample_texture_array(4, int(mat.texture_handles[4]), texcoord).r;
- mat.albedo *= ao;
+ mat.ao = sample_texture_array(4, int(mat.texture_handles[4]), texcoord).r;
}
- // Emission texture (add)
+ // Emission texture (replace)
if (mat.texture_handles[5] != 0) {
- mat.emission += sample_texture_array(5, int(mat.texture_handles[5]), texcoord).rgb;
+ mat.emission = sample_texture_array(5, int(mat.texture_handles[5]), texcoord).rgb;
}
}
@@ -623,7 +622,8 @@ vec3 eval_direct_lighting(inout HitInfo hit, Material mat, inout uint seed) {
float pdf_light = 1.0 / float(u_light_count);
vec3 brdf = mat.albedo * INV_PI;
- return brdf * radiance * n_dot_l / max(pdf_light, EPSILON);
+ // Apply AO to the final lighting
+ return brdf * radiance * n_dot_l * mat.ao / max(pdf_light, EPSILON);
}
// ============================================================================
@@ -641,6 +641,7 @@ Material fetch_material(uint material_id) {
m.roughness = 0.5;
m.type = MATERIAL_DIFFUSE;
m.ior = 1.5;
+ m.ao = 1.0; // default: no AO
return m;
}
diff --git a/src/core/raytracer.cpp b/src/core/raytracer.cpp
index 38cd735..1945ca8 100644
--- a/src/core/raytracer.cpp
+++ b/src/core/raytracer.cpp
@@ -306,8 +306,8 @@ void RayTracer::upload_scene_data_(const Scene &scene) {
float roughness;
int type;
float ior;
+ float ao;
float padding1;
- float padding2;
uint texture_handles[6];
};
@@ -322,6 +322,7 @@ void RayTracer::upload_scene_data_(const Scene &scene) {
data.roughness = mat->get_roughness();
data.type = static_cast(mat->get_type());
data.ior = mat->get_ior();
+ data.ao = 1.0f; // default: no AO
// Texture array indices (0 = no texture, 1+ = index into array)
data.texture_handles[0] = mat->get_texture_index(TextureSlot::ALBEDO);