Skip to content

Commit

Permalink
* Add box geometry + example scenes
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnovak committed Oct 12, 2016
1 parent 832eb91 commit 37ce33a
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 6 deletions.
2 changes: 1 addition & 1 deletion nim.cfg
@@ -1 +1 @@
path="../nim-nanovg/src"
path="../nim-glm-fork"
88 changes: 88 additions & 0 deletions src/data/scenes/boxes-pointlight1.nim
@@ -0,0 +1,88 @@
let objects = @[
Object(
name: "box1",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(-5.0, 2.0, -18.0))
.rotate(vec3(0.0, 1.0, 0.0), degToRad(-10.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.9, 0.3, 0.2))
),
Object(
name: "box2",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(0.5, 2.0, -8.0))
.rotate(vec3(1.0, 0.0, 0.0), degToRad(-30.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.6, 0.9, 0.2))
),
Object(
name: "box3",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(-5.0, 2.0, -10.0))
.rotate(vec3(1.0, 0.0, 0.0), degToRad(-50.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.1, 0.7, 0.2))
),
Object(
name: "box4",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(8.0, 2.0, -15.0))
.rotate(vec3(1.0, 0.0, 0.0), degToRad(-70.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.2, 0.3, 0.9))
),
Object(
name: "box5",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(4.0, 2.0, -16.0))
.rotate(vec3(1.0, 0.0, 0.0), degToRad(-60.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.2, 0.5, 0.9))
),
Object(
name: "box6",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(-2.0, 2.0, -42.0))
.rotate(vec3(1.0, 0.0, 0.0), degToRad(-40.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.9, 0.5, 0.2))
),
Object(
name: "box7",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(9.0, 2.0, -30.0))
.rotate(vec3(1.0, 0.0, 0.0), degToRad(-20.0)),
vmin = vec(-1.0, -1.0, -1.0), vmax = vec(1.0, 1.0, 1.0)),
material: Material(albedo: vec3(0.6, 0.5, 0.9))
),
Object(
name: "ground",
geometry: initPlane(objectToWorld = mat4(1.0)),
material: Material(albedo: vec3(0.4))
)
]


var lights = newSeq[Light]()

lights.add(
DistantLight(color: vec3(1.0), intensity: 4.0,
dir: vec(-2.0, -0.8, -0.3).normalize)
)
lights.add(
DistantLight(color: vec3(0.8, 0.3, 0.0), intensity: 1.0,
dir: vec(2.0, -0.8, -1.3).normalize)
)


var scene = Scene(
bgColor: vec3(0.0, 0.0, 0.0),

objects: objects,
lights: lights,

fov: 50.0,
cameraToWorld: mat4(1.0).rotate(vec3(1.0, 0, 0), degToRad(-12.0))
.translate(vec3(1.0, 5.5, 3.5))
)

70 changes: 70 additions & 0 deletions src/data/scenes/boxes.nim
@@ -0,0 +1,70 @@
var objects = newSeq[Object]()

objects.add(
Object(
name: "ground",
geometry: initPlane(objectToWorld = mat4(1.0)),
material: Material(albedo: vec3(0.4))
)
)

let ROWS = 4
let PAD = 3.8

let
xs = 0.0
ys = 3.0
zs = -18.0

var
x = xs
y = ys
z = zs

for i in 0..<ROWS:
for j in 0..<ROWS:
for k in 0..<ROWS:
objects.add(
Object(
name: "box",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(x, y, z)),
vmin = vec(-1.3, -1.3, -1.3), vmax = vec(1.3, 1.3, 1.3)),
material: Material(albedo: vec3(1.0 / ROWS.float * (ROWS-k).float,
1.0 / ROWS.float * (ROWS-j).float,
1.0 / ROWS.float * (ROWS-i).float))
)
)

x += PAD
y += PAD
x = xs
z -= PAD
x = xs
y = ys


var lights = newSeq[Light]()

lights.add(
DistantLight(color: vec3(1.0), intensity: 4.0,
dir: vec(-2.0, -0.8, -0.3).normalize)
)
lights.add(
DistantLight(color: vec3(0.8, 0.3, 0.0), intensity: 1.0,
dir: vec(2.0, -0.8, -1.3).normalize)
)


