initial broken commit
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
module Main where
|
||||
|
||||
import Control.Monad (mapM)
|
||||
import Control.Monad.Random
|
||||
import Data.Ix
|
||||
import Data.Maybe
|
||||
import Debug.Trace
|
||||
import Hittable
|
||||
import Linear.V2
|
||||
import Linear.V3
|
||||
import Linear.Vector
|
||||
import Maths
|
||||
import Ray
|
||||
import Text.Printf
|
||||
|
||||
type Color = (Double, Double, Double)
|
||||
|
||||
type Coord = (Int, Int)
|
||||
|
||||
type ImageDimensions = (Int, Int)
|
||||
|
||||
type ViewPortDimensions = (Double, Double)
|
||||
|
||||
-- TODO
|
||||
-- add multiple samples per pixel
|
||||
-- fix coordinate system
|
||||
-- DONE fix random number generator
|
||||
|
||||
backgroundColor = V3 0.0 0.0 0.0
|
||||
|
||||
-- getRayColor :: (Shape s, RandomGen g) => [s] -> Int -> Ray Double -> Rand g (V3 Double)
|
||||
-- need to accumulate somewhere
|
||||
getRayColor ws d r = do
|
||||
let h = getBestHit (mapMaybe (testHit r) ws)
|
||||
v <- getRayColor' r h ws d
|
||||
return $ v
|
||||
|
||||
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' _ _ _ 0 = do return $ backgroundColor
|
||||
getRayColor' (Ray o d) (Just (Hit t p n)) ws depth =
|
||||
do
|
||||
r <- randV3
|
||||
let target = p ^+^ n ^+^ r
|
||||
nextVal <- (getRayColor ws (depth - 1) (Ray p (target ^-^ p)))
|
||||
return $ colorWithNormal (calculateRayNormal (Ray o d) t) ^+^ (0.5 *^ nextVal)
|
||||
|
||||
colorGradient :: V3 Double -> V3 Double
|
||||
colorGradient (V3 x y z) = do
|
||||
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
|
||||
|
||||
getBestHit :: [Hit] -> Maybe Hit
|
||||
getBestHit [] = Nothing
|
||||
getBestHit (h : hs) = Just (getBestHit' hs h)
|
||||
|
||||
getBestHit' :: [Hit] -> Hit -> Hit
|
||||
getBestHit' (h : hs) bestHit =
|
||||
if root h > root bestHit
|
||||
then getBestHit' hs h
|
||||
else getBestHit' hs bestHit
|
||||
getBestHit' [] hit = hit
|
||||
|
||||
colorWithNormal :: V3 Double -> V3 Double
|
||||
colorWithNormal v = 0.5 *^ (v ^+^ V3 1.0 1.0 1.0)
|
||||
|
||||
rayTrace :: (Shape s, RandomGen g) => (Int, Int) -> ImageDimensions -> ViewPortDimensions -> [s] -> Rand g (V3 Double)
|
||||
rayTrace (x, y) (w, h) (vw, vh) world = do
|
||||
getRayColor world 50 (buildRay (xf * (vw / wf)) (yf * (vh / hf)))
|
||||
where
|
||||
xf = fromIntegral x
|
||||
yf = fromIntegral y
|
||||
wf = fromIntegral (w - 1)
|
||||
hf = fromIntegral (h - 1)
|
||||
|
||||
colorToString :: Color -> IO ()
|
||||
colorToString (x, y, z) = tupToString (xr, yr, zr)
|
||||
where
|
||||
xr = round (x * 255.0)
|
||||
yr = round (y * 255.0)
|
||||
zr = round (z * 255.0)
|
||||
|
||||
tupToString :: (Show a) => (a, a, a) -> IO ()
|
||||
tupToString (x, y, z) = putStrLn (show x ++ " " ++ show y ++ " " ++ show z)
|
||||
|
||||
v3ToColor :: V3 Double -> Color
|
||||
v3ToColor (V3 x y z) = (x, y, z)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
let w = 400
|
||||
let h = 400
|
||||
-- weirdly, the bottom circle appears on top and bottom
|
||||
let world = [Circle (V3 0.0 0.0 1.0) 0.25, Circle (V3 0.0 (-10.05) 1.0) 10]
|
||||
let coords = range ((-1 * (w `div` 2), -1 * (h `div` 2)), ((w `div` 2) - 1, (h `div` 2) - 1)) -- "canvas"
|
||||
--let aspect = 16.0 / 9.0
|
||||
g <- getStdGen
|
||||
let colors = map (\x -> foldl (^+^) (V3 0.0 0.0 0.0) $ replicate 50 $ evalRand (rayTrace x (w - 1, h - 1) (1.0, 1.0) world) g) coords
|
||||
let convertedColors = map v3ToColor colors
|
||||
--mapM_ print colors
|
||||
putStrLn "P3"
|
||||
putStrLn (show w ++ " " ++ show h)
|
||||
putStrLn "255"
|
||||
mapM_ colorToString convertedColors
|
||||
@@ -0,0 +1,51 @@
|
||||
name: wasm-raytracer
|
||||
version: 0.1.0.0
|
||||
github: "githubuser/wasm-raytracer"
|
||||
license: BSD3
|
||||
author: "Author name here"
|
||||
maintainer: "example@example.com"
|
||||
copyright: "2022 Author name here"
|
||||
|
||||
extra-source-files:
|
||||
- README.md
|
||||
- ChangeLog.md
|
||||
|
||||
# Metadata used when publishing your package
|
||||
# synopsis: Short description of your package
|
||||
# category: Web
|
||||
|
||||
# To avoid duplicated efforts in documentation and dealing with the
|
||||
# complications of embedding Haddock markup inside cabal files, it is
|
||||
# common to point users to the README.md file.
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/wasm-raytracer#readme>
|
||||
|
||||
dependencies:
|
||||
- base >= 4.7 && < 5
|
||||
- linear
|
||||
- random
|
||||
- mtl
|
||||
- MonadRandom
|
||||
library:
|
||||
source-dirs: src
|
||||
|
||||
executables:
|
||||
wasm-raytracer-exe:
|
||||
main: Main.hs
|
||||
source-dirs: app
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- wasm-raytracer
|
||||
|
||||
tests:
|
||||
wasm-raytracer-test:
|
||||
main: Spec.hs
|
||||
source-dirs: test
|
||||
ghc-options:
|
||||
- -threaded
|
||||
- -rtsopts
|
||||
- -with-rtsopts=-N
|
||||
dependencies:
|
||||
- wasm-raytracer
|
||||
@@ -0,0 +1,29 @@
|
||||
module Hittable (Shape (..), Circle (..), Hit (..)) where
|
||||
|
||||
import Linear.V3
|
||||
import Linear.Vector
|
||||
import Maths
|
||||
import Ray
|
||||
|
||||
class Shape s where
|
||||
testHit :: Ray Double -> s -> Maybe Hit
|
||||
|
||||
data Circle = Circle (V3 Double) Double
|
||||
|
||||
data Hit = Hit {root :: Double, p :: V3 Double, n :: V3 Double}
|
||||
|
||||
instance Shape Circle where
|
||||
testHit (Ray o d) (Circle center r) =
|
||||
if discriminant < 0.0
|
||||
then Nothing
|
||||
else Just (Hit root p (p - center ^/ r))
|
||||
where
|
||||
co = o - center
|
||||
a = lengthSquared d -- a vector dotted with itself is = lengthSquared
|
||||
b = d `dotP` co
|
||||
c = lengthSquared co - r ^ 2
|
||||
discriminant = b ^ 2 - a * c
|
||||
root = (b * (-1.0) - sqrt discriminant) / a
|
||||
p = rayAt (Ray o d) root
|
||||
|
||||
-- would make sense to build a Functor for shapes
|
||||
@@ -0,0 +1,44 @@
|
||||
module Maths
|
||||
( dotP,
|
||||
lengthSquared,
|
||||
unitVector,
|
||||
randV3,
|
||||
rand,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Monad.Random
|
||||
import Control.Monad.State (State, evalState, get, put)
|
||||
import Debug.Trace
|
||||
import Linear.V3
|
||||
import Linear.Vector
|
||||
import System.Random
|
||||
|
||||
rand :: (RandomGen g) => Rand g Double
|
||||
rand = getRandomR (-1.0, 1.0 :: Double)
|
||||
|
||||
randV3 :: (RandomGen g) => Rand g (V3 Double)
|
||||
randV3 = do
|
||||
x <- rand
|
||||
y <- rand
|
||||
z <- rand
|
||||
return $ V3 x y z
|
||||
|
||||
-- _ -> randV3
|
||||
|
||||
--inf = read "Infinity"
|
||||
|
||||
degToRadians :: (Floating a) => a -> a
|
||||
degToRadians d = (d * pi) / 180.0
|
||||
|
||||
dotP :: (Num a) => V3 a -> V3 a -> a
|
||||
dotP (V3 a b c) (V3 d e f) = a * d + b * e + c * f
|
||||
|
||||
lengthSquared :: (Num a) => V3 a -> a
|
||||
lengthSquared (V3 x y z) = x ^ 2 + y ^ 2 + z ^ 2
|
||||
|
||||
vectorLength :: (Floating f) => V3 f -> f
|
||||
vectorLength v = sqrt (lengthSquared v)
|
||||
|
||||
unitVector :: (Floating f) => V3 f -> V3 f
|
||||
unitVector v = v ^/ vectorLength v
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
module Ray
|
||||
( Ray (..),
|
||||
rayAt,
|
||||
calculateRayNormal,
|
||||
buildRay,
|
||||
)
|
||||
where
|
||||
|
||||
import Linear.V3
|
||||
import Linear.Vector
|
||||
import Maths
|
||||
|
||||
data Ray f = Ray (V3 f) (V3 f)
|
||||
|
||||
-- P(t) = A + tB; A is origin, B is direction
|
||||
rayAt :: (Floating f) => Ray f -> f -> V3 f
|
||||
rayAt (Ray origin dir) t = origin + (t *^ dir)
|
||||
|
||||
-- get the normal of the point at t
|
||||
calculateRayNormal :: (Floating f) => Ray f -> f -> V3 f
|
||||
calculateRayNormal r t = unitVector (rayAt r t ^-^ V3 0.0 0.0 1.0)
|
||||
|
||||
buildRay :: (Floating f) => f -> f -> Ray f
|
||||
buildRay u v = Ray (V3 0.0 0.0 0.0) (V3 v u 1.0)
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
# This file was automatically generated by 'stack init'
|
||||
#
|
||||
# Some commonly used options have been documented as comments in this file.
|
||||
# For advanced use and comprehensive documentation of the format, please see:
|
||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||
|
||||
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
||||
# A snapshot resolver dictates the compiler version and the set of packages
|
||||
# to be used for project dependencies. For example:
|
||||
#
|
||||
# resolver: lts-3.5
|
||||
# resolver: nightly-2015-09-21
|
||||
# resolver: ghc-7.10.2
|
||||
#
|
||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||
#
|
||||
# resolver: ./custom-snapshot.yaml
|
||||
# resolver: https://example.com/snapshots/2018-01-01.yaml
|
||||
resolver:
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/15.yaml
|
||||
|
||||
# User packages to be built.
|
||||
# Various formats can be used as shown in the example below.
|
||||
#
|
||||
# packages:
|
||||
# - some-directory
|
||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||
# subdirs:
|
||||
# - auto-update
|
||||
# - wai
|
||||
packages:
|
||||
- .
|
||||
# Dependency packages to be pulled from upstream that are not in the resolver.
|
||||
# These entries can reference officially published versions as well as
|
||||
# forks / in-progress versions pinned to a git hash. For example:
|
||||
#
|
||||
# extra-deps:
|
||||
# - acme-missiles-0.3
|
||||
# - git: https://github.com/commercialhaskell/stack.git
|
||||
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||
#
|
||||
# extra-deps: []
|
||||
|
||||
# Override default flag values for local packages and extra-deps
|
||||
# flags: {}
|
||||
|
||||
# Extra package databases containing global packages
|
||||
# extra-package-dbs: []
|
||||
|
||||
# Control whether we use the GHC we find on the path
|
||||
# system-ghc: true
|
||||
#
|
||||
# Require a specific version of stack, using version ranges
|
||||
# require-stack-version: -any # Default
|
||||
# require-stack-version: ">=2.7"
|
||||
#
|
||||
# Override the architecture used by stack, especially useful on Windows
|
||||
# arch: i386
|
||||
# arch: x86_64
|
||||
#
|
||||
# Extra directories used by stack for building
|
||||
# extra-include-dirs: [/path/to/dir]
|
||||
# extra-lib-dirs: [/path/to/dir]
|
||||
#
|
||||
# Allow a newer minor version of GHC than the snapshot specifies
|
||||
# compiler-check: newer-minor
|
||||
@@ -0,0 +1,74 @@
|
||||
cabal-version: 1.12
|
||||
|
||||
-- This file has been generated from package.yaml by hpack version 0.34.7.
|
||||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: wasm-raytracer
|
||||
version: 0.1.0.0
|
||||
description: Please see the README on GitHub at <https://github.com/githubuser/wasm-raytracer#readme>
|
||||
homepage: https://github.com/githubuser/wasm-raytracer#readme
|
||||
bug-reports: https://github.com/githubuser/wasm-raytracer/issues
|
||||
author: Author name here
|
||||
maintainer: example@example.com
|
||||
copyright: 2022 Author name here
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
build-type: Simple
|
||||
extra-source-files:
|
||||
README.md
|
||||
ChangeLog.md
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://github.com/githubuser/wasm-raytracer
|
||||
|
||||
library
|
||||
exposed-modules:
|
||||
Hittable
|
||||
Maths
|
||||
Ray
|
||||
other-modules:
|
||||
Paths_wasm_raytracer
|
||||
hs-source-dirs:
|
||||
src
|
||||
build-depends:
|
||||
MonadRandom
|
||||
, base >=4.7 && <5
|
||||
, linear
|
||||
, mtl
|
||||
, random
|
||||
default-language: Haskell2010
|
||||
|
||||
executable wasm-raytracer-exe
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
Paths_wasm_raytracer
|
||||
hs-source-dirs:
|
||||
app
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
MonadRandom
|
||||
, base >=4.7 && <5
|
||||
, linear
|
||||
, mtl
|
||||
, random
|
||||
, wasm-raytracer
|
||||
default-language: Haskell2010
|
||||
|
||||
test-suite wasm-raytracer-test
|
||||
type: exitcode-stdio-1.0
|
||||
main-is: Spec.hs
|
||||
other-modules:
|
||||
Paths_wasm_raytracer
|
||||
hs-source-dirs:
|
||||
test
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends:
|
||||
MonadRandom
|
||||
, base >=4.7 && <5
|
||||
, linear
|
||||
, mtl
|
||||
, random
|
||||
, wasm-raytracer
|
||||
default-language: Haskell2010
|
||||
Reference in New Issue
Block a user