gloss-examples-1.7.2.1: raster/Ray/Trace.hs
{-# LANGUAGE BangPatterns #-}
module Trace where
import Object
import Light
import Vec3
-- Cast a single ray into the scene
traceRay
:: [Object] -- objects in scene
-> [Light] -- direct lights in scene
-> Color -- ambient light in scene
-> Vec3 -- origin of ray
-> Vec3 -- direction of ray
-> Int -- maximum reflection count
-> Color -- visible color for this ray
traceRay !objs !lights !ambient !(Vec3 gX gY gZ) !dir !limit
= go gX gY gZ dir limit
where
-- too many reflections,
-- give up incase we've found two parallel mirrors..
go _ _ _ _ 0
= Vec3 0.0 0.0 0.0
go !oX !oY oZ !dir' !bounces
= castRay_continuation objs (Vec3 oX oY oZ) dir'
-- ray didn't intersect any objects
(Vec3 0.0 0.0 0.0)
-- ray hit an object
(\obj point@(Vec3 pX' pY' pZ')
-> let
-- get the surface normal at that point.
!normal = surfaceNormal obj point
-- result angle of ray after reflection.
!newdir = dir - normal `mulsV3` (2.0 * (normal `dotV3` dir))
-- determine the direct lighting at this point
!direct = applyLights objs point normal lights
-- see if ray hits anything else.
!refl = go pX' pY' pZ' newdir (bounces - 1)
-- total lighting is the direct lights plus ambient
!lighting = direct + ambient
-- total incoming light is direct lighting plus reflections
!color = colorOfObject obj point
!shine = shineOfObject obj point
!light_in = refl `mulsV3` shine
+ lighting `mulsV3` (1.0 - shine)
-- Outgoing light is incoming light modified by surface color.
-- We also need to clip it incase the sum of all incoming lights
-- will be too bright to display.
!light_out = clipV3 (light_in * color) 1.0
in light_out)
{-# INLINE traceRay #-}