(in-package :fwoar.lisp-sandbox.material)
(defun original-material (rec ray world depth)
(declare (ignore ray world depth))
(vec* 0.5
(vec+ #(1 1 1)
(.normal rec))))
(defun lambertian-material (albedo)
(lambda (rec ray world depth)
(declare (ignore ray))
(let ((scatter-direction (vec+ (.normal rec)
(random-unit-vector))))
(when (near-zero scatter-direction)
(setf scatter-direction (.normal rec)))
(vec* albedo
(ray-color (ray (.p rec)
scatter-direction)
world
(1- depth))))))
(defun metal-material (albedo)
(lambda (rec ray world depth)
(with-slots (direction) ray
(let* ((reflected (reflect (unit-vector direction)
(.normal rec)))
(scattered (ray (.p rec) reflected)))
(vec* albedo
(ray-color scattered
world
(1- depth)))))))
(defun fuzzy-metal-material (albedo fuzz)
(lambda (rec ray world depth)
(with-slots (direction) ray
(let* ((reflected (reflect (unit-vector direction)
(.normal rec)))
(scattered (ray (.p rec)
(vec+ reflected
(vec* fuzz
(random-in-unit-sphere))))))
(vec* albedo
(ray-color scattered
world
(1- depth)))))))
(defun dielectric-material (ir &optional (fuzz 0))
(lambda (rec ray world depth)
(with-slots (direction) ray
(let* ((attenuation (vec3 1.0d0 1.0d0 1.0d0))
(refraction-ratio (if (.front-face rec)
(/ 1.0d0 ir)
ir))
(unit-direction (unit-vector direction))
(normal (.normal rec))
(cos-theta (min 1.0d0
(dot (negate unit-direction)
normal)))
(sin-theta (sqrt (- 1
(* cos-theta cos-theta))))
(cannot-refract (> (* refraction-ratio
sin-theta)
1.0d0))
(direction (if (or cannot-refract
(> (reflectance cos-theta
refraction-ratio)
(random 1.0d0)))
(reflect unit-direction
normal)
(refract unit-direction
normal
refraction-ratio)))
(scattered (ray (.p rec)
(vec+ direction
(vec* fuzz
(random-in-unit-sphere))))))
(vec* attenuation
(ray-color scattered
world
(1- depth)))))))
|