added camera object
This commit is contained in:
+22
-16
@@ -1,12 +1,12 @@
|
|||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
|
import Camera
|
||||||
import Control.Monad (mapM)
|
import Control.Monad (mapM)
|
||||||
import Control.Monad.Random
|
import Control.Monad.Random
|
||||||
import Data.Ix
|
import Data.Ix
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Hittable
|
import Hittable
|
||||||
import IOUtils
|
import IOUtils
|
||||||
import Linear.V2
|
|
||||||
import Linear.V3
|
import Linear.V3
|
||||||
import Linear.Vector
|
import Linear.Vector
|
||||||
import Material
|
import Material
|
||||||
@@ -17,8 +17,6 @@ type Coord = (Int, Int)
|
|||||||
|
|
||||||
type ImageDimensions = (Int, Int)
|
type ImageDimensions = (Int, Int)
|
||||||
|
|
||||||
type ViewPortDimensions = (Double, Double)
|
|
||||||
|
|
||||||
-- TODO
|
-- TODO
|
||||||
-- antialiasing
|
-- antialiasing
|
||||||
|
|
||||||
@@ -26,24 +24,24 @@ type ViewPortDimensions = (Double, Double)
|
|||||||
scatter :: (RandomGen g) => Ray -> Hit -> Rand g (Ray)
|
scatter :: (RandomGen g) => Ray -> Hit -> Rand g (Ray)
|
||||||
scatter (Ray o d) (Hit t p n (Lambertian c)) = do
|
scatter (Ray o d) (Hit t p n (Lambertian c)) = do
|
||||||
r <- randV3
|
r <- randV3
|
||||||
let target = p ^+^ colorWithNormal (unitVector n) ^+^ r
|
let target = p ^+^ colorWithNormal n ^+^ r
|
||||||
return $ Ray p (target ^-^ p)
|
return $ Ray p (target ^-^ p)
|
||||||
scatter (Ray o d) (Hit t p n (Metal c)) = do
|
scatter (Ray o d) (Hit t p n (Metal c)) = do
|
||||||
let reflected = reflect (unitVector d) (unitVector n)
|
let reflected = reflect (unitVector d) n
|
||||||
return $ Ray p reflected
|
return $ Ray p reflected
|
||||||
scatter (Ray o d) (Hit t p n (Glass c)) = do
|
scatter (Ray o d) (Hit t p n (Glass c)) = do
|
||||||
let refraction_ratio = if isFrontFace (Ray o d) n then 1.0 / 1.5 else 1.0
|
let refraction_ratio = if isFrontFace (Ray o d) n then 1.0 / 1.5 else 1.0
|
||||||
let ud = unitVector d
|
let ud = unitVector d
|
||||||
let ct = min (ud `dotP` (unitVector n)) 1.0
|
let ct = min (ud `dotP` n) 1.0
|
||||||
let st = sqrt (1.0 - ct * ct)
|
let st = sqrt (1.0 - ct * ct)
|
||||||
rVal <- rand
|
rVal <- rand
|
||||||
|
|
||||||
if refraction_ratio * st > 1.0 || reflectance ct refraction_ratio < rVal
|
if refraction_ratio * st > 1.0 || reflectance ct refraction_ratio < rVal
|
||||||
then do
|
then do
|
||||||
let reflected = reflect ud (unitVector n)
|
let reflected = reflect ud n
|
||||||
return $ Ray p reflected
|
return $ Ray p reflected
|
||||||
else do
|
else do
|
||||||
let refracted = refract ud (unitVector n) refraction_ratio
|
let refracted = refract ud n refraction_ratio
|
||||||
return $ Ray p refracted
|
return $ Ray p refracted
|
||||||
|
|
||||||
getRayColor :: (Shape s, RandomGen g) => [s] -> Int -> Ray -> Rand g (V3 Double)
|
getRayColor :: (Shape s, RandomGen g) => [s] -> Int -> Ray -> Rand g (V3 Double)
|
||||||
@@ -84,10 +82,10 @@ colorWithNormal v = 0.5 *^ (v ^+^ V3 1.0 1.0 1.0)
|
|||||||
|
|
||||||
-- heart of loop, for each x y coordinate pixel, convert it into world space and then run the ray tracing algorithm
|
-- heart of loop, for each x y coordinate pixel, convert it into world space and then run the ray tracing algorithm
|
||||||
-- run [samples] times in order to increase fidelity
|
-- run [samples] times in order to increase fidelity
|
||||||
rayTrace :: (Shape s) => (Int, Int) -> ImageDimensions -> ViewPortDimensions -> [s] -> Int -> IO (V3 Double)
|
rayTrace :: (Shape s) => (Int, Int) -> ImageDimensions -> [s] -> Int -> Camera -> IO (V3 Double)
|
||||||
rayTrace (x, y) (w, h) (vw, vh) world samples = do
|
rayTrace (x, y) (w, h) world samples camera = do
|
||||||
let maxDepth = 50
|
let maxDepth = 50
|
||||||
l <- replicateM samples (evalRandIO (getRayColor world maxDepth $ (buildRay (xf * (vw / wf)) (yf * (vh / hf)))))
|
l <- replicateM samples (evalRandIO (getRayColor world maxDepth $ buildRay (xf / wf) (yf / hf) camera))
|
||||||
return $ foldl (^+^) (V3 0.0 0.0 0.0) l
|
return $ foldl (^+^) (V3 0.0 0.0 0.0) l
|
||||||
where
|
where
|
||||||
xf = fromIntegral x
|
xf = fromIntegral x
|
||||||
@@ -99,14 +97,22 @@ main :: IO ()
|
|||||||
main = do
|
main = do
|
||||||
let w = 400
|
let w = 400
|
||||||
let h = 400
|
let h = 400
|
||||||
|
|
||||||
|
let aspect = 1.0 --16.0 / 9.0
|
||||||
|
let viewHeight = 2.0
|
||||||
|
let viewWidth = aspect * viewHeight
|
||||||
|
let focalLength = 1.0
|
||||||
|
|
||||||
|
let camera = makeCamera (V3 0.0 0.0 0.0) viewWidth viewHeight focalLength
|
||||||
|
|
||||||
let samples = 25
|
let samples = 25
|
||||||
let world =
|
let world =
|
||||||
[ Circle (V3 0.0 0.0 (-1.0)) 0.25 (Glass (V3 1.0 1.0 1.0)),
|
[ Circle (V3 0.0 0.0 (-1.0)) 0.5 (Glass (V3 1.0 1.0 1.0)),
|
||||||
Circle (V3 0.5 0.0 (-1.0)) 0.25 (Lambertian (V3 0.7 0.1 0.1)),
|
Circle (V3 1.0 0.0 (-1.0)) 0.5 (Lambertian (V3 0.7 0.1 0.1)),
|
||||||
Circle (V3 0.0 (-10.25) (-1.0)) 10 (Lambertian (V3 0.7 0.6 0.5))
|
Circle (V3 0.0 (-100.5) (-1.0)) 100 (Lambertian (V3 0.7 0.6 0.5))
|
||||||
]
|
]
|
||||||
let coords = [(x, y) | x <- reverse $ [-1 * (w `div` 2) .. (w `div` 2) - 1], y <- [-1 * (h `div` 2) .. (h `div` 2) - 1]]
|
let coords = [(x, y) | x <- reverse [0 .. w - 1], y <- [0 .. h - 1]]
|
||||||
colors <- mapM (\x -> rayTrace x (w, h) (1.0, 1.0) world samples) coords
|
colors <- mapM (\x -> rayTrace x (w, h) world samples camera) coords
|
||||||
let convertedColors = map v3ToColor colors
|
let convertedColors = map v3ToColor colors
|
||||||
-- print ppm header
|
-- print ppm header
|
||||||
putStrLn "P3"
|
putStrLn "P3"
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
module Camera (Camera (..), makeCamera) where
|
||||||
|
|
||||||
|
import Linear.V3
|
||||||
|
import Linear.Vector
|
||||||
|
|
||||||
|
data Camera = Camera {origin :: V3 Double, lowerLeft :: V3 Double, horizontal :: V3 Double, vertical :: V3 Double}
|
||||||
|
|
||||||
|
makeCamera :: V3 Double -> Double -> Double -> Double -> Camera
|
||||||
|
makeCamera o viewWidth viewHeight focalLength = do
|
||||||
|
let horizontal = V3 viewWidth 0.0 0.0
|
||||||
|
let vertical = V3 0.0 viewHeight 0.0
|
||||||
|
let focalVec = V3 0.0 0.0 focalLength
|
||||||
|
let lowerLeft = o ^-^ (horizontal ^/ 2) ^-^ (vertical ^/ 2) ^-^ focalVec
|
||||||
|
Camera o lowerLeft horizontal vertical
|
||||||
+3
-3
@@ -36,11 +36,11 @@ instance Shape Circle where
|
|||||||
then Just (Hit rootP pp (getFaceNormal (Ray o d) ((pp - center) ^/ r)) m)
|
then Just (Hit rootP pp (getFaceNormal (Ray o d) ((pp - center) ^/ r)) m)
|
||||||
else Nothing
|
else Nothing
|
||||||
where
|
where
|
||||||
co = o - center
|
co = o ^-^ center
|
||||||
a = lengthSquared d -- a vector dotted with itself is = lengthSquared
|
a = lengthSquared d -- a vector dotted with itself is = lengthSquared
|
||||||
b = co `dotP` d
|
b = co `dotP` d
|
||||||
c = lengthSquared co - r ^ 2
|
c = lengthSquared co - r * r
|
||||||
discriminant = b ^ 2 - a * c
|
discriminant = b * b - a * c
|
||||||
root = (b * (-1.0) - sqrt discriminant) / a
|
root = (b * (-1.0) - sqrt discriminant) / a
|
||||||
rootP = (b * (-1.0) + sqrt discriminant) / a
|
rootP = (b * (-1.0) + sqrt discriminant) / a
|
||||||
p = rayAt (Ray o d) root
|
p = rayAt (Ray o d) root
|
||||||
|
|||||||
+6
-5
@@ -7,6 +7,7 @@ module Ray
|
|||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Camera
|
||||||
import Control.Monad.Random
|
import Control.Monad.Random
|
||||||
import Linear.V3
|
import Linear.V3
|
||||||
import Linear.Vector
|
import Linear.Vector
|
||||||
@@ -22,11 +23,11 @@ rayAt (Ray origin dir) t = origin + (t *^ dir)
|
|||||||
calculateRayNormal :: Ray -> Double -> V3 Double
|
calculateRayNormal :: Ray -> Double -> V3 Double
|
||||||
calculateRayNormal r t = unitVector (rayAt r t ^-^ V3 0.0 0.0 1.0)
|
calculateRayNormal r t = unitVector (rayAt r t ^-^ V3 0.0 0.0 1.0)
|
||||||
|
|
||||||
buildRayAA :: (RandomGen g) => Double -> Double -> Rand g Ray
|
buildRayAA :: (RandomGen g) => Double -> Double -> Camera -> Rand g Ray
|
||||||
buildRayAA u v = do
|
buildRayAA u v camera = do
|
||||||
ur <- rand
|
ur <- rand
|
||||||
vr <- rand
|
vr <- rand
|
||||||
return (Ray (V3 0.0 0.0 0.0) (V3 (v + vr) (u + ur) (-1.0)))
|
return $ buildRay (u + ur) (v + vr) camera
|
||||||
|
|
||||||
buildRay :: Double -> Double -> Ray
|
buildRay :: Double -> Double -> Camera -> Ray
|
||||||
buildRay u v = Ray (V3 0.0 0.0 0.0) (V3 v u (-1.0))
|
buildRay u v (Camera o ll h vv) = Ray o (ll ^+^ (v *^ h) ^+^ (u *^ vv) ^-^ o)
|
||||||
|
|||||||
Reference in New Issue
Block a user