Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions Camera.roc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
interface Camera
exposes [Camera, make, ray]
imports [Vec.{ Vec }, Ray.{ Ray }, RNG.{ RNG }, Math]
module [Camera, make, ray]

import Vec exposing [Vec]
import Ray exposing [Ray]
import RNG exposing [RNG]
import Math

Camera : {
origin : Vec,
Expand All @@ -14,7 +17,7 @@ Camera : {
}

make : { lookFrom : Vec, lookAt : Vec, up : Vec, fov : F64, aspectRatio : F64, aperture : F64, focusDist : F64 } -> Camera
make = \{ lookFrom, lookAt, up, fov, aspectRatio, aperture, focusDist } ->
make = |{ lookFrom, lookAt, up, fov, aspectRatio, aperture, focusDist }|
theta = Math.degToRad fov
h = Num.tan (theta / 2)
viewportHeight = 2 * h
Expand Down Expand Up @@ -48,8 +51,8 @@ make = \{ lookFrom, lookAt, up, fov, aspectRatio, aperture, focusDist } ->
}

ray : Camera, F64, F64, RNG, (RNG, Ray -> a) -> a
ray = \{ u, v, lowerLeftCorner, lensRadius, horizontal, vertical, origin }, s, t, rng, fn ->
newRng, unitDisk <- RNG.vecInUnitDisk rng
ray = |{ u, v, lowerLeftCorner, lensRadius, horizontal, vertical, origin }, s, t, rng, fn|
{ newRng, unitDisk } = RNG.vecInUnitDisk rng
rd = Vec.scale unitDisk lensRadius

offset = Vec.add (Vec.scale u rd.x) (Vec.scale v rd.y)
Expand Down
46 changes: 23 additions & 23 deletions Color.roc
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
interface Color
exposes [
Color,
zero,
one,
neg,
add,
sub,
mul,
div,
scale,
shrink,
toPixel,
]
imports [Math]
module [
Color,
zero,
one,
neg,
add,
sub,
mul,
div,
scale,
shrink,
toPixel,
]

import Math

Color : { r : F64, g : F64, b : F64 }

Expand All @@ -23,53 +23,53 @@ one : Color
one = { r: 1, g: 1, b: 1 }

