git.haldean.org artray / 4959e98
Antialiasing! But a parsing bug. Will Brown 8 years ago
6 changed file(s) with 61 addition(s) and 47 deletion(s). Raw diff Collapse all Expand all
55
66 data Scene =
77 Scene {
8 geom :: [Primitive],
98 background :: ColorTriple,
109 globalAmbient :: ColorTriple,
10 subpixels :: Int,
11 geom :: [Primitive],
1112 lights :: [Light],
1213 viewer :: Viewer
1314 } deriving (Show, Read)
8081 } deriving (Show, Read)
8182
8283 data Point2D =
83 -- | Describes a point in the image using pixel coordinates
84 Point2D Int Int
84 -- | Describes a point in the image using pixel coordinates, allowing for
85 -- | fractional pixels for subpixel sampling.
86 Point2D Double Double
8587 -- | Describes a point in the image using offsets from the center, where each
8688 -- field goes from zero to one.
8789 | RelPoint2D Double Double
9496 colorm r g b = ColorMaterial (r, g, b)
9597
9698 toRelPoint :: Size -> Point2D -> Point2D
97 toRelPoint size (Point2D ix iy) =
99 toRelPoint size (Point2D x y) =
98100 RelPoint2D ((x - xc) / xc) ((y - yc) / yc)
99101 where xc = fromIntegral (fst size) / 2
100102 yc = fromIntegral (snd size) / 2
101 x = fromIntegral ix
102 y = fromIntegral iy
103103
104104 -- |Creates a viewer
105105 view :: Vec3 -- ^ The location of the viewer
137137
138138 sumColor :: ColorTriple -> ColorTriple -> ColorTriple
139139 sumColor (r1, g1, b1) (r2, g2, b2) = normalizeColor (r1 + r2, g1 + g2, b1 + b2)
140 sumColor' (r1, g1, b1) (r2, g2, b2) = (r1 + r2, g1 + g2, b1 + b2)
140141
142 meanColor :: [ColorTriple] -> ColorTriple
143 meanColor colors = div $ foldl1 sumColor' colors
144 where l = fromIntegral $ length colors
145 div (r, g, b) = (r / l, g / l, b / l)
77 import ArtRay.Geometry
88 import ArtRay.Primitives
99
10 pixelColor :: Size -> Scene -> Viewer -> Point2D -> Color
10 pixelColor :: Size -> Scene -> Viewer -> Point2D -> ColorTriple
1111 pixelColor size scene viewer (Point2D ix iy) =
1212 pixelColor size scene viewer (toRelPoint size (Point2D ix iy))
1313 pixelColor size scene viewer (RelPoint2D hu hv) =
14 colorFrom $
15 colorAtRay scene ray 0 where ray = pointToRay viewer (RelPoint2D hu hv)
14 colorAtRay scene ray 0 where ray = pointToRay viewer (RelPoint2D hu hv)
1615
1716 colorFor :: Scene
1817 -> Primitive -- | The shape to determine the color for
10099 intersectWithScene scene ray exclude =
101100 mapMaybe (firstIntersection ray) (filter (`notElem` exclude) (geom scene))
102101
103 rayTraceImage :: Scene -> Size -> Point -> Color
104 rayTraceImage scene size (x, y) =
105 pixelColor size scene (viewer scene) (Point2D x y)
55 import Graphics.GD
66 import ArtRay.Geometry
77
8 applyToImage :: (Size -> Point -> Color) -> Image -> IO()
8 -- | Raytrace an image without antialiasing
9 rayTraceImage :: Scene -> Size -> Point2D -> ColorTriple
10 rayTraceImage scene size point@(Point2D x y) =
11 pixelColor size scene (viewer scene) point
12
13 -- | Raytrace an image with antialiasing by subpixel sampling
14 rayTraceImage' :: Scene -> Size -> Point -> ColorTriple
15 rayTraceImage' scene size (x, y) =
16 meanColor $ map (rayTraceImage scene size)
17 [Point2D (fromIntegral x + x') (fromIntegral y + y')
18 | x' <- [(-0.5),inc..0.5], y' <- [(-0.5),inc..0.5]]
19 where inc = (-0.5) + (1 / (fromIntegral $ subpixels scene))
20
21 applyToImage :: (Size -> Point -> ColorTriple) -> Image -> IO()
922 applyToImage imFunc im =
1023 do
1124 size <- imageSize im
12 sequence_ [setPixel (i,j) (imFunc size (i,j)) im | i <- [0..(fst size)], j <- [0..(snd size)]]
25 sequence_ [setPixel (i,j) (colorFrom $ imFunc size (i,j)) im
26 | i <- [0..(fst size)], j <- [0..(snd size)]]
1327
1428 render :: Scene -> Int -> String -> IO()
1529 render scene size outfile =
1630 do
1731 im <- newImage (size, size)
18 applyToImage (rayTraceImage scene) im
32 applyToImage (rayTraceImage' scene) im
1933 savePngFile outfile im
20
66 Compilation is handled by the build.sh script. After running build.sh,
77 you can execute ArtRay as follows:
88
9 ./artray [input scene] [output image]
9 ./ar [input scene] [output image]
1010
1111 Output is always written in PNG format. Input is in ArtRay format, which is
1212 essentially a bunch of nested data constructors. Better docs for this are on
00 if [ ! -d "build" ]; then
11 mkdir build
22 fi
3 ghc ArtRay/Main.hs -o artray -odir build/ -hidir build/ -O
3 ghc ArtRay/Main.hs -o ar -odir build/ -hidir build/ -O
33 center = Vec3 14.0 (-4.0) 0.0,
44 radius = 3.0,
55 material = PhongMaterial {
6 specular = (1.0,1.0,1.0),
7 diffuse = (0.7,0.0,0.0),
8 ambient = (1.0,0.0,0.0),
9 phongexp = 4
10 }
6 specular = (1.0, 1.0, 1.0),
7 diffuse = (0.7, 0.0, 0.0),
8 ambient = (1.0, 0.0, 0.0),
9 phongexp = 4
10 }
1111 },
1212
1313 Sphere {
1414 center = Vec3 10.0 0.0 0.0,
1515 radius = 1.0,
1616 material = PhongMaterial {
17 specular = (1.0,1.0,1.0),
18 diffuse = (0.0,0.7,0.0),
19 ambient = (0.0,1.0,0.0),
20 phongexp = 4
21 }
17 specular = (1.0, 1.0, 1.0),
18 diffuse = (0.0, 0.7, 0.0),
19 ambient = (0.0, 1.0, 0.0),
20 phongexp = 4
21 }
2222 },
23
23
2424 Plane {
2525 pnorm = Vec3 (-2) 0 (-1),
2626 point = Vec3 13 0 6,
2727 material = ReflectiveMaterial {
2828 base = PhongMaterial {
29 specular = (0.0,0.0,0.0),
30 diffuse = (0.0,0.0,0.7),
31 ambient = (0.0,0.0,1.0),
32 phongexp = 4
29 specular = (0.0, 0.0, 0.0),
30 diffuse = (0.0, 0.0, 0.7),
31 ambient = (0.0, 0.0, 1.0),
32 phongexp = 4
3333 },
34 reflectivity = 0.5
35 }
34 reflectivity = 0.5
35 }
3636 }
3737 ],
3838
39 background = (0.0,0.0,0.0),
40 global_ambient = (0.4,0.4,0.4),
39 subpixels = 4,
40 background = (0.0, 0.0, 0.0),
41 globalAmbient = (0.4, 0.4, 0.4),
42
4143 lights = [
4244 PhongLight {
43 speclight = (1.0,1.0,1.0),
44 difflight = (1.0,1.0,1.0),
45 loclight = Vec3 6.0 4.0 0.0
46 }
47 ],
48
45 speclight = (1.0, 1.0, 1.0),
46 difflight = (1.0, 1.0, 1.0),
47 loclight = Vec3 6.0 4.0 0.0
48 }],
49
4950 viewer = Viewer {
5051 location = Vec3 0.0 0.0 0.0,
5152 u = Vec3 0.0 0.422 0.0,
5253 v = Vec3 0.0 0.0 0.422,
53 f = Vec3 1.0 (-0.2) 0.0
54 }
55 }
56
54 f = Vec3 1.0 (-0.2) 0.0
55 }
56 }