def sample(self, it, sampler, active=True): bs = BSDFSample.zeros_like(it.p) spectrum = torch.zeros_like(it.p) cos_theta_i = it.wi[..., 2] active = (cos_theta_i > 0) & active f_i = fresnel(cos_theta_i, self.eta)[0] spec_sample_weight = self.spec_sample_weight() p_spec = f_i * spec_sample_weight p_diff = (1 - f_i) * (1 - spec_sample_weight) p_spec = (p_spec) / (p_spec + p_diff) p_diff = 1 - p_spec sample_spec = active & (sampler.sample(p_spec.shape) < p_spec) # sample_diff = active & (~sample_spec) bs.wo = torch.where( sample_spec.unsqueeze(-1), reflect(it.frame[..., 2], it.wi), square_to_cos_hemisphere( sampler.sample(it.shape()[:-1] + (2, ), device=it.device())), ) bs.pdf = torch.where( sample_spec, p_spec, p_diff * square_to_cos_hemisphere_pdf(bs.wo), ).clamp(min=1e-10) f_o = fresnel(bs.wo[..., 2], self.eta)[0] spectrum = torch.where( sample_spec.unsqueeze(-1), self.specular * (f_i/bs.pdf).unsqueeze(-1), self.diffuse.expand_as(it.p) / (1- self.fdr_int) \ * bs.pdf.unsqueeze(-1) * self.inv_eta_2 *\ (1 - f_i.unsqueeze(-1)) * (1 - f_o.unsqueeze(-1)) ) return bs, spectrum
def sample(self, it, sampler, active=True): cos_theta_i = it.wi[..., 2] bs = BSDFSample.zeros_like(it.p) bs.wo = square_to_cos_hemisphere( sampler.sample(it.shape()[:-1] + (2, ), device=it.device())) bs.wo = F.normalize(bs.wo, dim=-1) bs.pdf = square_to_cos_hemisphere_pdf(bs.wo) bs.eta = 1.0 spectrum = self.act(self.mlp(param_rusin2(it.wi, bs.wo))) return bs, spectrum
def eval_and_pdf(self, it, wo, active=True): cos_theta_i = it.wi[..., 2] cos_theta_o = wo[..., 2] #active = (cos_theta_i > 0) & (cos_theta_o > 0) & active spectrum = self.preproc(cos_theta_o.unsqueeze(-1) * self.reflectance) #spectrum[~active] = 0 pdf = square_to_cos_hemisphere_pdf(wo) #pdf[~active] = 0 return spectrum, pdf
def eval_and_pdf(self, it, wo, active=True): cos_theta_i = it.wi[..., 2] cos_theta_o = wo[..., 2] # active = (cos_theta_i > 0) & (cos_theta_o > 0) & active R = reflect(it.frame[..., 2], it.wi) spectral = (R * wo).sum(dim=-1).clamp(min=1e-20).pow(self.min_spec + self.shine.exp()) spectrum = cos_theta_i.unsqueeze(-1) * self.diffuse/math.pi + \ spectral.unsqueeze(-1) * self.specular/math.pi # just a guess of the PDF since it's not physically based pdf = square_to_cos_hemisphere_pdf(wo) #spectrum[~active] = 0 #pdf[~active] = 0 return spectrum, pdf
def sample(self, it, sampler, active=True): cos_theta_i = it.wi[..., 2] bs = BSDFSample.zeros_like(it.p) active = (cos_theta_i > 0) & active if not active.any(): return bs, torch.zeros_like(it.p) bs.wo = square_to_cos_hemisphere( sampler.sample(it.shape()[:-1] + (2, ), device=it.device())) bs.wo = F.normalize(bs.wo, dim=-1) bs.pdf = square_to_cos_hemisphere_pdf(bs.wo) bs.eta = 1.0 bs.sampled_component = 0 # cast spectrum to same shape as interaction spectrum = self.preproc(self.reflectance).expand(*it.shape()).clone() #spectrum[(~active) | (bs.pdf <= 0), :] = 0 return bs, spectrum
def eval_and_pdf(self, it, wo, active=True): cos_theta_i = it.wi[..., 2] cos_theta_o = wo[..., 2] active = (cos_theta_i > 0) & (cos_theta_o > 0) & active f_i = fresnel(cos_theta_i, self.eta)[0] f_o = fresnel(cos_theta_o, self.eta)[0] pdf = square_to_cos_hemisphere_pdf(wo) spectrum = (self.diffuse.expand_as(it.p)/(1 - self.fdr_int)) \ * self.inv_eta_2 * (pdf * (1 - f_i) * (1 - f_o)).unsqueeze(-1) # DeltaReflection ssw = self.spec_sample_weight() prob_specular = ssw * f_i prob_diffuse = (1 - f_i) * (1 - ssw) prob_diffuse = prob_diffuse / (prob_specular + prob_diffuse) pdf = pdf * prob_diffuse #spectrum[~active] = 0 #pdf[~active] = 0 return spectrum, pdf
def sample(self, it, sampler, active=True): cos_theta_i = it.wi[..., 2] bs = BSDFSample.zeros_like(it.p) active = (cos_theta_i > 0) & active if not active.any(): return bs, torch.zeros_like(it.p) bs.wo = square_to_cos_hemisphere( sampler.sample(it.shape()[:-1] + (2, ), device=it.device())) bs.pdf = square_to_cos_hemisphere_pdf(bs.wo) bs.eta = 1.0 bs.sampled_component = 0 # cast spectrum to same shape as interaction cos_theta_o = bs.wo[..., 2] active = (cos_theta_o > 0) & active R = reflect(it.frame[..., 2], it.wi) spectral = (R * bs.wo).sum(dim=-1).clamp( min=1e-20).pow(self.min_spec + self.shine.exp()) spectrum = cos_theta_i.unsqueeze(-1) * self.diffuse/math.pi + \ spectral.unsqueeze(-1) * self.specular/math.pi spectrum[(~active) | (bs.pdf <= 0), :] = 0 return bs, spectrum