neg : Color -> Color
neg = \c -> {
neg = |c| {
r: -c.r,
g: -c.g,
b: -c.b,
}

add : Color, Color -> Color
add = \a, b -> {
add = |a, b| {
r: a.r + b.r,
g: a.g + b.g,
b: a.b + b.b,
}

sub : Color, Color -> Color
sub = \a, b -> {
sub = |a, b| {
r: a.r - b.r,
g: a.g - b.g,
b: a.b - b.b,
}

mul : Color, Color -> Color
mul = \a, b -> {
mul = |a, b| {
r: a.r * b.r,
g: a.g * b.g,
b: a.b * b.b,
}

div : Color, Color -> Color
div = \a, b -> {
div = |a, b| {
r: a.r / b.r,
g: a.g / b.g,
b: a.b / b.b,
}

scale : Color, F64 -> Color
scale = \c, t -> {
scale = |c, t| {
r: c.r * t,
g: c.g * t,
b: c.b * t,
}

shrink : Color, F64 -> Color
shrink = \c, t ->
shrink = |c, t|
scale c (1 / t)

toPixel : Color, Num * -> { r : U8, g : U8, b : U8 }
toPixel = \{ r, g, b }, samples ->
toPixel = |{ r, g, b }, samples|
if Num.isZero samples then
{ r: 0, g: 0, b: 0 }
else
Expand Down
9 changes: 5 additions & 4 deletions HitRecord.roc
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
interface HitRecord
exposes [HitRecord, make]
imports [Vec.{ Vec }, Ray.{ Ray }]
module [HitRecord, make]

import Vec exposing [Vec]
import Ray exposing [Ray]

HitRecord : { p : Vec, normal : Vec, t : F64, frontFace : Bool }

make : { p : Vec, t : F64, ray : Ray, outwardNormal : Vec } -> HitRecord
make = \{ p, t, ray, outwardNormal } ->
make = |{ p, t, ray, outwardNormal }|
frontFace = Vec.dot ray.direction outwardNormal < 0
normal = if frontFace then outwardNormal else Vec.neg outwardNormal

Expand Down
40 changes: 23 additions & 17 deletions Material.roc
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
interface Material
exposes [Material, scatter]
imports [Color.{ Color }, RNG.{ RNG }, Vec, Ray.{ Ray }, HitRecord.{ HitRecord }, Math]
module [Material, scatter]

import Color exposing [Color]
import RNG exposing [RNG]
import Vec
import Ray exposing [Ray]
import HitRecord exposing [HitRecord]
import Math

ScatterRecord : { attenuation : Color, scattered : Ray }

Material : [Lambertian Color, Metal Color F64, Dielectric F64]

scatter : Material, Ray, HitRecord, RNG, (RNG, Result ScatterRecord [NoHit] -> a) -> a
scatter = \material, ray, rec, rng, fn ->
scatter = |material, ray, rec, rng, fn|
when material is
Lambertian albedo -> lambertian albedo rec rng fn
Metal albedo fuzz -> metal albedo fuzz ray rec rng fn
Dielectric ir -> dielectric ir ray rec rng fn

lambertian = \albedo, rec, rng, fn ->
newRng, unitVec <- RNG.unitVec rng
lambertian = |albedo, rec, rng, fn|
{ newRng, unitVec } = RNG.unitVec rng fn

scatterDirection = Vec.add rec.normal unitVec

direction = if Vec.nearZero scatterDirection then rec.normal else scatterDirection
scattered = { origin: rec.p, direction }

fn newRng (Ok { attenuation: albedo, scattered })

metal = \albedo, fuzz, ray, rec, rng, fn ->
newRng, unitSphere <- RNG.vecInUnitSphere rng
fn newRng |{ x, y, z }| { x, y, z }
# fn newRng (Ok { attenuation: albedo, scattered })
# fn newRng (Ok { attenuation: albedo, scattered = { origin: rec.p, direction } })
metal = |albedo, fuzz, ray, rec, rng, fn|
{ newRng, unitSphere } = RNG.vecInUnitSphere rng fn
reflected = Vec.unit ray.direction |> Vec.reflect rec.normal

scattered = { origin: rec.p, direction: Vec.scale unitSphere fuzz |> Vec.add reflected }
Expand All @@ -33,8 +39,7 @@ metal = \albedo, fuzz, ray, rec, rng, fn ->
fn newRng (Ok { attenuation: albedo, scattered })
else
fn newRng (Err NoHit)

dielectric = \ir, ray, rec, rng, fn ->
dielectric = |ir, ray, rec, rng, fn|
refractionRatio = if rec.frontFace then 1 / ir else ir

unitDirection = Vec.unit ray.direction
Expand All @@ -44,18 +49,19 @@ dielectric = \ir, ray, rec, rng, fn ->

cannotRefract = refractionRatio * sinTheta > 1

newRng, real <- RNG.real rng
{ newRng, real } = RNG.real |rng, x| x

direction = if cannotRefract || reflectance cosTheta refractionRatio > real then
direction = (
if cannotRefract or reflectance cosTheta refractionRatio > real then
Vec.reflect unitDirection rec.normal
else
Vec.refract unitDirection rec.normal refractionRatio
)

scattered = { origin: rec.p, direction}
scattered = { origin: rec.p, direction }

fn newRng (Ok { attenuation: Color.one, scattered })

reflectance = \cosine, refIdx ->
reflectance = |cosine, refIdx|
r = (1 - refIdx) / (1 + refIdx)
r0 = r * r
r0 + (1 - r0) * Num.pow (1 - cosine) 5
12 changes: 5 additions & 7 deletions Math.roc
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
interface Math
exposes [pi, degToRad, clamp, min, max]
imports []
module [pi, degToRad, clamp, min, max]

pi : F64
pi = 3.1415926535897932385

degToRad : F64 -> F64
degToRad = \deg ->
degToRad = |deg|
deg * pi / 180

clamp : F64, { min : F64, max : F64 } -> F64
clamp = \x, range ->
clamp = |x, range|
if x < range.min then
range.min
else if x > range.max then
Expand All @@ -19,14 +17,14 @@ clamp = \x, range ->
x

min : F64, F64 -> F64
min = \a, b ->
min = |a, b|
if a < b then
a
else
b

max : F64, F64 -> F64
max = \a, b ->
max = |a, b|
if a > b then
a
else
Expand Down
Loading