Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Tracer
- module Material =
- open System
- open Interfaces
- open System.Threading
- open Vector
- //Might need to take the average of the colourSums, we'll see when I can test
- let Pi = Math.PI
- let e = 0.00001
- let reflectLight (ld:Vector) (n:Vector) = -ld + (2.0 * (n * ld)) * n
- let reflectRay (dir:Vector) (n:Vector) = dir + (-2.0 * (n * dir) * n)
- let rec shadeMatte (kdcdPi:Colour) (p:Point) (n:Vector) (lights:ILight list) (scene:IScene) (acc:Colour) =
- match lights with
- | l :: rest -> let ls = l.s p n scene
- let ld = l.d p
- let lG = l.G
- let lpdf = l.pdf n
- let lc = l.c p scene
- let cosPhi = n*ld
- if not ls && cosPhi > 0.0
- then let colour = acc + (kdcdPi * (lG/lpdf) * lc * cosPhi)
- shadeMatte kdcdPi p n rest scene colour
- else shadeMatte kdcdPi p n rest scene acc
- | [] -> acc
- let spec (cs:Colour) (ks:float) (exp:int) (rl:Vector) (rd:Vector) =
- if (rl * (-rd)) > 0.0
- then ks * cs * (pown (rl * -rd) exp)
- else Colour.BLACK
- let reflect (cr:Colour) (kr:float) (p:Point) (d':Vector) (scene:IScene) (depth:int) =
- if depth <= scene.maxDepth
- then
- let hit = scene.traceRay p d'
- if hit.IsNone then Colour.BLACK
- else
- let hit = hit.Value :?> ShapeHit
- let n2 = hit.n
- let mat2 = hit.m
- let hp = hit.p
- let n2 =
- if d' * n2 > 0.0
- then -n2
- else n2
- let p' = hp + e * n2
- kr * cr * (mat2.shade p' d' n2 scene (depth+1))
- else Colour.BLACK
- let rec shadePhong (kdcdPi:Colour) (cs:Colour) (ks:float) (exp:int) (dir:Vector) (p:Point) (n:Vector) (lights:ILight list) (scene:IScene) (acc:Colour) =
- match lights with
- | l :: rest -> let ls = l.s p n scene
- let ld = l.d p
- let nld = n * ld
- let rl = (-ld) + (2.0 * (nld)) * n
- let rlrd = rl * (-dir)
- let shade = if (not ls) && nld > 0.0
- then let spec = if rlrd > 0.0
- then (ks * cs) * (pown rlrd exp)
- else Colour.BLACK
- let acc = acc + (kdcdPi + spec) * ((l.G/(l.pdf n))*(l.c p scene) * nld)
- shadePhong kdcdPi cs ks exp dir p n rest scene acc
- else shadePhong kdcdPi cs ks exp dir p n rest scene acc
- match shade with
- | Colour.RGB(r,g,b) -> if Double.IsInfinity r then failwith "infinity"
- shade
- | [] -> acc
- type MatteMaterial(ca:Colour, ka:float, cd:Colour, kd:float) =
- let kdcdPi = (kd*cd) / Pi
- interface IMaterial with
- member this.shade p d n scene depth =
- let ambient = ca * ka * scene.ambientLight.c p n scene
- let n = if d * n > 0.0 then -n else n
- let p' = p + (e * n)
- shadeMatte kdcdPi p' n scene.lights scene ambient
- type MatteReflectiveMaterial(ca:Colour, ka:float, cd:Colour, kd:float, cr:Colour, kr:float) =
- let kdcdPi = (kd*cd / Pi)
- interface IMaterial with
- member this.shade p d n scene depth =
- let ambient = ca * ka * scene.ambientLight.c p n scene
- let n = if d * n > 0.0 then -n else n
- let p' = p + (e * n)
- let d' = d + (-2.0 * (n * d)) * n
- let c = shadeMatte kdcdPi p' n scene.lights scene ambient
- c + reflect cr kr p' d' scene depth
- type PhongMaterial(ca:Colour, ka:float, cd:Colour, kd:float, cs:Colour, ks:float, exp:int) =
- let kdcdPi = (kd * cd) / Pi
- interface IMaterial with
- member this.shade p d n scene depth =
- let ambient = ca * ka * scene.ambientLight.c p n scene
- let dn = d * n
- let n = if dn > 0.0 then -n else n
- let p' = p + (e * n)
- shadePhong kdcdPi cs ks exp d p' n scene.lights scene ambient
- type PhongReflectiveMaterial(ca:Colour, ka:float, cd:Colour, kd:float, cs:Colour, ks:float, cr:Colour, kr:float, exp:int) =
- let kdcdPi = (kd * cd) / Pi
- interface IMaterial with
- member this.shade p d n scene depth =
- let ambient = ca * ka * scene.ambientLight.c p n scene
- let n = if d * n > 0.0 then -n else n
- let p' = p + e * n
- let d' = d + (-2.0 * (n * d)) * n
- let c = shadePhong kdcdPi cs ks exp d p' n scene.lights scene ambient
- c + reflect cr kr p' d' scene depth
- type MatteGlossyReflectiveMaterial(ca : Colour, ka : float, cd : Colour, kd : float, cr : Colour, kr : float, s : ISampler) =
- let kdcdPi = (kd*cd) / Pi
- interface IMaterial with
- member this.shade p d n scene depth =
- let spx,spy,spz = s.getNext Thread.CurrentThread.ManagedThreadId
- let ambient = ca * ka * scene.ambientLight.c p n scene
- let n = if d * n > 0.0
- then -n
- else n
- let p' = p + e * n
- let c = shadeMatte kdcdPi p' n scene.lights scene ambient
- let d' = d + 2.0 * (n * -d) * n
- let frame = OrthonormalFrame(d')
- let frameDir = normalize (Point.direction (Point.mkPoint 0.0 0.0 0.0) (Point.mkPoint spx spy spz))
- let d'' = normalize (convertOrthVector frameDir frame)
- let d''' =
- if Vector.dotProduct n d'' > 0.0
- then mkVector -(Vector.getX d'') -(Vector.getY d'') (Vector.getZ d'')
- else d''
- c + reflect cr kr p' d''' scene depth
- type PhongGlossyReflectiveMaterial (ca : Colour, ka : float, cd : Colour, kd : float, cs : Colour, ks : float, cr : Colour, kr : float, exps : int, expr : int, s : ISampler) =
- interface IMaterial with
- member this.shade p d n scene depth = failwith "venter på Peter"
- type EmissiveMaterial(c : Colour, i : float) =
- member this.er = c * i
- interface IMaterial with
- member this.shade p d n scene depth =
- if (n * -d > 0.0) then this.er
- else Colour.BLACK
- let mkMatteMaterial ca ka cd kd = new MatteMaterial(ca, ka, cd, kd) :> IMaterial
- let mkMatteReflectiveMaterial ca ka cd kd cr kr = new MatteReflectiveMaterial(ca, ka, cd, kd, cr, kr) :> IMaterial
- let mkPhongMaterial ca ka cd kd cs ks exp = new PhongMaterial(ca, ka, cd, kd, cs, ks, exp) :> IMaterial
- let mkPhongReflectiveMaterial ca ka cd kd cs ks cr kr exp = new PhongReflectiveMaterial(ca, ka, cd, kd, cs, ks, cr, kr, exp) :> IMaterial
- let mkMatteGlossyReflectiveMaterial ca ka cd kd cr kr s = new MatteGlossyReflectiveMaterial(ca, ka, cd, kd, cr, kr, s) :> IMaterial
- let mkEmissiveMaterial c i = new EmissiveMaterial(c, i) :> IMaterial
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement