def sample(self, dir, N, t, i, j, mat_buf, mat_id): next_dir = ti.Vector([0.0, 0.0, 0.0]) w_out = dir cos_theta_i = w_out.dot(N) ior = UF.get_material_ior(mat_buf, mat_id) eta = ior probability = ti.random() f_or_b = 1.0 R = probability + 1.0 extinction = 1.0 if (cos_theta_i > 0.0): N = -N extinction = ti.exp(-0.1*t) else: cos_theta_i = -cos_theta_i eta = 1.0 /ior next_dir,suc = self.refract(w_out, N, eta) if suc > 0.0: R = self.schlick(cos_theta_i, ior) if (probability < R): next_dir = ts.reflect(w_out, N) else: f_or_b = -1.0 return next_dir, f_or_b*extinction
def render_func(self, pos, normal, dir, light_dir): color = ts.vec3(0.0) shineness = self.shineness half_lambert = ts.dot(normal, light_dir) * 0.5 + 0.5 lambert = max(0, ts.dot(normal, light_dir)) blinn_phong = ts.dot(normal, ts.mix(light_dir, -dir, 0.5)) blinn_phong = pow(max(blinn_phong, 0), shineness) refl_dir = ts.reflect(light_dir, normal) phong = -ts.dot(normal, refl_dir) phong = pow(max(phong, 0), shineness) strength = 0.0 if ti.static(self.lambert != 0.0): strength += lambert * self.lambert if ti.static(self.half_lambert != 0.0): strength += half_lambert * self.half_lambert if ti.static(self.blinn_phong != 0.0): strength += blinn_phong * self.blinn_phong if ti.static(self.phong != 0.0): strength += phong * self.phong color = ts.vec3(strength) if ti.static(self.is_normal_map): color = normal * 0.5 + 0.5 return color
def sample(self, dir, N, i, j, mat_buf, mat_id): next_dir = ti.Vector([0.0, 0.0, 0.0]) inout = 1.0 metal = UF.get_material_metallic(mat_buf, mat_id) rough = UF.get_material_roughness(mat_buf, mat_id) diffuseRatio = 0.5 * (1.0 - metal) specularAlpha = max(0.001, rough) probability = ti.random() r1 = ti.random() r2 = ti.random() if (probability < diffuseRatio): next_dir = self.CosineSampleHemisphere(r1, r2) next_dir = self.inverse_transform(next_dir, N) else: phi = r1 * 2.0 * M_PIf cosTheta = ti.sqrt( (1.0 - r2) / (1.0 + (specularAlpha * specularAlpha - 1.0) * r2)) sinTheta = ti.sqrt(1.0 - (cosTheta * cosTheta)) sinPhi = ti.sin(phi) cosPhi = ti.cos(phi) half = ti.Vector([sinTheta * cosPhi, sinTheta * sinPhi, cosTheta]) half = self.inverse_transform(half, N) next_dir = ts.reflect(dir, half) return next_dir, inout
def render_func(self, pos, normal, viewdir, light): # TODO: move render_func to Light.render_func? if ti.static(isinstance(light, Skybox)): dir = ts.reflect(viewdir, normal) dir = v4trans(self.model.scene.camera.L2W[None], dir, 0) return light.sample(dir) * self.specular_color * self.specular else: return Shading.render_func(self, pos, normal, viewdir, light)
def light(lightdir, lightcol, tex, norm, camdir): cosa = ti.pow(0.5 + 0.5 * norm.dot(-lightdir), 2.0) cosr = ti.max((-camdir).dot(ts.reflect(lightdir, norm)), -0.0) diffuse = cosa phong = ti.pow(cosr, 8.0) return lightcol * (tex * diffuse + phong)
def my_render_func(pos, normal, dir, light_dir): n = cartoon_level[None] refl_dir = ts.reflect(light_dir, normal) #refl_dir = ts.mix(light_dir, -dir, 0.5) NoL = pow(ts.dot(normal, refl_dir), 12) NoL = ts.mix(NoL, ts.dot(normal, light_dir) * 0.5 + 0.5, 0.5) strength = 0.2 if any(normal): strength = ti.floor(max(0, NoL * n + 0.5)) / n return ts.vec3(strength)
def get_ambient(camera, normal, view): c_floor = ts.vec3(0.75) c_sky = ts.vec3(0.8, 0.9, 0.95) refl_dir = -ts.reflect(-view, normal) refl_dir = ts.normalize(camera.trans_dir(refl_dir)) color = ts.vec3(ambient) if refl_dir[1] > 0: color *= c_sky else: f = min(1.0, -refl_dir[1] * 25.0) color *= c_sky * (1 - f) + c_floor * f return color
def radiance(self): outdir = ts.vec3(0.0) clr = ts.vec3(0.0) if ti.random() < self.emission: clr = ts.vec3(self.emission_color) elif ti.random() < self.specular: clr = ts.vec3(self.specular_color) outdir = ts.reflect(self.indir, self.normal) elif ti.random() < self.diffuse: clr = ts.vec3(self.diffuse_color) outdir = ts.randUnit3D() if outdir.dot(self.normal) < 0: outdir = -outdir #s = ti.random() #outdir = ts.vec3(ti.sqrt(1 - s**2) * ts.randUnit2D(), s) #outdir = ti.Matrix.cols([self.tangent, self.bitangent, self.normal]) @ outdir return self.pos, outdir, clr
def raycast(self, sampling_rate: float): ''' Produce a rendering. Run compute_entry_exit first! ''' for i, j in self.valid_sample_step_count: # For all pixels for sample_idx in range(self.sample_step_nums[i, j]): look_from = self.cam_pos[None] if self.render_tape[i, j, sample_idx - 1].w < 0.99 and sample_idx < ti.static( self.max_samples): tmax = self.exit[i, j] n_samples = self.sample_step_nums[i, j] ray_len = (tmax - self.entry[i, j]) tmin = self.entry[ i, j] + 0.5 * ray_len / n_samples # Offset tmin as t_start vd = self.rays[i, j] pos = look_from + tl.mix( tmin, tmax, float(sample_idx) / float(n_samples - 1)) * vd # Current Pos light_pos = look_from + tl.vec3(0.0, 1.0, 0.0) intensity = self.sample_volume_trilinear(pos) sample_color = self.apply_transfer_function(intensity) opacity = 1.0 - ti.pow(1.0 - sample_color.w, 1.0 / sampling_rate) # if sample_color.w > 1e-3: normal = self.get_volume_normal(pos) light_dir = ( pos - light_pos).normalized() # Direction to light source n_dot_l = max(normal.dot(light_dir), 0.0) diffuse = self.diffuse * n_dot_l r = tl.reflect(light_dir, normal) # Direction of reflected light r_dot_v = max(r.dot(-vd), 0.0) specular = self.specular * pow(r_dot_v, self.shininess) shaded_color = tl.vec4( ti.min(1.0, diffuse + specular + self.ambient) * sample_color.xyz * opacity * self.light_color, opacity) self.render_tape[i, j, sample_idx] = ( 1.0 - self.render_tape[i, j, sample_idx - 1].w ) * shaded_color + self.render_tape[i, j, sample_idx - 1] self.valid_sample_step_count[i, j] += 1 else: self.render_tape[i, j, sample_idx] = self.render_tape[ i, j, sample_idx - 1]
def raycast_nondiff(self, sampling_rate: float): ''' Raycasts in a non-differentiable (but faster and cleaner) way. Use `get_final_image_nondiff` with this. Args: sampling_rate (float): Sampling rate (multiplier with Nyquist frequence) ''' for i, j in self.valid_sample_step_count: # For all pixels for cnt in range(self.sample_step_nums[i, j]): look_from = self.cam_pos[None] if self.render_tape[i, j, 0].w < 0.99: tmax = self.exit[i, j] n_samples = self.sample_step_nums[i, j] ray_len = (tmax - self.entry[i, j]) tmin = self.entry[ i, j] + 0.5 * ray_len / n_samples # Offset tmin as t_start vd = self.rays[i, j] pos = look_from + tl.mix( tmin, tmax, float(cnt) / float(n_samples - 1)) * vd # Current Pos light_pos = look_from + tl.vec3(0.0, 1.0, 0.0) intensity = self.sample_volume_trilinear(pos) sample_color = self.apply_transfer_function(intensity) opacity = 1.0 - ti.pow(1.0 - sample_color.w, 1.0 / sampling_rate) if sample_color.w > 1e-3: normal = self.get_volume_normal(pos) light_dir = (pos - light_pos).normalized( ) # Direction to light source n_dot_l = max(normal.dot(light_dir), 0.0) diffuse = self.diffuse * n_dot_l r = tl.reflect(light_dir, normal) # Direction of reflected light r_dot_v = max(r.dot(-vd), 0.0) specular = self.specular * pow(r_dot_v, self.shininess) shaded_color = tl.vec4( (diffuse + specular + self.ambient) * sample_color.xyz * opacity * self.light_color, opacity) self.render_tape[ i, j, 0] = (1.0 - self.render_tape[i, j, 0].w ) * shaded_color + self.render_tape[i, j, 0]