Skip to content

Commit

Permalink
Merge pull request #9 from quephird/implememt_soft_shadows
Browse files Browse the repository at this point in the history
Implememt soft shadows
  • Loading branch information
quephird committed Oct 13, 2022
2 parents 4e70d3a + 29bee59 commit 5ef07da
Show file tree
Hide file tree
Showing 12 changed files with 590 additions and 218 deletions.
4 changes: 4 additions & 0 deletions Sources/ScintillaLib/Color.swift
Expand Up @@ -33,6 +33,10 @@ public struct Color {
Color(self.r*scalar, self.g*scalar, self.b*scalar)
}

func divideScalar(_ scalar: Double) -> Self {
return self.multiplyScalar(1.0/scalar)
}

func hadamard(_ other: Self) -> Self {
Color(self.r*other.r, self.g*other.g, self.b*other.b)
}
Expand Down
296 changes: 148 additions & 148 deletions Sources/ScintillaLib/Examples.swift
Expand Up @@ -7,154 +7,154 @@

import Foundation

func testScene() -> World {
return World {
Light(point(-10, 10, -10))
Camera(800, 600, PI/3, .view(
point(0, 10, -15),
point(0, 0, 0),
vector(0, 1, 0)))
for n in 0...3 {
Cube(.solidColor(Color(1, 0, 0)))
.rotateY(PI/6)
.rotateX(PI/6)
.rotateZ(PI/6)
.translate(4*cos(Double(n)*PI/2), 0, 4*sin(Double(n)*PI/2))
}
}
}

func testGroup() -> World {
return World {
Light(point(-10, 10, -10))
Camera(800, 600, PI/3, .view(
point(0, 5, -10),
point(0, 0, 0),
vector(0, 1, 0)))
Group {
Sphere(.solidColor(Color(1, 0, 0)))
for n in 0...2 {
Sphere(.solidColor(Color(0, 1, 0)))
.translate(2, 0, 0)
.rotateY(2*Double(n)*PI/3)
}
}
.translate(0, 1, 0)
Plane(.pattern(Checkered2D(.black, .white, .identity)))
}
}

func testTorus() -> World {
return World {
Light(point(-10, 10, -10))
Camera(800, 600, PI/3, .view(
point(0, 5, -10),
point(0, 0, 0),
vector(0, 1, 0)))
Torus(.solidColor(Color(1, 0.5, 0)))
.translate(0, 1, 0)
Plane(.pattern(Checkered2D(.black, .white, .identity)))
}
}

func testDie() -> World {
let material = Material.solidColor(Color(1, 0.5, 0))
.reflective(0.2)

return World {
Light(point(-10, 10, -10))
Camera(800, 600, PI/3, .view(
point(0, 5, -10),
point(0, 0, 0),
vector(0, 1, 0)))
Cube(material).intersection {
Sphere(material)
.scale(1.55, 1.55, 1.55)
Cylinder(material, -2, 2, true)
.scale(1.35, 1.35, 1.35)
Cylinder(material, -2, 2, true)
.scale(1.35, 1.35, 1.35)
.rotateX(PI/2)
Cylinder(material, -2, 2, true)
.scale(1.35, 1.35, 1.35)
.rotateZ(PI/2)
}.difference {
for (x, y, z) in [
// face with six dimples
(-0.6, 1.0, 0.6),
(-0.6, 1.0, 0.0),
(-0.6, 1.0, -0.6),
(0.6, 1.0, 0.6),
(0.6, 1.0, 0.0),
(0.6, 1.0, -0.6),
// face with five dimples
(0.0, 0.0, -1.0),
(0.6, 0.6, -1.0),
(0.6, -0.6, -1.0),
(-0.6, 0.6, -1.0),
(-0.6, -0.6, -1.0),
// face with four dimples
(1.0, 0.6, 0.6),
(1.0, 0.6, -0.6),
(1.0, -0.6, 0.6),
(1.0, -0.6, -0.6),
// face with three dimples
(-1.0, 0.6, 0.6),
(-1.0, 0, 0),
(-1.0, -0.6, -0.6),
// face with two dimples
(0.6, 0.6, 1.0),
(-0.6, -0.6, 1.0),
// face with one dimple
(0.0, -1.0, 0.0),
] {
Sphere(.solidColor(Color(1, 1, 1)))
.scale(0.2, 0.2, 0.2)
.translate(x, y, z)
}
}
.rotateY(PI/3)
.translate(0.0, 1.0, 0.0)
Plane(.pattern(Checkered2D(.black, .white, .identity)))
}
}

func chapterSevenScene() -> World {
return World {
Light(point(-10, 10, -10))
Camera(800, 600, PI/3, .view(
point(0, 2, -5),
point(0, 0, 0),
vector(0, 1, 0)))
Sphere(.solidColor(Color(1, 0.9, 0.9)))
.scale(10, 0.01, 10)
Sphere(.solidColor(Color(1, 0.9, 0.9)))
.scale(10, 0.01, 10)
.rotateX(PI/2)
.rotateY(-PI/4)
.translate(0, 0, 5)
Sphere(.solidColor(Color(1, 0.9, 0.9)))
.scale(10, 0.01, 10)
.rotateX(PI/2)
.rotateY(PI/4)
.translate(0, 0, 5)
Sphere(.solidColor(Color(1, 0.8, 0.1))
.diffuse(0.7)
.specular(0.3))
.scale(0.33, 0.33, 0.33)
.translate(-1.5, 0.33, -0.75)
Sphere(.solidColor(Color(0.1, 1.0, 0.5))
.diffuse(0.7)
.specular(0.3))
.translate(-0.5, 1.0, 0.5)
Sphere(.solidColor(Color(0.5, 1, 0.1))
.diffuse(0.7)
.specular(0.3))
.scale(0.5, 0.5, 0.5)
.translate(1.5, 0.5, -0.5)
}
}

