WUT_Computer_Science/Programming/TRAK/sightpy/materials/thin_film_interference.py
2026-02-06 22:15:36 +01:00

67 lines
3.0 KiB
Python

from ..utils.constants import *
from ..utils.vector3 import vec3, rgb, extract
from functools import reduce as reduce
from ..ray import Ray, get_raycolor
from .. import lights
import numpy as np
from . import Material
from ..utils.image_functions import load_image
class ThinFilmInterference(Material):
def __init__(self, thickness, noise = 0.,**kwargs):
super().__init__(**kwargs)
self.thickness = thickness
# precomputed reflectance vs cosθI (vertical axis) and thickness (horizontal axis)
self.thin_film_interference_reflectance = load_image("sightpy/textures/thin_film_interference_n=1.4.png")
self.thickness_noise = load_image("sightpy/textures/noise.png")
self.thickness_noise = (self.thickness_noise[:,:,0])
self.noise_factor = noise
def get_color(self, scene, ray, hit):
hit.point = (ray.origin + ray.dir * hit.distance) # intersection point
N = hit.material.get_Normal(hit) # normal
# Ambient
color = rgb(0.,0.,0.)
V = ray.dir*-1. # direction to ray origin
if ray.depth < hit.surface.max_ray_depth:
"""
if hit_orientation== UPWARDS:
#ray enter in the material
if hit_orientation== UPDOWN:
#ray get out of the material
"""
cosθi = V.dot(N)
u,v = hit.get_uv()
thickness = self.thickness
if self.noise_factor != 0.:
thickness += self.noise_factor*(self.thickness_noise[-((v * self.thickness_noise.shape[0]*0.5 ).astype(int)% self.thickness_noise.shape[0]) , (u * self.thickness_noise.shape[1]*0.5).astype(int) % self.thickness_noise.shape[1] ].T - 0.5)
Fim = self.thin_film_interference_reflectance[(cosθi* self.thin_film_interference_reflectance.shape[0]).astype(int), thickness.astype(int) ]
else:
Fim = self.thin_film_interference_reflectance[(cosθi* self.thin_film_interference_reflectance.shape[0]).astype(int), int(thickness) ]
F = vec3(Fim[:,0],Fim[:,1],Fim[:,2])
# compute reflection
reflected_ray_dir = (ray.dir - N * 2. * ray.dir.dot(N)).normalize()
nudged = hit.point + N * .000001 # M nudged to avoid itself
color += (scene.ambient_color + get_raycolor(Ray(nudged, reflected_ray_dir, ray.depth + 1, ray.n, ray.reflections + 1, ray.transmissions, ray.diffuse_reflections), scene))*F
# because the film is very thin (nm) we ignore refraction for transmitted ray.
transmitted_ray_dir = ray.dir
nudged = hit.point - N * .000001 #nudged for transmitted ray
T = 1. - F
transmitted_color = get_raycolor( Ray(nudged, transmitted_ray_dir, ray.depth + 1, ray.n, ray.reflections, ray.transmissions + 1, ray.diffuse_reflections), scene )*T
color += transmitted_color
return color