|
|
|
@ -29,7 +29,7 @@ scatter (Ray o d) (Hit t p n (Lambertian c)) = do |
|
|
|
|
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 |
|
|
|
|
let reflected = reflect (unitVector d) (unitVector n) |
|
|
|
|
return $ Ray p reflected |
|
|
|
|
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 |
|
|
|
@ -40,17 +40,16 @@ scatter (Ray o d) (Hit t p n (Glass c)) = do |
|
|
|
|
|
|
|
|
|
if refraction_ratio * st > 1.0 || reflectance ct refraction_ratio < rVal |
|
|
|
|
then do |
|
|
|
|
let reflected = reflect ud n |
|
|
|
|
let reflected = reflect ud (unitVector n) |
|
|
|
|
return $ Ray p reflected |
|
|
|
|
else do |
|
|
|
|
let refracted = refract ud n refraction_ratio |
|
|
|
|
let refracted = refract ud (unitVector n) refraction_ratio |
|
|
|
|
return $ Ray p refracted |
|
|
|
|
|
|
|
|
|
getRayColor :: (Shape s, RandomGen g) => [s] -> Int -> Ray -> Rand g (V3 Double) |
|
|
|
|
getRayColor ws d r = do |
|
|
|
|
let h = getBestHit (mapMaybe (testHit r) ws) |
|
|
|
|
v <- getRayColor' r h ws d |
|
|
|
|
return v |
|
|
|
|
getRayColor' r h ws d |
|
|
|
|
|
|
|
|
|
-- get color of pixel according to the closest hit found |
|
|
|
|
getRayColor' :: (Shape s, RandomGen g) => Ray -> Maybe Hit -> [s] -> Int -> Rand g (V3 Double) |
|
|
|
@ -88,7 +87,7 @@ colorWithNormal v = 0.5 *^ (v ^+^ V3 1.0 1.0 1.0) |
|
|
|
|
rayTrace :: (Shape s) => (Int, Int) -> ImageDimensions -> ViewPortDimensions -> [s] -> Int -> IO (V3 Double) |
|
|
|
|
rayTrace (x, y) (w, h) (vw, vh) world samples = do |
|
|
|
|
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 * (vw / wf)) (yf * (vh / hf))))) |
|
|
|
|
return $ foldl (^+^) (V3 0.0 0.0 0.0) l |
|
|
|
|
where |
|
|
|
|
xf = fromIntegral x |
|
|
|
@ -102,11 +101,11 @@ main = do |
|
|
|
|
let h = 400 |
|
|
|
|
let samples = 25 |
|
|
|
|
let world = |
|
|
|
|
[ Circle (V3 (0.0) 0.0 (-1.0)) 0.25 (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 0.0 0.0 (-1.0)) 0.25 (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 0.0 (-10.25) (-1.0)) 10 (Lambertian (V3 0.7 0.6 0.5)) |
|
|
|
|
] |
|
|
|
|
let coords = reverse $ range ((-1 * (w `div` 2), -1 * (h `div` 2)), ((w `div` 2) - 1, (h `div` 2) - 1)) -- "canvas" |
|
|
|
|
let coords = [(x, y) | x <- reverse $ [-1 * (w `div` 2) .. (w `div` 2) - 1], y <- [-1 * (h `div` 2) .. (h `div` 2) - 1]] |
|
|
|
|
colors <- mapM (\x -> rayTrace x (w, h) (1.0, 1.0) world samples) coords |
|
|
|
|
let convertedColors = map v3ToColor colors |
|
|
|
|
-- print ppm header |
|
|
|
|