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