var scene = Scene(
bgColor: vec3(0.15, 0.09, 0.07),

objects: objects,
lights: lights,

fov: 65.0,
cameraToWorld: mat4(1.0).rotate(X_AXIS, degToRad(-34.0))
.rotate(Y_AXIS, degToRad(-35.0))
.translate(vec3(-3.5, 20.5, 9.5))
)

65 changes: 65 additions & 0 deletions src/data/scenes/boxes2.nim
@@ -0,0 +1,65 @@
var objects = newSeq[Object]()

objects.add(
Object(
name: "ball1",
geometry: initSphere(
objectToWorld = mat4(1.0).translate(vec3(0.0, 1.5, -18.0)),
r = 1.5),
material: Material(albedo: vec3(0.5))
)
)

objects.add(
Object(
name: "ground",
geometry: initPlane(objectToWorld = mat4(1.0)),
material: Material(albedo: vec3(0.3))
)
)

let N = 12
var rot = 0.0

for i in 0..<N:
objects.add(
Object(
name: "box",
geometry: initBox(
objectToWorld = mat4(1.0).translate(vec3(0.0, 0.5, -18.0))
.rotate(Y_AXIS, degToRad(rot))
.translate(vec3(0.0, 0.0, 5.0)),
vmin = vec(-0.5, -0.5, -0.5), vmax = vec(0.5, 0.5, 0.5)),
material: Material(albedo: vec3(0.5))
)
)
rot += 360.0 / N.float


var lights = newSeq[Light]()

lights.add(
PointLight(color: vec3(1.0, 0.8, 0.5), intensity: 4000.0,
pos: point(2.0, 8.0, -25.0))
)
lights.add(
DistantLight(color: vec3(1.0, 0.0, 0.0), intensity: 3.0,
dir: vec(1.7, -0.5, 2.3).normalize)
)
lights.add(
DistantLight(color: vec3(1.0, 0.0, 0.0), intensity: 0.3,
dir: vec(-6.0, -0.5, -2.3).normalize)
)


var scene = Scene(
bgColor: vec3(0.15, 0.07, 0.04),

objects: objects,
lights: lights,

fov: 50.0,
cameraToWorld: mat4(1.0).rotate(X_AXIS, degToRad(-15.0))
.translate(vec3(0.0, 4.8, -4.5))
)

Binary file added src/raytracer
Binary file not shown.
8 changes: 4 additions & 4 deletions src/raytracer.nim
Expand Up @@ -40,14 +40,14 @@ when not defined(SINGLE_THREADED):

proc main() =
let opts = Options(
width: 600,
height: 400,
antialias: Antialias(kind: akNone, gridSize: 4),
width: 1200,
height: 800,
antialias: Antialias(kind: akMultiJittered, gridSize: 4),
bias: 0.00000001,
maxRayDepth: 5
)

include data/scenes/spheres-pointlight1.nim
include data/scenes/boxes2.nim

var framebuf = newFramebuf(opts.width, opts.height)
let numLines = opts.height
Expand Down
75 changes: 74 additions & 1 deletion src/renderer/geom.nim
Expand Up @@ -4,8 +4,15 @@ import glm
import ../utils/mathutils


const X_AXIS* = vec3(1.0, 0.0, 0.0)
const Y_AXIS* = vec3(0.0, 1.0, 0.0)
const Z_AXIS* = vec3(0.0, 0.0, 1.0)

template vec*[T](x, y, z: T): Vec4[T] = vec4(x, y, z, 0.0)
template vec*[T](v: Vec4[T]): Vec4[T] = vec4(v.xyz, 0.0)

template point*[T](x, y, z: T): Vec4[T] = vec4(x, y, z, 1.0)
template point*[T](v: Vec4[T]): Vec4[T] = vec4(v.xyz, 1.0)

template isVec*[T] (v: Vec4[T]): bool = v.w == 0.0
template isPoint*[T](v: Vec4[T]): bool = v.w == 1.0
Expand All @@ -20,6 +27,45 @@ proc `$`*(r: Ray): string =
result = "Ray(pos=" & $r.pos & ", dir=" & $r.dir & ")"


