Advertisement
Guest User

Untitled

a guest
May 16th, 2018
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 8.26 KB | None | 0 0
  1. namespace Tracer
  2. module Camera =
  3.     open System
  4.     open Point
  5.     open Vector
  6.     open Interfaces
  7.     open System.Drawing
  8.     open System.Windows.Forms
  9.     open sampling
  10.     open System.Threading;
  11.     open System.Collections.Concurrent
  12.     open System.Threading.Tasks
  13.     open System.Drawing.Imaging
  14.     open Microsoft.FSharp.NativeInterop
  15.    
  16.     type point = Point.Point
  17.     type vector = Vector.Vector
  18.     type sampler = ISampler
  19.  
  20.     //credits to
  21.     type LockContext(bitmap : Bitmap) =
  22.         let data = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat)
  23.        
  24.         let getPixelAddress x y =
  25.             match data.PixelFormat with
  26.             | PixelFormat.Format32bppArgb -> NativePtr.add<byte> (NativePtr.ofNativeInt (data.Scan0)) ((y * (data.Stride)) + (x*4))
  27.             | _ -> failwith "PixelFormat not supported"
  28.        
  29.         let setPixel x y (color : Color) =
  30.             let address = getPixelAddress x y
  31.             match data.PixelFormat with
  32.             | PixelFormat.Format32bppArgb -> NativePtr.set address 3 color.A
  33.                                              NativePtr.set address 2 color.R
  34.                                              NativePtr.set address 1 color.G
  35.                                              NativePtr.write address color.B
  36.             | _ -> failwith "PixelFormat not supported"
  37.         member this.SetPixeL(x,y, color : Color) = setPixel x y color
  38.  
  39.  
  40.     let rec getClosestHit (hits:(float * vector * IMaterial * point) option list) (index:int) (bestIndex:int) (leastT:float) =
  41.         match hits with
  42.         | hit :: rest -> if hit.IsSome
  43.                          then let (t, _, _, _) = hit.Value
  44.                               if t < leastT
  45.                               then getClosestHit rest (index + 1) index t
  46.                               else getClosestHit rest (index + 1) bestIndex leastT
  47.                          else getClosestHit rest (index + 1) bestIndex leastT
  48.         | [] -> bestIndex
  49.  
  50.     let rec findHit (o:point) (dir:vector) (shapes:IShape list) (bestHit:(float * vector * IMaterial * point) option) (minDist:float) =
  51.         match shapes with
  52.         | s :: rest -> match s.hit o dir with
  53.                        | Some(t, n, mat, hp) -> if t < minDist
  54.                                                 then findHit o dir rest (Some(t, n, mat, hp)) t
  55.                                                 else findHit o dir rest bestHit minDist
  56.                        | None -> findHit o dir rest bestHit minDist
  57.         | [] -> bestHit
  58.  
  59.     let traceRay (o:point) (dir:vector) (shapes:IShape list) =
  60.         findHit o dir shapes None Double.PositiveInfinity
  61.  
  62.     type Scene(shapes, lights, ambientLight, maxDepth) =
  63.         interface IScene with
  64.             member this.shapes = shapes
  65.             member this.lights = lights
  66.             member this.ambientLight = ambientLight
  67.             member this.maxDepth = maxDepth
  68.             member this.traceRay o dir = traceRay o dir shapes
  69.  
  70.     let mkScene s l a m = new Scene(s, l, a, m) :> IScene
  71.  
  72. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. //                                                 rendering                                                                                    //
  74. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  75.  
  76.  
  77.     let renderScene (scene:IScene) (camera:ICamera) : Bitmap =
  78.         let threadBag = new ConcurrentBag<int*int*Color>()
  79.  
  80.         let resX = camera.getResX
  81.         let resY = camera.getResY
  82.  
  83.         let bmp = new Bitmap(resX, resY)
  84.    
  85.         let stopWatch = System.Diagnostics.Stopwatch.StartNew()    
  86.  
  87.         let mutable progress = 0
  88.  
  89.         let context = new LockContext(bmp)
  90.  
  91.         Parallel.For(0,resY-1, fun j ->
  92.             do
  93.             for i in [0 .. resX-1]
  94.                 do
  95.                 let mutable accum = Colour.mkColour 0.0 0.0 0.0
  96.                 for ii in [1 .. camera.vpSampler.length]
  97.                     do
  98.                     let (dir,position) = camera.calcDir i j
  99.                     let hit = traceRay position dir scene.shapes
  100.  
  101.                     if hit.IsSome
  102.                     then
  103.                         let t, n, mat, p = hit.Value
  104.                         accum <- accum + (mat.shade p dir n scene 0)
  105.                 context.SetPixeL(i,j, Colour.toColor (accum/(float camera.vpSampler.length)))) |> ignore
  106.         bmp
  107.  
  108.     let renderToFile (scene:IScene) (camera:ICamera) (path:string) =
  109.         (renderScene scene camera).Save(path)
  110.  
  111.     let renderToScreen (scene:IScene) (camera:ICamera) : unit =
  112.         let bmp = renderScene scene camera
  113.         let result = new Form(MaximizeBox = true, Text = "Rendered Image")
  114.         let graphics = result.CreateGraphics()
  115.         graphics.DrawImage(bmp, 0, 0)
  116.         do Application.Run result
  117.  
  118. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  119. //                                                  types and inheritance                                                                                     //
  120. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  121.  
  122.  
  123.     type PinholeCamera(position, lookat, up, zoom, vpWidth, vpHeight, pixelWidth, pixelHeight, vpSampler) = //Parametre
  124.         let position = position
  125.         let lookat = lookat
  126.         let up = up
  127.         let zoom = zoom
  128.         let vpWidth = vpWidth
  129.         let vpHeight = vpHeight
  130.         let resX = pixelWidth
  131.         let resY = pixelHeight
  132.         let vpSampler = vpSampler
  133.         member this.w = normalize (Point.distance lookat position)
  134.         member this.v = normalize (crossProduct up this.w)
  135.         member this.u = crossProduct this.w this.v
  136.         member this.calcPxPy i j (x,y) =
  137.             ((vpWidth / float resX) * (float i - (float resX / 2.0) + x)), ((vpHeight / float resY) * (float j - (float resY / 2.0) + y))
  138.         interface ICamera with
  139.             member this.vpSampler = vpSampler
  140.             member this.getResX = resX
  141.             member this.getResY = resY
  142.             member this.calcDir i j =
  143.                 let (x,y,_) = (vpSampler: ISampler).getNext Thread.CurrentThread.ManagedThreadId
  144.                 let (px,py) = this.calcPxPy i j (x,y)
  145.                 Vector.normalize (Vector.substract (Vector.add ((Vector.multScalar px this.v),(Vector.multScalar py this.u)),(Vector.multScalar zoom this.w))), position // had a weird issue with not being able to reach infix operators
  146.  
  147.     type ThinLensCamera(position,lookat,up,zoom,vpWidth,vpHeight,pixelWidth,pixelHeight,lensRadius,fpDistance,vpSampler,lenseSampler) =
  148.         inherit PinholeCamera(position, lookat, up, zoom, vpWidth, vpHeight, pixelWidth, pixelHeight, vpSampler)  
  149.         let lensRadius = lensRadius
  150.         let fpDistance = fpDistance
  151.         let lenseSampler = lenseSampler
  152.         interface ICamera with
  153.             override this.calcDir i j =
  154.                 let (x,y,_) = (vpSampler: ISampler).getNext Thread.CurrentThread.ManagedThreadId
  155.                 let (qx,qy) = this.calcPxPy i j (x,y)
  156.                 let (px,py) = (fpDistance*qx/zoom,fpDistance*qy/zoom)
  157.                 let (sx, sy,_) = (lenseSampler : ISampler).getNext Thread.CurrentThread.ManagedThreadId
  158.                 let (lx,ly) = (lensRadius*sx,lensRadius*sy)
  159.                 (Vector.normalize (((px-lx)*this.u) + ((py-ly)*this.v) - (fpDistance*this.w))),(position + (lx*this.u) + (ly*this.v)) // should normalize vector
  160.        
  161.     let mkPinholeCamera position lookat up zoom vpWidth vpHeight pixelWidth pixelHeight vpSampler = new PinholeCamera(position,lookat,up,zoom,vpWidth,vpHeight,pixelWidth,pixelHeight,vpSampler) :> ICamera
  162.     let mkThinLensCamera position lookat up zoom vpWidth vpHeight pixelWidth pixelHeight lensRadius fpDistance vpSampler (lensSampler:ISampler) = new ThinLensCamera(position,lookat,up,zoom,vpWidth,vpHeight,pixelWidth,pixelHeight,lensRadius,fpDistance,vpSampler,lensSampler) :> ICamera
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement