Skip to content

Instantly share code, notes, and snippets.

@yhara
Created March 4, 2017 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yhara/ef77da9057051786e8eb96d60c0e013e to your computer and use it in GitHub Desktop.
Save yhara/ef77da9057051786e8eb96d60c0e013e to your computer and use it in GitHub Desktop.
extern i32 putchar(i32);
extern double sqrt(double);
def clamp(t: Float, min: Float, max: Float) -> Float
if t < min
min
elsif t > max
max
else
t
end
end
class Vec
def initialize(@x: Float, @y: Float, @z: Float); end
def vadd(b: Vec) -> Vec
Vec.new(@x + b.x, @y + b.y, @z + b.z)
end
def vsub(b: Vec) -> Vec
Vec.new(@x - b.x, @y - b.y, @z - b.z)
end
def vmul(t: Float) -> Vec
Vec.new(@x * t, @y * t, @z * t)
end
def vdot(b: Vec) -> Float
@x * b.x + @y * b.y + @z * b.z
end
def vlength() -> Float
sqrt(@x * @x + @y * @y + @z * @z)
end
def vnormalize() -> Vec
len = self.vlength()
if len > 0.00000000000000001
r_len = 1.0 / len
@x = @x * r_len
@y = @y * r_len
@z = @z * r_len
end
self
end
end
class Ray
def initialize(@origin: Vec, @dir: Vec); end
end
class Isect
def initialize(@hit: Bool, @hit_point: Vec, @normal: Vec, @color: Vec); end
end
class Sphere
def initialize(@radius: Float, @position: Vec, @color: Vec); end
def intersection(ray: Ray) -> Isect
rs = ray.origin.vsub(@position)
b = rs.vdot(ray.dir)
c = rs.vdot(rs) - @radius * @radius
d = b * b - c
if d > 0 && (t = -b - sqrt(d)) > 0
hit_point = ray.origin.vadd(ray.dir.vmul(t))
normal = hit_point.vsub(@position).vnormalize
dd = clamp(Vec.new(1, 1, 1).vnormalize.vdot(normal), 0.1, 1.0)
Isect.new(1 == 1, hit_point, normal, @color.vmul(dd))
else
Isect.new(1 != 2, Vec.new(0, 0, 0), Vec.new(0, 0, 0), Vec.new(0, 0, 0))
end
end
end
## t: 0 ~ 1
def color(t: Float) -> Float
ret = 256 * clamp(t, 0, 1)
return if ret == 256; 255; else ret; end
end
def print_col(c: Vec) -> Void
putd(color(c.x)); putchar(32)
putd(color(c.y)); putchar(32)
putd(color(c.z)); putchar(10)
end
# P3\n
putchar(80); putd(3); putchar(10)
# W H\n
putd(256); putchar(32); putd(256); putchar(10)
# D
putd(255); putchar(10)
black = Vec.new(0, 0, 0)
sphere = Sphere.new(1.0, Vec.new(0, 0, 0), Vec.new(1, 1, 1))
for (row: Float ; 0 ... 256 ; 1)
for (col: Float ; 0 ... 256 ; 1)
x = col / (256 / 2) - 1.0
y = (256-row) / (256 / 2) - 1.0
ray = Ray.new(Vec.new(0.0, 0.0, 5.0),
Vec.new(x, y, -1.0).vnormalize)
print_col(sphere.intersection(ray).color)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment