From d8994e93c8bb175ea99e2dccc50dd85a0ecc8cb4 Mon Sep 17 00:00:00 2001
From: Enigmatisms <984041003@qq.com>
Date: Thu, 1 Jun 2023 18:43:43 +0800
Subject: [PATCH] AdaPT now supports complex scene rendering.
---
bxdf/brdf.py | 2 +-
scene_viz.py | 2 +-
scenes/cbox/kitchen.xml | 322 ++++++++++++++++++++++++++++++++++------
scenes/cbox/smaller.xml | 152 +++++++++++++++++++
tracer/path_tracer.py | 18 +++
5 files changed, 449 insertions(+), 47 deletions(-)
create mode 100644 scenes/cbox/smaller.xml
diff --git a/bxdf/brdf.py b/bxdf/brdf.py
index 48619ed..08dc30f 100644
--- a/bxdf/brdf.py
+++ b/bxdf/brdf.py
@@ -122,7 +122,7 @@ def eval_blinn_phong(self, ray_in: vec3, ray_out: vec3, normal: vec3, tex = INVA
half_way.fill(0.0)
dot_clamp = ti.max(0.0, tm.dot(half_way, normal))
glossy = tm.pow(dot_clamp, self.k_g)
- cosine_term = tm.max(0.0, tm.dot(normal, ray_out))
+ cosine_term = ti.max(0.0, tm.dot(normal, ray_out))
# A modified Phong model (k_d + k_s should be smaller than 1, otherwise not physically plausible)
diffuse_color = ti.select(tex[0] < 0, self.k_d, tex)
return (diffuse_color + self.k_s * (0.5 * (self.k_g + 2.0) * glossy)) * INV_PI * cosine_term
diff --git a/scene_viz.py b/scene_viz.py
index 6ede95e..09fc897 100644
--- a/scene_viz.py
+++ b/scene_viz.py
@@ -131,7 +131,7 @@ def render(self):
ray = self.pix2ray(i, j)
obj_id, normal, _d, _u, _v = self.ray_intersect(ray, self.cam_t[None])
if obj_id >= 0:
- self.pixels[i, j].fill(ti.max(-tm.dot(ray, normal), 0.))
+ self.pixels[i, j].fill(ti.abs(tm.dot(ray, normal)))
else:
self.pixels[i, j].fill(0.0)
diff --git a/scenes/cbox/kitchen.xml b/scenes/cbox/kitchen.xml
index 75547ca..7810d21 100644
--- a/scenes/cbox/kitchen.xml
+++ b/scenes/cbox/kitchen.xml
@@ -5,16 +5,17 @@
-
+
-
+
+
@@ -23,7 +24,7 @@
-
+
@@ -36,38 +37,26 @@
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
@@ -76,56 +65,299 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scenes/cbox/smaller.xml b/scenes/cbox/smaller.xml
new file mode 100644
index 0000000..f7f84cb
--- /dev/null
+++ b/scenes/cbox/smaller.xml
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tracer/path_tracer.py b/tracer/path_tracer.py
index 836f053..88b1c02 100644
--- a/tracer/path_tracer.py
+++ b/tracer/path_tracer.py
@@ -60,6 +60,8 @@ def __init__(self, emitters: List[LightSource], objects: List[ObjDescriptor], pr
self.stratified_sample = prop['stratified_sampling'] # whether to use stratified sampling
self.use_mis = prop['use_mis'] # whether to use multiple importance sampling
self.num_shadow_ray = prop['num_shadow_ray'] # number of shadow samples to trace
+ # two sides BRDF (for some complex scene of which the normals might be incorrectly pointed)
+ self.brdf_two_sides = prop.get('brdf_two_sides', False)
if self.num_shadow_ray > 0:
self.inv_num_shadow_ray = 1. / float(self.num_shadow_ray)
else:
@@ -365,6 +367,10 @@ def sample_new_ray(self,
ret_dir, ret_spec, ret_pdf = self.bsdf_field[idx].medium.sample_new_rays(incid)
else: # surface sampling
if ti.is_active(self.brdf_nodes, idx): # active means the object is attached to BRDF
+ if ti.static(self.brdf_two_sides):
+ dot_res = tm.dot(incid, normal)
+ if dot_res > 0.: # two sides
+ normal *= -1
ret_dir, ret_spec, ret_pdf = self.brdf_field[idx].sample_new_rays(incid, normal, tex)
else: # directly sample surface
ret_dir, ret_spec, ret_pdf = self.bsdf_field[idx].sample_surf_rays(incid, normal, self.world.medium, mode)
@@ -382,6 +388,10 @@ def eval(self, idx: int, incid: vec3, out: vec3, normal: vec3,
ret_spec.fill(self.bsdf_field[idx].medium.eval(incid, out))
else: # surface interaction
if ti.is_active(self.brdf_nodes, idx): # active means the object is attached to BRDF
+ if ti.static(self.brdf_two_sides):
+ dot_res = tm.dot(incid, normal)
+ if dot_res > 0.: # two sides
+ normal *= -1
ret_spec = self.brdf_field[idx].eval(incid, out, normal, tex)
else: # directly evaluate surface
ret_spec = self.bsdf_field[idx].eval_surf(incid, out, normal, self.world.medium, mode, tex)
@@ -392,6 +402,10 @@ def surface_pdf(self, idx: int, outdir: vec3, normal: vec3, incid: vec3, tex: ve
""" Outdir: actual incident ray direction, incid: ray (from camera) """
pdf = 0.
if ti.is_active(self.brdf_nodes, idx): # active means the object is attached to BRDF
+ if ti.static(self.brdf_two_sides):
+ dot_res = tm.dot(incid, normal)
+ if dot_res > 0.: # two sides
+ normal *= -1
pdf = self.brdf_field[idx].get_pdf(outdir, normal, incid, tex)
else:
pdf = self.bsdf_field[idx].get_pdf(outdir, normal, incid, self.world.medium)
@@ -406,6 +420,10 @@ def get_pdf(self, idx: int, incid: vec3, out: vec3, normal: vec3, is_mi: int, in
else:
pdf = self.bsdf_field[idx].medium.eval(incid, out)
else:
+ if ti.static(self.brdf_two_sides):
+ dot_res = tm.dot(incid, normal)
+ if dot_res > 0.: # two sides
+ normal *= -1
pdf = self.surface_pdf(idx, out, normal, incid, tex)
return pdf