Skip to content

Instantly share code, notes, and snippets.

@jrraymond
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrraymond/70803b1fccc221efe580 to your computer and use it in GitHub Desktop.
Save jrraymond/70803b1fccc221efe580 to your computer and use it in GitHub Desktop.
vectors_conundrum
type Point = (Float,Float)
type GridU = U.Vector Point
{- Explanation: colorPixel evaluates to the color of a pixel for a given world
- Antialiasing is tracing > 1 rays through each pixel and averaging the results.
- Soft shadows are shadows that do not have a hard edge, this requires sending multiple shadow rays to each light.
- Depth of field: only objects at a certain distance are in focus. To do this we send multiple rays though each antialising
- point with each base perturbed slightly. Objects are in focus if they are at the distance the view plane is at.
-
- Three arguments:
- World -> all the information needed to color a pixel, objects, lights, eye point, view plane distance etc etc
- (Point,(V.Vector (U.Vector Point),(GridU,GridU))) ->
- The first element (Point) is the screen cordinates of the pixel ex: (0,0) (0,1)
- The (V.Vector (U.Vector Point)) is a two dimensional vector of Points used to perturb the base of the ray being traced
- to simulate a depth of field effect .
The length of the U.Vector Point == the number of depth of field rays being used.
The length of V.Vector (U.Vector Point) == the number of antialiasing rays.
- (GridU,GridU) -> Two unboxed vectors of points used for antialiasing and soft shadows respectively.
- The first is the screen coordinates through which to send the rays. These are randomly jittered.
- The second is the first grid shuffled.
- The length of each GridU == the number of antialiasing rays.
- For the first point in the antialising grid, we send (# depth of field rays) rays through that point and average the results.
- We repeat this for all points in the antialiasing grid.
- Performance wise this ended up being 2x as slow on a given scene as the list version but ran in 30% space.
-}
{- world, image plane point, list of list of points for dof pertubations,
- jittered grid for antialiasing, shuffled jittered grid for soft shadows -}
colorPixel :: World
-> (Point,(V.Vector (U.Vector Point),(GridU,GridU)))
-> Color
colorPixel w ((i,j),(rrs,(pts,sh_grid))) = avgColorsU (U.convert cs0) where
d = wMaxDepth w
cs0 = V.imap (\ix rs -> let (p,q) = pts U.! ix
rfts = sh_grid U.! ix --this is used to create soft shadows and is passed along by ray (read Random FloaT Shadow)
rays = U.map (getRay w (i+p,j+q)) rs
colors = U.map (raytrace w d rfts) rays
in avgColorsU colors) rrs
-- in Main this is how colorPixel is used
wd = cImageWidth c
ht = cImageHeight c
rs0 = chunksOf (wAntiAliasing w) (chunksOf (wDOF w) (randomPairs rng))
rs = V.map (V.map U.fromList . V.fromList) (V.fromListN (cImageWidth c + 10) rs0)
grids = generateGridsU rng (cImageWidth c + 10) (wAntiAliasing w)
info = V.zip rs grids
infol = V.length info
img = U.generate (wd * ht)
(\i -> colorPixel w (pixelIx wd ht i, info V.! mod i infol))
{-if you we interested in pixlelIx
- For 8x6 image it turns [0..n] into (0,5),(1,5),(2,5)..(7,5),
(0,4),(1,4).. (7,4),
(0,3),(1,3).. (7,3)...
-}
pixelIx :: Int -> Int -> Int -> (Float,Float)
pixelIx wd ht i = (fromIntegral (mod i wd), fromIntegral (ht - 1 - div i wd))
{- Explanation: colorPixel evaluates to the color of a pixel for a given world
- Three arguments:
- World -> all the information needed to color a pixel, objects, lights, etc etc
- (Point,(U.Vector Point,(GridU,GridU))) ->
- The first element (Point) is the screen cordinates of the pixel ex: (0,0) (0,1)
- The (U.Vector Point)) is the previous vector but smushed into a 1 dimensional vector.
- The length == num depth of field rays * num anti aliasing rays.
- (GridU,GridU) -> Two unboxed vectors of points used for antialiasing and soft shadows respectively.
- The first is the screen coordinates through which to send the rays. These are randomly jittered.
- The second is the first grid shuffled.
- The length of each GridU == the number of antialiasing rays.
-
- This ended up being much slower. Previously took 340 seconds on a complex scene with 64 antialiasing rays. Now takes > 20 minutes. I didn't wait to learn how long it actually would take.
-}
{- world, image plane point, points for dof pertubations,
- jittered grid for antialiasing, shuffled jittered grid for soft shadows -}
colorPixel :: World
-> (Point,(U.Vector Point,(GridU,GridU)))
-> Color
colorPixel w ((i,j),(rrs,(pts,sh_grid))) = avgColorsU cs0 where
d = wMaxDepth w
dof = wDOF w
cs0 = U.izipWith f pts sh_grid
f ix (p,q) rfts = let rs = U.slice (ix * dof) dof rrs --TODO try unsafe slice
in avgColorsU $ U.map (raytrace w d rfts . getRay w (i+p,j+q)) rs
--and it is used in main in the same way:
wd = cImageWidth c
ht = cImageHeight c
rs0 = chunksOf (cAntiAliasing c) (chunksOf (wDOF w) (randomPairs rng))
rs = V.map (U.fromList . concat) (V.fromListN (cImageWidth c + 10) rs0)
grids = generateGridsU rng (cImageWidth c + 10) (wAntiAliasing w)
info = V.zip rs grids
infol = V.length info
img = U.generate (wd * ht)
(\i -> colorPixel w (pixelIx wd ht i, info V.! mod i infol))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment