about summary refs log tree commit diff stats
path: root/apps/raytracing
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-10-04 21:07:27 -0700
committerKartik Agaram <vc@akkartik.com>2020-10-04 21:15:28 -0700
commit5c105a7acaae4a295716a6da68ae73b4378ad1cd (patch)
treefe3aee778d67d802cbaea1843641e03049490799 /apps/raytracing
parentf5e1656d15325b37c91ee110215e9a032e6cc1ce (diff)
downloadmu-5c105a7acaae4a295716a6da68ae73b4378ad1cd.tar.gz
6949 - snapshot of next raytracing milestone
Not yet right, but worth a snapshot just because it gives a cool result.
Here, try it out:
  $ ./translate_mu_debug apps/raytracing/3.mu
  $ ./a.elf > x.ppm
Now view x.ppm as an image.

In general, this was quite tedious to write. And a still-open question
is how to emit the progress bar to stderr. My options are to either duplicate
all my print-* functions (already proliferating) or add global variables
to Mu.
Diffstat (limited to 'apps/raytracing')
-rw-r--r--apps/raytracing/3.mu382
-rw-r--r--apps/raytracing/ray.mu11
-rw-r--r--apps/raytracing/vec.mu28
3 files changed, 351 insertions, 70 deletions
diff --git a/apps/raytracing/3.mu b/apps/raytracing/3.mu
index 6be820f6..24d31040 100644
--- a/apps/raytracing/3.mu
+++ b/apps/raytracing/3.mu
@@ -1,4 +1,4 @@
-# Listing 7 of https://raytracing.github.io/books/RayTracingInOneWeekend.html
+# Listing 9 of https://raytracing.github.io/books/RayTracingInOneWeekend.html
 #
 # To run (on Linux):
 #   $ git clone https://github.com/akkartik/mu
@@ -6,62 +6,157 @@
 #   $ ./translate_mu apps/raytracing/3.mu
 #   $ ./a.elf > 3.ppm
 
+fn ray-color _in: (addr ray), _out: (addr rgb) {
+  var in/esi: (addr ray) <- copy _in
+  var out/edi: (addr rgb) <- copy _out
+  var dir/eax: (addr vec3) <- get in, dir
+  var y-addr/eax: (addr float) <- get dir, y
+  # t = (dir.y + 1.0) / 2.0
+  var t/xmm0: float <- copy *y-addr
+  var one/eax: int <- copy 1
+  var one-f/xmm1: float <- convert one
+  t <- add one-f
+  var two/eax: int <- copy 2
+  var two-f/xmm2: float <- convert two
+  t <- divide two-f
+  # whitening = (1.0 - t) * white
+  var whitening-storage: rgb
+  var whitening/ecx: (addr rgb) <- address whitening-storage
+  rgb-white whitening
+  var one-minus-t/xmm3: float <- copy one-f
+  one-minus-t <- subtract t
+  rgb-scale-up whitening, one-minus-t
+  # out = t * (0.5, 0.7, 1.0)
+  var dest/eax: (addr float) <- get out, r
+  fill-in-rational dest, 5, 0xa
+  dest <- get out, g
+  fill-in-rational dest, 7, 0xa
+  dest <- get out, b
+  copy-to *dest, one-f
+  # blend with whitening
+  rgb-add-to out, whitening
+}
+
 fn main -> exit-status/ebx: int {
-  print-string 0, "P3\n256 256\n255\n"
-  var _four/edx: int <- copy 4
-  var four/xmm1: float <- convert _four
-  var one-fourth/xmm1: float <- reciprocal four
-  var max/edx: int <- copy 0xff
-  var image-size/xmm2: float <- convert max
-  var j/ecx: int <- copy 0xff
+
+  # image
+  #   width = 400
+  #   height = 400 * 9/16 = 225
+  var aspect: float
+  var aspect-addr/eax: (addr float) <- address aspect
+  fill-in-rational aspect-addr, 0x10, 9  # 16/9
+
+  # camera
+
+  # viewport-height = 2.0
+  var tmp/eax: int <- copy 2
+  var two-f/xmm4: float <- convert tmp
+  var viewport-height/xmm7: float <- copy two-f
+  # viewport-width = aspect * viewport-height
+  var viewport-width/xmm6: float <- convert tmp
+  viewport-width <- multiply aspect
+  # focal-length = 1.0
+  tmp <- copy 1
+  var focal-length/xmm5: float <- convert tmp
+
+  # origin = point3(0, 0, 0)
+  var origin-storage: vec3
+  var origin/edi: (addr vec3) <- address origin-storage
+  # horizontal = vec3(viewport-width, 0, 0)
+  var horizontal-storage: vec3
+  var dest/eax: (addr float) <- get horizontal-storage, x
+  copy-to *dest, viewport-width
+  var horizontal/ebx: (addr vec3) <- address horizontal-storage
+  # vertical = vec3(0, viewport-height, 0)
+  var vertical-storage: vec3
+  dest <- get vertical-storage, y
+  copy-to *dest, viewport-height
+  var vertical/edx: (addr vec3) <- address vertical-storage
+  # lower-left-corner = origin - horizontal/2 - vertical/2 - vec3(0, 0, focal-length)
+  # . lower-left-corner = origin
+  var lower-left-corner-storage: vec3
+  var lower-left-corner/esi: (addr vec3) <- address lower-left-corner-storage
+  copy-object origin, lower-left-corner
+  # . lower-left-corner -= horizontal/2
+  var tmp2: vec3
+  var tmp2-addr/eax: (addr vec3) <- address tmp2
+  copy-object horizontal, tmp2-addr
+  vec3-scale-down tmp2-addr, two-f
+  vec3-subtract-from lower-left-corner, tmp2-addr
+  # . lower-left-corner -= vertical/2
+  copy-object vertical, tmp2-addr
+  vec3-scale-down tmp2-addr, two-f
+  vec3-subtract-from lower-left-corner, tmp2-addr
+  # . lower-left-corner -= vec3(0, 0, focal-length)
+  var dest2/ecx: (addr float) <- get lower-left-corner, z
+  var tmp3/xmm0: float <- copy *dest2
+  tmp3 <- subtract focal-length
+  copy-to *dest2, tmp3
+  # phew!
+
+  # render
+
+  # live variables at this point:
+  #   origin (edi)
+  #   lower-left-corner (esi)
+  #   horizontal (ebx)
+  #   vertical (edx)
+  # floating-point registers are all free
+  print-string 0, "P3\n400 225\n255\n"  # 225 = image height
+  var tmp/eax: int <- copy 0x18f # image width - 1
+  var image-width-1/xmm7: float <- convert tmp
+  tmp <- copy 0xe0  # image height - 1
+  var image-height-1/xmm6: float <- convert tmp
+  #
+  var j/ecx: int <- copy 0xe0  # 224
   {
     compare j, 0
     break-if-<
     var i/eax: int <- copy 0
     {
-      compare i, 0xff
-      break-if->
-#?       var c: rgb
-#?       # compute r
-#?       var tmp/xmm0: float <- convert i
-#?       tmp <- divide image-size
-#?       var r-addr/edx: (addr float) <- get c, r
-#?       copy-to *r-addr, tmp
-#? #?       var tmp2/ebx: int <- reinterpret *r-addr
-#? #?       print-int32-hex 0, tmp2
-#? #?       print-string 0, "\n"
-#?       # compute g
-#?       tmp <- convert j
-#?       tmp <- divide image-size
-#?       var g-addr/edx: (addr float) <- get c, g
-#?       copy-to *g-addr, tmp
-#?       # compute b
-#?       var b-addr/edx: (addr float) <- get c, b
-#?       copy-to *b-addr, one-fourth
-#?       # emit
-#?       var c-addr/edx: (addr rgb) <- address c
-#?       print-rgb 0, c-addr
-      var p: vec3
-      # compute r
-      var tmp/xmm0: float <- convert i
-      tmp <- divide image-size
-      var r-addr/edx: (addr float) <- get p, x
-      copy-to *r-addr, tmp
-#?       var tmp2/ebx: int <- reinterpret *r-addr
-#?       print-int32-hex 0, tmp2
-#?       print-string 0, "\n"
-      # compute g
-      tmp <- convert j
-      tmp <- divide image-size
-      var g-addr/edx: (addr float) <- get p, y
-      copy-to *g-addr, tmp
-      # compute b
-      var b-addr/edx: (addr float) <- get p, z
-      copy-to *b-addr, one-fourth
-      # emit
-      var p-addr/edx: (addr vec3) <- address p
-      print-vec3 0, p-addr
-      print-string 0, "\n"
+      compare i, 0x190  # 400 = image width
+      break-if->=
+      # u = i / (image-width - 1)
+      var u/xmm0: float <- convert i
+      u <- divide image-width-1
+      # v = j / (image-height - 1)
+      var v/xmm1: float <- convert j
+      v <- divide image-height-1
+      # r = ray(origin, lower-left-corner + u*horizontal + v*vertical - origin)
+      var r-storage: ray
+      # . . we're running out of int registers now,
+      # . . but luckily we don't need i and j in the rest of this loop iteration,
+      # . . so we'll just spill them in a block
+      {
+        # . r.orig = origin
+        var r/eax: (addr ray) <- address r-storage
+        var dest/ecx: (addr vec3) <- get r, orig
+        copy-object origin, dest
+        # . r.dir = lower-left-corner
+        dest <- get r, dir
+        copy-object lower-left-corner, dest
+        # . r.dir += horizontal*u
+        var tmp-vec3: vec3
+        var tmp/eax: (addr vec3) <- address tmp-vec3
+        copy-object horizontal, tmp
+        vec3-scale-up tmp, u
+        vec3-add-to dest, tmp
+        # . r.dir += vertical*v
+        copy-object vertical, tmp
+        vec3-scale-up tmp, v
+        vec3-add-to dest, tmp
+        # . r.dir -= origin
+        vec3-subtract-from dest, origin
+      }
+      # pixel-color = ray-color(r)
+      var c-storage: rgb
+      var c/ecx: (addr rgb) <- address c-storage
+      {
+        var r/eax: (addr ray) <- address r-storage
+        ray-color r, c
+        # write color
+        print-rgb 0, c
+      }
       i <- increment
       loop
     }
@@ -71,6 +166,31 @@ fn main -> exit-status/ebx: int {
   exit-status <- copy 1
 }
 
+type ray {
+  orig: vec3  # point
+  dir: vec3
+}
+
+# A little different from the constructor at https://raytracing.github.io/books/RayTracingInOneWeekend.html
+# We immediately normalize the direction vector so we don't have to keep doing
+# so.
+fn initialize-ray _self: (addr ray), o: (addr vec3), d: (addr vec3) {
+  var self/esi: (addr ray) <- copy _self
+  var dest/eax: (addr vec3) <- get self, orig
+  copy-object o, dest
+  dest <- get self, dir
+  vec3-unit d, dest
+}
+
+fn ray-at _self: (addr ray), t: float, out: (addr vec3) {
+  var self/esi: (addr ray) <- copy _self
+  var src/eax: (addr vec3) <- get self, dir
+  copy-object src, out
+  vec3-scale-up out, t
+  src <- get self, orig
+  vec3-add-to out, src
+}
+
 type rgb {
   # components normalized to within [0.0, 1.0]
   r: float
@@ -106,22 +226,172 @@ fn print-rgb screen: (addr screen), _c: (addr rgb) {
   print-string screen, "\n"
 }
 
+fn rgb-white _c: (addr rgb) {
+  var c/esi: (addr rgb) <- copy _c
+  var one/eax: int <- copy 1
+  var one-f/xmm0: float <- convert one
+  var dest/edi: (addr float) <- get c, r
+  copy-to *dest, one-f
+  dest <- get c, g
+  copy-to *dest, one-f
+  dest <- get c, b
+  copy-to *dest, one-f
+}
+
+fn rgb-add-to _c1: (addr rgb), _c2: (addr rgb) {
+  var c1/edi: (addr rgb) <- copy _c1
+  var c2/esi: (addr rgb) <- copy _c2
+  # c1.r += c2.r
+  var arg1/eax: (addr float) <- get c1, r
+  var arg2/ecx: (addr float) <- get c2, r
+  var result/xmm0: float <- copy *arg1
+  result <- add *arg2
+  copy-to *arg1, result
+  # c1.g += c2.g
+  arg1 <- get c1, g
+  arg2 <- get c2, g
+  result <- copy *arg1
+  result <- add *arg2
+  copy-to *arg1, result
+  # c1.b += c2.b
+  arg1 <- get c1, b
+  arg2 <- get c2, b
+  result <- copy *arg1
+  result <- add *arg2
+  copy-to *arg1, result
+}
+
+fn rgb-scale-up _c1: (addr rgb), f: float {
+  var c1/edi: (addr rgb) <- copy _c1
+  # c1.r *= f
+  var dest/eax: (addr float) <- get c1, r
+  var result/xmm0: float <- copy *dest
+  result <- multiply f
+  copy-to *dest, result
+  # c1.g *= f
+  dest <- get c1, g
+  result <- copy *dest
+  result <- multiply f
+  copy-to *dest, result
+  # c1.b *= f
+  dest <- get c1, b
+  result <- copy *dest
+  result <- multiply f
+  copy-to *dest, result
+}
+
 type vec3 {
   x: float
   y: float
   z: float
 }
 
-fn print-vec3 screen: (addr screen), _a: (addr vec3) {
-  var a/esi: (addr vec3) <- copy _a
+fn print-vec3 screen: (addr screen), _v: (addr vec3) {
+  var v/esi: (addr vec3) <- copy _v
   print-string screen, "("
-  var tmp/eax: (addr float) <- get a, x
+  var tmp/eax: (addr float) <- get v, x
   print-float screen, *tmp
   print-string screen, ", "
-  tmp <- get a, y
+  tmp <- get v, y
   print-float screen, *tmp
   print-string screen, ", "
-  tmp <- get a, z
+  tmp <- get v, z
   print-float screen, *tmp
   print-string screen, ")"
 }
+
+fn vec3-add-to _v1: (addr vec3), _v2: (addr vec3) {
+  var v1/edi: (addr vec3) <- copy _v1
+  var v2/esi: (addr vec3) <- copy _v2
+  # v1.x += v2.x
+  var arg1/eax: (addr float) <- get v1, x
+  var arg2/ecx: (addr float) <- get v2, x
+  var result/xmm0: float <- copy *arg1
+  result <- add *arg2
+  copy-to *arg1, result
+  # v1.y += v2.y
+  arg1 <- get v1, y
+  arg2 <- get v2, y
+  result <- copy *arg1
+  result <- add *arg2
+  copy-to *arg1, result
+  # v1.z += v2.z
+  arg1 <- get v1, z
+  arg2 <- get v2, z
+  result <- copy *arg1
+  result <- add *arg2
+  copy-to *arg1, result
+}
+
+fn vec3-subtract-from v1: (addr vec3), v2: (addr vec3) {
+  var tmp-storage: vec3
+  var tmp/eax: (addr vec3) <- address tmp-storage
+  copy-object v2, tmp
+  vec3-negate tmp
+  vec3-add-to v1, tmp
+}
+
+fn vec3-negate v: (addr vec3) {
+  var negative-one/eax: int <- copy -1
+  var negative-one-f/xmm0: float <- convert negative-one
+  vec3-scale-up v, negative-one-f
+}
+
+fn vec3-scale-up _v1: (addr vec3), f: float {
+  var v1/edi: (addr vec3) <- copy _v1
+  # v1.x *= f
+  var dest/eax: (addr float) <- get v1, x
+  var result/xmm0: float <- copy *dest
+  result <- multiply f
+  copy-to *dest, result
+  # v1.y *= f
+  dest <- get v1, y
+  result <- copy *dest
+  result <- multiply f
+  copy-to *dest, result
+  # v1.z *= f
+  dest <- get v1, z
+  result <- copy *dest
+  result <- multiply f
+  copy-to *dest, result
+}
+
+fn vec3-scale-down _v1: (addr vec3), f: float {
+  var v1/edi: (addr vec3) <- copy _v1
+  # v1.x /= f
+  var dest/eax: (addr float) <- get v1, x
+  var result/xmm0: float <- copy *dest
+  result <- divide f
+  copy-to *dest, result
+  # v1.y /= f
+  dest <- get v1, y
+  result <- copy *dest
+  result <- divide f
+  copy-to *dest, result
+  # v1.z /= f
+  dest <- get v1, z
+  result <- copy *dest
+  result <- divide f
+  copy-to *dest, result
+}
+
+fn vec3-unit in: (addr vec3), out: (addr vec3) {
+  var len/xmm0: float <- vec3-length in
+  copy-object in, out
+  vec3-scale-down out, len
+}
+
+fn vec3-length v: (addr vec3) -> result/xmm0: float {
+  result <- vec3-length-squared v
+  result <- square-root result
+}
+
+fn vec3-length-squared _v: (addr vec3) -> result/xmm0: float {
+  var v/esi: (addr vec3) <- copy _v
+  # result = v.x * v.x
+  var src/eax: (addr float) <- get v, x
+  var tmp/xmm1: float <- copy *src
+  tmp <- multiply tmp
+  result <- copy tmp
+  # 
+}
diff --git a/apps/raytracing/ray.mu b/apps/raytracing/ray.mu
index ca2cb475..33d1a9fe 100644
--- a/apps/raytracing/ray.mu
+++ b/apps/raytracing/ray.mu
@@ -3,6 +3,17 @@ type ray {
   dir: vec3
 }
 
+# A little different from the constructor at https://raytracing.github.io/books/RayTracingInOneWeekend.html
+# We immediately normalize the direction vector so we don't have to keep doing
+# so.
+fn initialize-ray _self: (addr ray), o: (addr vec3), d: (addr vec3) {
+  var self/esi: (addr ray) <- copy _self
+  var dest/eax: (addr vec3) <- get self, orig
+  copy-object o, dest
+  dest <- get self, dir
+  vec3-unit d, dest
+}
+
 fn ray-at _self: (addr ray), t: float, out: (addr vec3) {
   var self/esi: (addr ray) <- copy _self
   var src/eax: (addr vec3) <- get self, dir
diff --git a/apps/raytracing/vec.mu b/apps/raytracing/vec.mu
index 5539a0dd..b5fa1c74 100644
--- a/apps/raytracing/vec.mu
+++ b/apps/raytracing/vec.mu
@@ -4,46 +4,46 @@ type vec3 {
   z: float
 }
 
-fn vec3-negate _a: (addr vec3), out: (addr vec3) {
+fn vec3-negate _v: (addr vec3) {
 }
 
-fn vec3-add-to _a: (addr vec3), _b: (addr vec3) {
+fn vec3-add-to _v1: (addr vec3), _v2: (addr vec3) {
 }
 
-fn vec3-mul-by _a: (addr vec3), _b: (addr vec3) {
+fn vec3-mul-by _v1: (addr vec3), _v2: (addr vec3) {
 }
 
-fn vec3-scale-up _a: (addr vec3), n: float {
+fn vec3-scale-up _v: (addr vec3), f: float {
 }
 
-fn vec3-scale-down _a: (addr vec3), n: float {
+fn vec3-scale-down _v: (addr vec3), f: float {
 }
 
-fn vec3-length _a: (addr vec3) -> result/eax: float {
+fn vec3-length v: (addr vec3) -> result/xmm0: float {
 }
 
-fn vec3-length-squared _a: (addr vec3) -> result/eax: float {
+fn vec3-length-squared _v: (addr vec3) -> result/xmm0: float {
 }
 
-fn vec3-dot _a: (addr vec3), _b: (addr vec3) -> result/eax: float {
+fn vec3-dot _v1: (addr vec3), _v2: (addr vec3) -> result/xmm0: float {
 }
 
-fn vec3-cross _a: (addr vec3), _b: (addr vec3), out: (addr vec3) {
+fn vec3-cross _v1: (addr vec3), _v2: (addr vec3), out: (addr vec3) {
 }
 
 fn vec3-unit in: (addr vec3), out: (addr vec3) {
 }
 
-fn print-vec3 screen: (addr screen), _a: (addr vec3) {
-  var a/esi: (addr vec3) <- copy _a
+fn print-vec3 screen: (addr screen), _v: (addr vec3) {
+  var v/esi: (addr vec3) <- copy _v
   print-string screen, "("
-  var tmp/eax: (addr float) <- get a, x
+  var tmp/eax: (addr float) <- get v, x
   print-float screen, *tmp
   print-string screen, ", "
-  tmp <- get a, y
+  tmp <- get v, y
   print-float screen, *tmp
   print-string screen, ", "
-  tmp <- get a, z
+  tmp <- get v, z
   print-float screen, *tmp
   print-string screen, ")"
 }