I got my hobby ray tracer producing images. It is not true diffuse ambient occlusion because the rays are uniform on the hemisphere rather than a cosine distribution. I include it as one big file because xcode has been under rapid evolution lately. Here's a 100 sample image. All at pixel center so not antialiased.
And here's all the code cut-and-pastable into xcode. You can run it as an executable from the terminal (xcode shows the path as shown)
//
// main.swift
//
// Created by Peter Shirley on 7/20/14.
// This work is in the public domain
//
import Foundation
protocol hitable {
func hit(r : ray, tmin : Double) -> (Bool, Double, vec3)
}
class sphere : hitable {
var center : vec3 = vec3(x: 0.0, y: 0.0, z: 0.0)
var radius : Double = 0.0
func hit(r : ray, tmin : Double) -> (Bool, Double, vec3) {
var A : Double = dot(r.direction, r.direction)
var B : Double = 2.0*dot(r.direction,r.origin - center)
var C : Double = dot(r.origin - center,r.origin - center) - radius*radius
let discriminant = B*B - 4.0*A*C
if discriminant > 0 {
var t : Double = (-B - sqrt(discriminant) ) / (2.0*A)
if t < tmin {
t = (-B + sqrt(discriminant)) / (2.0*A)
}
return (t > tmin, t, r.location_at_parameter(t) - center)
} else {
return (false, 0.0, vec3(x:1.0, y:0.0, z:0.0))
}
}
}
class hitable_list : hitable {
var members : [hitable] = []
func add(h : hitable) {
members.append(h)
}
func hit(r : ray, tmin : Double) -> (Bool, Double, vec3) {
var t_clostest_so_far = 1.0e6 // not defined: Double.max
var hit_anything : Bool = false
var new_t : Double
var hit_it : Bool
var normal : vec3 = vec3(x:1.0, y:0.0, z:0.0)
var new_normal : vec3
for item in members {
(hit_it , new_t, new_normal) = item.hit(r, tmin: tmin)
if (hit_it && new_t < t_clostest_so_far) {
hit_anything = true
t_clostest_so_far = new_t
normal = new_normal
}
}
return (hit_anything, t_clostest_so_far, normal)
}
}
// implicit type inference. Swift when in doubt assumes Double
struct vec3 : Printable {
var x = 0.0, y = 0.0, z = 0.0
var description : String {
return "hello"
}
}
func * (left: Double, right: vec3) -> vec3 {
return vec3(x: left * right.x, y: left * right.y, z: left * right.z)
}
func / (left: Double, right: vec3) -> vec3 {
return vec3(x: left / right.x, y: left / right.y, z: left / right.z)
}
func * (left: vec3, right: Double) -> vec3 {
return vec3(x: left.x * right, y: left.y * right, z: left.z * right)
}
func / (left: vec3, right: Double) -> vec3 {
return vec3(x: left.x / right, y: left.y / right, z: left.z / right)
}
func + (left: vec3, right: vec3) -> vec3 {
return vec3(x: left.x + right.x, y: left.y + right.y, z: left.z + right.z)
}
func - (left: vec3, right: vec3) -> vec3 {
return vec3(x: left.x - right.x, y: left.y - right.y, z: left.z - right.z)
}
func * (left: vec3, right: vec3) -> vec3 {
return vec3(x: left.x * right.x, y: left.y * right.y, z: left.z * right.z)
}
func / (left: vec3, right: vec3) -> vec3 {
return vec3(x: left.x / right.x, y: left.y / right.y, z: left.z / right.z)
}
func max(v: vec3) -> Double {
if v.x > v.y && v.x > v.z {
return v.x
}
else if v.y > v.x && v.y > v.z {
return v.y
}
else {
return v.z
}
}
func min(v: vec3) -> Double {
if v.x < v.y && v.x < v.z {
return v.x
}
else if v.y < v.x && v.y < v.z {
return v.y
}
else {
return v.z
}
}
func dot (left: vec3, right: vec3) -> Double {
return left.x * right.x + left.y * right.y + left.z * right.z
}
func cross (left: vec3, right: vec3) -> vec3 {
return vec3(x: left.y * right.z - left.z * right.y, y: left.z * right.x - left.z * right.x, z: left.x * right.y - left.y * right.x)
}
func unit_vector(v: vec3) -> vec3 {
var length : Double = sqrt(dot(v, v))
return vec3(x: v.x/length, y: v.y/length, z: v.z/length)
}
protocol Printable {
var description: String { get }
}
struct ray {
var origin : vec3
var direction : vec3
func location_at_parameter(t: Double) -> vec3 {
return origin + t*direction
}
}
var u : vec3 = vec3(x: 1.0, y: 0.0, z: 0.0);
var v : vec3 = vec3(x: 0.0, y: 1.0, z: 0.0);
var w : vec3 = cross(u, v)
var n : vec3 = u
var spheres : hitable_list = hitable_list()
var my_sphere1 : sphere = sphere()
my_sphere1.center = vec3(x: 0.0, y: 0.0, z: 0.0)
my_sphere1.radius = 1.0
spheres.add(my_sphere1)
var my_sphere2 : sphere = sphere()
my_sphere2.center = vec3(x: 2.0, y: 0.0, z: 2.0)
my_sphere2.radius = 1.0
spheres.add(my_sphere2)
var my_sphere3 : sphere = sphere()
my_sphere3.center = vec3(x: -2.0, y: 0.0, z: 2.0)
my_sphere3.radius = 1.0
spheres.add(my_sphere3)
var my_sphere4 : sphere = sphere()
my_sphere4.center = vec3(x: 0.0, y: -1001.0, z: 0.0)
my_sphere4.radius = 1000.0
spheres.add(my_sphere4)
let the_world : hitable = spheres
let ray_origin = vec3(x: 0.0, y: 2.5, z: -10.0)
let nx = 256
let ny = 256
let ns = 100
println("P3");
println ("\(nx) \(ny)");
println ("255");
for j in 0...255 {
for i in 0...255 {
var accum :vec3 = vec3(x: 0.0, y: 0.0, z: 0.0)
var red = 0, green = 0, blue = 0
for s in 1...ns {
var attenuation : vec3 = vec3(x: 1.0, y: 1.0, z: 1.0)
var not_yet_missed : Bool = true
var ray_target : vec3 = vec3(x: -1.0 + 2.0*Double(i)/Double(nx), y: 2.5 + -1.0 + 2.0*Double(255-j)/Double(ny), z: -8.0)
var the_ray : ray = ray(origin: ray_origin, direction: ray_target-ray_origin)
while not_yet_missed {
let hit_info = the_world.hit(the_ray, tmin: 0.01)
if hit_info.0 {
attenuation = 0.5*attenuation
let new_ray_origin = the_ray.location_at_parameter(hit_info.1)
var scattered_direction : vec3 = hit_info.2
do {
do {
scattered_direction = vec3(x: -1.0 + 2.0*drand48(), y: -1.0 + 2.0*drand48(), z: -1.0 + 2.0*drand48())
} while dot(scattered_direction,scattered_direction) > 1.0
} while dot(scattered_direction, hit_info.2) < 0.001
the_ray = ray(origin: new_ray_origin, direction: scattered_direction)
}
else {
not_yet_missed = false
}
}
accum = accum + attenuation
}
red = Int(255.5*accum.x/Double(ns))
green = Int(255.5*accum.y/Double(ns))
blue = Int(255.5*accum.z/Double(ns))
println("\(red) \(green) \(blue)");
}
}
1 comment:
After a long time I got something fresh and quality content on massage therapy services. I searched a lot for the related material but got almost replica work. Keep it up! It is really very informative. clipping path service
Post a Comment