diff --git a/app/Main.hs b/app/Main.hs index 5de164d..76dc5cc 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -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 diff --git a/src/Maths.hs b/src/Maths.hs index 65d6d9a..c295df5 100644 --- a/src/Maths.hs +++ b/src/Maths.hs @@ -28,10 +28,6 @@ randV3 = do then randV3 else return $ unitVector (V3 x y z) --- _ -> randV3 - ---inf = read "Infinity" - degToRadians :: Double -> Double degToRadians d = (d * pi) / 180.0 diff --git a/src/Ray.hs b/src/Ray.hs index 9a4b5f9..d4b7473 100644 --- a/src/Ray.hs +++ b/src/Ray.hs @@ -3,6 +3,7 @@ module Ray rayAt, calculateRayNormal, buildRay, + buildRayAA, ) where @@ -21,5 +22,11 @@ rayAt (Ray origin dir) t = origin + (t *^ dir) calculateRayNormal :: Ray -> Double -> V3 Double calculateRayNormal r t = unitVector (rayAt r t ^-^ V3 0.0 0.0 1.0) +buildRayAA :: (RandomGen g) => Double -> Double -> Rand g Ray +buildRayAA u v = do + ur <- rand + vr <- rand + return (Ray (V3 0.0 0.0 0.0) (V3 (v + vr) (u + ur) (-1.0))) + buildRay :: Double -> Double -> Ray buildRay u v = Ray (V3 0.0 0.0 0.0) (V3 v u (-1.0))