mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 19:23:03 +02:00
* works for cornell now, will be extended to import others * works for all scenes * can load environments and blur them * minor cleanup * Example commands added to README.md
100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
from ..utils.constants import *
|
|
from ..utils.vector3 import vec3, rgb, extract
|
|
from ..utils.random import spherical_caps_pdf, cosine_pdf, mixed_pdf
|
|
from functools import reduce as reduce
|
|
from ..ray import Ray, get_raycolor
|
|
from .. import lights
|
|
import numpy as np
|
|
from . import Material
|
|
from ..textures import *
|
|
|
|
class Diffuse(Material):
|
|
def __init__(self, diff_color, diffuse_rays = 20, ambient_weight = 0.5, **kwargs):
|
|
super().__init__(**kwargs)
|
|
|
|
if isinstance(diff_color, vec3):
|
|
self.diff_texture = solid_color(diff_color)
|
|
elif isinstance(diff_color, texture):
|
|
self.diff_texture = diff_color
|
|
|
|
self.diffuse_rays = diffuse_rays
|
|
self.max_diffuse_reflections = 2
|
|
self.ambient_weight = ambient_weight
|
|
|
|
def get_color(self, scene, ray, hit):
|
|
|
|
hit.point = (ray.origin + ray.dir * hit.distance) # intersection point
|
|
N = hit.material.get_Normal(hit) # normal
|
|
|
|
diff_color = self.diff_texture.get_color(hit)
|
|
|
|
|
|
color = rgb(0.,0.,0.)
|
|
|
|
if ray.diffuse_reflections < 1:
|
|
|
|
|
|
nudged = hit.point + N * .000001
|
|
N_repeated = N.repeat(self.diffuse_rays)
|
|
|
|
|
|
if ray.n.shape() == 1:
|
|
n_repeated = ray.n
|
|
else:
|
|
n_repeated = ray.n.repeat(self.diffuse_rays)
|
|
|
|
nudged_repeated = nudged.repeat(self.diffuse_rays)
|
|
hit_repeated = hit.point.repeat(self.diffuse_rays)
|
|
|
|
|
|
size = N.shape()[0] * self.diffuse_rays
|
|
|
|
pdf1 = cosine_pdf(size, N_repeated)
|
|
pdf2 = spherical_caps_pdf(size, nudged_repeated, scene.importance_sampled_list)
|
|
|
|
s_pdf = None
|
|
if scene.importance_sampled_list == []:
|
|
s_pdf = cosine_pdf(size, N_repeated)
|
|
else:
|
|
s_pdf = mixed_pdf(size, pdf1, pdf2, self.ambient_weight)
|
|
|
|
ray_dir = s_pdf.generate()
|
|
PDF_val = s_pdf.value(ray_dir)
|
|
|
|
NdotL = np.clip(ray_dir.dot(N_repeated),0.,1.)
|
|
color_temp = get_raycolor(Ray(nudged_repeated, ray_dir, ray.depth + 1, n_repeated, ray.reflections + 1, ray.transmissions, ray.diffuse_reflections + 1), scene)
|
|
color_temp = color_temp * NdotL / PDF_val / (np.pi) # diff_color/np.pi = Lambertian BRDF
|
|
color += diff_color * color_temp.reshape(N.shape()[0], self.diffuse_rays).mean(axis = 1)
|
|
|
|
return color
|
|
|
|
elif ray.diffuse_reflections < self.max_diffuse_reflections:
|
|
|
|
"""
|
|
when ray.diffuse_reflections > 1 we just call one diffuse ray to solve rendering equation (otherwise is too slow)
|
|
"""
|
|
|
|
nudged = hit.point + N * .000001
|
|
size = N.shape()[0]
|
|
s_pdf = None
|
|
|
|
pdf1 = cosine_pdf(size, N)
|
|
pdf2 = spherical_caps_pdf(size, nudged, scene.importance_sampled_list)
|
|
|
|
if scene.importance_sampled_list == []:
|
|
s_pdf = cosine_pdf(size, N)
|
|
else:
|
|
s_pdf = mixed_pdf(size, pdf1, pdf2, self.ambient_weight)
|
|
|
|
ray_dir = s_pdf.generate()
|
|
PDF_val = s_pdf.value(ray_dir)
|
|
|
|
NdotL = np.clip(N.dot(ray_dir),0.,1.)
|
|
color_temp = diff_color * get_raycolor(Ray(nudged, ray_dir, ray.depth + 1, ray.n, ray.reflections + 1, ray.transmissions, ray.diffuse_reflections + 1), scene)
|
|
color = color_temp * NdotL / PDF_val / (np.pi)
|
|
|
|
return color
|
|
|
|
else:
|
|
return color
|