type
AABB* = ref object
vmin, vmax: Vec4[float]

method `$`*(b: AABB): string =
result = "AABB(vmin=" & $b.vmin & ", vmax=" & $b.vmax & ")"

method intersect*(b: AABB, r: Ray): float =
var
tmin = (b.vmin.x - r.pos.x) / r.dir.x
tmax = (b.vmax.x - r.pos.x) / r.dir.x

if (tmin > tmax): swap(tmin, tmax)

var
tymin = (b.vmin.y - r.pos.y) / r.dir.y
tymax = (b.vmax.y - r.pos.y) / r.dir.y

if (tymin > tymax): swap(tymin, tymax)

if (tmin > tymax) or (tymin > tmax): return -Inf

if tymin > tmin: tmin = tymin
if tymax < tmax: tmax = tymax

var
tzmin = (b.vmin.z - r.pos.z) / r.dir.z
tzmax = (b.vmax.z - r.pos.z) / r.dir.z

if (tzmin > tzmax): swap(tzmin, tzmax)

if tmin > tzmax or tzmin > tmax: return -Inf

if tzmin > tmin: tmin = tzmin
if tzmax < tmax: tmax = tzmax

return tmin


type
Geometry* = ref object of RootObj
objectToWorld*: Mat4x4[float]
Expand All @@ -31,6 +77,9 @@ type
Plane* = ref object of Geometry
discard

Box* = ref object of Geometry
aabb*: AABB


proc initSphere*(r: float, objectToWorld: Mat4x4[float]): Sphere =
result = Sphere(r: r,
Expand All @@ -42,6 +91,11 @@ proc initPlane*(objectToWorld: Mat4x4[float]): Plane =
result = Plane(objectToWorld: objectToWorld,
worldToObject: objectToWorld.inverse)

proc initBox*(vmin, vmax: Vec4[float], objectToWorld: Mat4x4[float]): Box =
result = Box(aabb: AABB(vmin: vmin, vmax: vmax),
objectToWorld: objectToWorld,
worldToObject: objectToWorld.inverse)


method `$`*(g: Geometry): string {.base.} = ""

Expand All @@ -51,6 +105,9 @@ method `$`*(s: Sphere): string =
method `$`*(p: Plane): string =
result = "Plane(objectToWorld: " & $p.objectToWorld & ")"

method `$`*(b: Box): string =
result = "Box(aabb=" & $b.aabb &
", objectToWorld: " & $b.objectToWorld & ")"

method intersect*(g: Geometry, r: Ray): float {.base.} = -Inf

Expand Down Expand Up @@ -87,16 +144,32 @@ method intersect*(p: Plane, r: Ray): float =
else:
result = -Inf

method intersect*(b: Box, r: Ray): float =
result = intersect(b.aabb, r)


method normal*(g: Geometry, p: Vec4[float]): Vec4[float] {.base.} =
vec4(0.0)

method normal*(s: Sphere, hit: Vec4[float]): Vec4[float] =
result = vec4(hit.xyz, 0).normalize
result = vec(hit).normalize

method normal*(p: Plane, hit: Vec4[float]): Vec4[float] =
result = vec(0.0, 1.0, 0.0)

method normal*(b: Box, hit: Vec4[float]): Vec4[float] =
let
c = (b.aabb.vmin + b.aabb.vmax) * 0.5
d = vec(hit - c)
dx = abs(b.aabb.vmin.x - b.aabb.vmax.x) * 0.5
dy = abs(b.aabb.vmin.y - b.aabb.vmax.y) * 0.5
dz = abs(b.aabb.vmin.z - b.aabb.vmax.z) * 0.5
bias = 1.0000001

result = vec(float((d.x / dx * bias).int),
float((d.y / dy * bias).int),
float((d.z / dz * bias).int)).normalize


# Tests

Expand Down
1 change: 1 addition & 0 deletions src/renderer/nim.cfg
@@ -0,0 +1 @@
path="../../../nim-glm-fork"

0 comments on commit 37ce33a

Please sign in to comment.