added materials
This commit is contained in:
+20
-13
@@ -9,6 +9,7 @@ import Hittable
|
|||||||
import Linear.V2
|
import Linear.V2
|
||||||
import Linear.V3
|
import Linear.V3
|
||||||
import Linear.Vector
|
import Linear.Vector
|
||||||
|
import Material
|
||||||
import Maths
|
import Maths
|
||||||
import Ray
|
import Ray
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
@@ -22,12 +23,19 @@ type ImageDimensions = (Int, Int)
|
|||||||
type ViewPortDimensions = (Double, Double)
|
type ViewPortDimensions = (Double, Double)
|
||||||
|
|
||||||
-- TODO
|
-- TODO
|
||||||
-- DONE add multiple samples per pixel
|
-- antialiasing
|
||||||
-- fix coordinate system
|
|
||||||
-- DONE fix random number generator
|
|
||||||
|
|
||||||
backgroundColor = V3 0.0 0.0 0.0
|
backgroundColor = V3 0.0 0.0 0.0
|
||||||
|
|
||||||
|
scatter :: (RandomGen g) => Ray Double -> Hit -> Rand g (Ray Double)
|
||||||
|
scatter (Ray o d) (Hit t p n (Lambertian c)) = do
|
||||||
|
r <- randV3
|
||||||
|
let target = p ^+^ colorWithNormal (unitVector n) ^+^ r
|
||||||
|
return $ Ray p (target ^-^ p)
|
||||||
|
scatter (Ray o d) (Hit t p n (Metal c)) = do
|
||||||
|
let reflected = reflect (unitVector d) n
|
||||||
|
return $ Ray p reflected
|
||||||
|
|
||||||
getRayColor :: (Shape s, RandomGen g) => [s] -> Int -> Ray Double -> Rand g (V3 Double)
|
getRayColor :: (Shape s, RandomGen g) => [s] -> Int -> Ray Double -> Rand g (V3 Double)
|
||||||
getRayColor ws d r = do
|
getRayColor ws d r = do
|
||||||
let h = getBestHit (mapMaybe (testHit r) ws)
|
let h = getBestHit (mapMaybe (testHit r) ws)
|
||||||
@@ -37,19 +45,17 @@ getRayColor ws d r = do
|
|||||||
getRayColor' :: (Shape s, RandomGen g) => Ray Double -> Maybe Hit -> [s] -> Int -> Rand g (V3 Double)
|
getRayColor' :: (Shape s, RandomGen g) => Ray Double -> Maybe Hit -> [s] -> Int -> Rand g (V3 Double)
|
||||||
getRayColor' (Ray o d) Nothing _ _ = do return $ colorGradient (unitVector d)
|
getRayColor' (Ray o d) Nothing _ _ = do return $ colorGradient (unitVector d)
|
||||||
getRayColor' (Ray o d) _ _ 0 = do return $ colorGradient (unitVector d)
|
getRayColor' (Ray o d) _ _ 0 = do return $ colorGradient (unitVector d)
|
||||||
getRayColor' (Ray o d) (Just (Hit t p n)) ws depth =
|
getRayColor' (Ray o d) (Just (Hit t p n m)) ws depth = do
|
||||||
do
|
let a = attenuation m
|
||||||
r <- randV3
|
ray <- scatter (Ray o d) (Hit t p n m)
|
||||||
let target = p ^+^ colorWithNormal (unitVector n) ^+^ r
|
nextVal <- getRayColor ws (depth - 1) ray
|
||||||
nextVal <- getRayColor ws (depth - 1) (Ray p (target ^-^ p))
|
return (a * nextVal)
|
||||||
return (0.5 *^ nextVal)
|
|
||||||
|
|
||||||
colorGradient :: V3 Double -> V3 Double
|
colorGradient :: V3 Double -> V3 Double
|
||||||
colorGradient (V3 x y z) = do
|
colorGradient (V3 x y z) = do
|
||||||
let t = 0.5 * (y + 1.0)
|
let t = 0.5 * (y + 1.0)
|
||||||
(1.0 - t) *^ V3 1.0 1.0 1.0 + t *^ V3 0.5 0.7 1.0
|
(1.0 - t) *^ V3 1.0 1.0 1.0 + t *^ V3 0.5 0.7 1.0
|
||||||
|
|
||||||
-- testHit needs to take into account other hits, not here
|
|
||||||
getBestHit [] = Nothing
|
getBestHit [] = Nothing
|
||||||
getBestHit (h : hs) = Just (getBestHit' hs h)
|
getBestHit (h : hs) = Just (getBestHit' hs h)
|
||||||
|
|
||||||
@@ -98,9 +104,10 @@ main :: IO ()
|
|||||||
main = do
|
main = do
|
||||||
let w = 400
|
let w = 400
|
||||||
let h = 400
|
let h = 400
|
||||||
-- weirdly, the bottom circle appears on top and bottom
|
let world =
|
||||||
-- Circle (V3 0.0 (-10.05) 1.0) 5]
|
[ Circle (V3 0.0 0.0 (-1.0)) 0.25 (Metal (V3 0.8 0.8 0.8)),
|
||||||
let world = [Circle (V3 0.0 0.0 (-1.0)) 0.25, Circle (V3 0.0 (-10.25) (-1.0)) 10]
|
Circle (V3 0.0 (-10.25) (-1.0)) 10 (Lambertian (V3 0.7 0.3 0.3))
|
||||||
|
]
|
||||||
let coords = reverse $ range ((-1 * (w `div` 2), -1 * (h `div` 2)), ((w `div` 2) - 1, (h `div` 2) - 1)) -- "canvas"
|
let coords = reverse $ range ((-1 * (w `div` 2), -1 * (h `div` 2)), ((w `div` 2) - 1, (h `div` 2) - 1)) -- "canvas"
|
||||||
colors <- mapM (\x -> rayTrace x (w, h) (1.0, 1.0) world) coords
|
colors <- mapM (\x -> rayTrace x (w, h) (1.0, 1.0) world) coords
|
||||||
let convertedColors = map v3ToColor colors
|
let convertedColors = map v3ToColor colors
|
||||||
|
|||||||
+6
-6
@@ -2,16 +2,16 @@ module Hittable (Shape (..), Circle (..), Hit (..)) where
|
|||||||
|
|
||||||
import Linear.V3
|
import Linear.V3
|
||||||
import Linear.Vector
|
import Linear.Vector
|
||||||
|
import Material
|
||||||
import Maths
|
import Maths
|
||||||
import Ray
|
import Ray
|
||||||
|
|
||||||
-- section 6.4 will be the key here
|
|
||||||
class Shape s where
|
class Shape s where
|
||||||
testHit :: Ray Double -> s -> Maybe Hit
|
testHit :: Ray Double -> s -> Maybe Hit
|
||||||
|
|
||||||
data Circle = Circle (V3 Double) Double
|
data Circle = Circle (V3 Double) Double Material
|
||||||
|
|
||||||
data Hit = Hit {root :: Double, p :: V3 Double, n :: V3 Double}
|
data Hit = Hit {root :: Double, p :: V3 Double, n :: V3 Double, m :: Material}
|
||||||
|
|
||||||
getFaceNormal :: Ray Double -> V3 Double -> V3 Double
|
getFaceNormal :: Ray Double -> V3 Double -> V3 Double
|
||||||
getFaceNormal (Ray o d) n
|
getFaceNormal (Ray o d) n
|
||||||
@@ -20,15 +20,15 @@ getFaceNormal (Ray o d) n
|
|||||||
|
|
||||||
-- t_min 0 t_max infinity... need closest so far
|
-- t_min 0 t_max infinity... need closest so far
|
||||||
instance Shape Circle where
|
instance Shape Circle where
|
||||||
testHit (Ray o d) (Circle center r) =
|
testHit (Ray o d) (Circle center r m) =
|
||||||
if discriminant < 0.0
|
if discriminant < 0.0
|
||||||
then Nothing
|
then Nothing
|
||||||
else
|
else
|
||||||
if root > 0.001
|
if root > 0.001
|
||||||
then Just (Hit root p (getFaceNormal (Ray o d) ((p - center) ^/ r)))
|
then Just (Hit root p (getFaceNormal (Ray o d) ((p - center) ^/ r)) m)
|
||||||
else
|
else
|
||||||
if rootP > 0.001
|
if rootP > 0.001
|
||||||
then Just (Hit rootP pp (getFaceNormal (Ray o d) ((pp - center) ^/ r)))
|
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
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
module Material (Material (..), attenuation) where
|
||||||
|
|
||||||
|
import Linear.V3
|
||||||
|
import Linear.Vector
|
||||||
|
import Maths
|
||||||
|
import Ray
|
||||||
|
|
||||||
|
data Material = Lambertian (V3 Double) | Metal (V3 Double)
|
||||||
|
|
||||||
|
-- attenuation :: (Material m) => m -> V3 Double
|
||||||
|
attenuation (Lambertian c) = c
|
||||||
|
attenuation (Metal c) = c
|
||||||
@@ -4,6 +4,7 @@ module Maths
|
|||||||
unitVector,
|
unitVector,
|
||||||
randV3,
|
randV3,
|
||||||
rand,
|
rand,
|
||||||
|
reflect,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@@ -44,3 +45,6 @@ vectorLength v = sqrt (lengthSquared v)
|
|||||||
|
|
||||||
unitVector :: (Floating f) => V3 f -> V3 f
|
unitVector :: (Floating f) => V3 f -> V3 f
|
||||||
unitVector v = v ^/ vectorLength v
|
unitVector v = v ^/ vectorLength v
|
||||||
|
|
||||||
|
reflect :: (Floating f) => V3 f -> V3 f -> V3 f
|
||||||
|
reflect v n = v - (2 * (v `dotP` n)) *^ n
|
||||||
|
|||||||
Reference in New Issue
Block a user