//func testScene() -> World {
// return World {
// Light(point(-10, 10, -10))
// Camera(800, 600, PI/3, .view(
// point(0, 10, -15),
// point(0, 0, 0),
// vector(0, 1, 0)))
// for n in 0...3 {
// Cube(.solidColor(Color(1, 0, 0)))
// .rotateY(PI/6)
// .rotateX(PI/6)
// .rotateZ(PI/6)
// .translate(4*cos(Double(n)*PI/2), 0, 4*sin(Double(n)*PI/2))
// }
// }
//}
//
//func testGroup() -> World {
// return World {
// Light(point(-10, 10, -10))
// Camera(800, 600, PI/3, .view(
// point(0, 5, -10),
// point(0, 0, 0),
// vector(0, 1, 0)))
// Group {
// Sphere(.solidColor(Color(1, 0, 0)))
// for n in 0...2 {
// Sphere(.solidColor(Color(0, 1, 0)))
// .translate(2, 0, 0)
// .rotateY(2*Double(n)*PI/3)
// }
// }
// .translate(0, 1, 0)
// Plane(.pattern(Checkered2D(.black, .white, .identity)))
// }
//}
//
//func testTorus() -> World {
// return World {
// Light(point(-10, 10, -10))
// Camera(800, 600, PI/3, .view(
// point(0, 5, -10),
// point(0, 0, 0),
// vector(0, 1, 0)))
// Torus(.solidColor(Color(1, 0.5, 0)))
// .translate(0, 1, 0)
// Plane(.pattern(Checkered2D(.black, .white, .identity)))
// }
//}
//
//func testDie() -> World {
// let material = Material.solidColor(Color(1, 0.5, 0))
// .reflective(0.2)
//
// return World {
// Light(point(-10, 10, -10))
// Camera(800, 600, PI/3, .view(
// point(0, 5, -10),
// point(0, 0, 0),
// vector(0, 1, 0)))
// Cube(material).intersection {
// Sphere(material)
// .scale(1.55, 1.55, 1.55)
// Cylinder(material, -2, 2, true)
// .scale(1.35, 1.35, 1.35)
// Cylinder(material, -2, 2, true)
// .scale(1.35, 1.35, 1.35)
// .rotateX(PI/2)
// Cylinder(material, -2, 2, true)
// .scale(1.35, 1.35, 1.35)
// .rotateZ(PI/2)
// }.difference {
// for (x, y, z) in [
// // face with six dimples
// (-0.6, 1.0, 0.6),
// (-0.6, 1.0, 0.0),
// (-0.6, 1.0, -0.6),
// (0.6, 1.0, 0.6),
// (0.6, 1.0, 0.0),
// (0.6, 1.0, -0.6),
// // face with five dimples
// (0.0, 0.0, -1.0),
// (0.6, 0.6, -1.0),
// (0.6, -0.6, -1.0),
// (-0.6, 0.6, -1.0),
// (-0.6, -0.6, -1.0),
// // face with four dimples
// (1.0, 0.6, 0.6),
// (1.0, 0.6, -0.6),
// (1.0, -0.6, 0.6),
// (1.0, -0.6, -0.6),
// // face with three dimples
// (-1.0, 0.6, 0.6),
// (-1.0, 0, 0),
// (-1.0, -0.6, -0.6),
// // face with two dimples
// (0.6, 0.6, 1.0),
// (-0.6, -0.6, 1.0),
// // face with one dimple
// (0.0, -1.0, 0.0),
// ] {
// Sphere(.solidColor(Color(1, 1, 1)))
// .scale(0.2, 0.2, 0.2)
// .translate(x, y, z)
// }
// }
// .rotateY(PI/3)
// .translate(0.0, 1.0, 0.0)
// Plane(.pattern(Checkered2D(.black, .white, .identity)))
// }
//}
//
//func chapterSevenScene() -> World {
// return World {
// Light(point(-10, 10, -10))
// Camera(800, 600, PI/3, .view(
// point(0, 2, -5),
// point(0, 0, 0),
// vector(0, 1, 0)))
// Sphere(.solidColor(Color(1, 0.9, 0.9)))
// .scale(10, 0.01, 10)
// Sphere(.solidColor(Color(1, 0.9, 0.9)))
// .scale(10, 0.01, 10)
// .rotateX(PI/2)
// .rotateY(-PI/4)
// .translate(0, 0, 5)
// Sphere(.solidColor(Color(1, 0.9, 0.9)))
// .scale(10, 0.01, 10)
// .rotateX(PI/2)
// .rotateY(PI/4)
// .translate(0, 0, 5)
// Sphere(.solidColor(Color(1, 0.8, 0.1))
// .diffuse(0.7)
// .specular(0.3))
// .scale(0.33, 0.33, 0.33)
// .translate(-1.5, 0.33, -0.75)
// Sphere(.solidColor(Color(0.1, 1.0, 0.5))
// .diffuse(0.7)
// .specular(0.3))
// .translate(-0.5, 1.0, 0.5)
// Sphere(.solidColor(Color(0.5, 1, 0.1))
// .diffuse(0.7)
// .specular(0.3))
// .scale(0.5, 0.5, 0.5)
// .translate(1.5, 0.5, -0.5)
// }
//}
//
//func chapterNineScene() -> World {
// let floorMaterial = Material(.solidColor(Color(1, 0.9, 0.9)), 0.1, 0.9, 0.0, 200, 0.0, 0.0, 0.0)
// let floor = Plane(.identity, floorMaterial)
Expand Down
11 changes: 6 additions & 5 deletions Sources/ScintillaLib/Intersection.swift
Expand Up @@ -81,12 +81,13 @@ public struct Intersection {
}
}

func hit(_ intersections: inout [Intersection]) -> Optional<Intersection> {
intersections
.sort(by: { i1, i2 in
func hit(_ intersections: [Intersection], includeOnlyShadowingObjects: Bool = false) -> Optional<Intersection> {
return intersections
.sorted(by: { i1, i2 in
i1.t < i2.t
})
return intersections
.filter({intersection in intersection.t > 0})
.filter { intersection in
intersection.t > 0 && (includeOnlyShadowingObjects ? intersection.shape.castsShadow : true)
}
.first
}
37 changes: 37 additions & 0 deletions Sources/ScintillaLib/Jitter.swift
@@ -0,0 +1,37 @@
//
// Jitter.swift
//
//
// Created by Danielle Kefford on 10/11/22.
//

public protocol Jitter {
mutating func next() -> Double
}

public struct NoJitter: Jitter {
public mutating func next() -> Double {
return 0.5
}
}

public struct PseudorandomJitter: Jitter {
var index: Int = 0
var values: [Double]

public init(_ values: [Double]) {
self.values = values
}

public mutating func next() -> Double {
let nextValue = self.values[index]
index = (index+1) % self.values.count
return nextValue
}
}

public struct RandomJitter: Jitter {
public func next() -> Double {
return Double.random(in: 0.0...1.0)
}
}

0 comments on commit 5ef07da

Please sign in to comment.