Add antialiasing.
[the-worst-raytracer] / tf.py
diff --git a/tf.py b/tf.py
index 5a10bbb..4a7508d 100755 (executable)
--- a/tf.py
+++ b/tf.py
@@ -9,12 +9,15 @@ t0 = time.time()
 import numpy as np
 import tensorflow as tf
 import Image
 import numpy as np
 import tensorflow as tf
 import Image
-td = time.time() - t0
-print 'loading took %.3f sec' % td
+t1 = time.time()
+print 'loading took %.3f sec' % (t1 - t0)
 
 # width and height
 W, H = 800, 600
 
 
 # width and height
 W, H = 800, 600
 
+# Antialias using AA^2 samples per pixel.
+AA = 4
+
 def save(tf_array, fn):
   img = np.asarray(tf_array)
   a = np.nanmin(img)
 def save(tf_array, fn):
   img = np.asarray(tf_array)
   a = np.nanmin(img)
@@ -144,17 +147,24 @@ def main():
       return tf.select(tf.greater(plane_depth, 0), plane_col, sky)
 
     camera = tf.constant([0.,0,-5], name='camera')
       return tf.select(tf.greater(plane_depth, 0), plane_col, sky)
 
     camera = tf.constant([0.,0,-5], name='camera')
+    aa_x = tf.placeholder(tf.float32, name='aa_x')
+    aa_y = tf.placeholder(tf.float32, name='aa_y')
+    accumulator = tf.Variable(tf.zeros([H*W,3]), name='accumulator')
 
     with tf.name_scope('screen'):
       # linspace from 0 to N-1, to get X and Y numbers for every row and col.
       x = tf.linspace(0., W-1, W)
       y = tf.linspace(0., H-1, H)
 
 
     with tf.name_scope('screen'):
       # linspace from 0 to N-1, to get X and Y numbers for every row and col.
       x = tf.linspace(0., W-1, W)
       y = tf.linspace(0., H-1, H)
 
-      # add half pixel offset (center of pixel), put (0,0) in the center,
+      # antialiasing pixel offsets
+      ofs_x = (aa_x + .5) / AA
+      ofs_y = (aa_y + .5) / AA
+
+      # add pixel offset (antialiasing), center the image on (0,0)
       # scale so Y goes from -1 to +1
       # invert Y
       # scale so Y goes from -1 to +1
       # invert Y
-      x = (x + .5 - W/2.) / (H/2.)
-      y = (y + .5 - H/2.) / (H/2.) * -1.
+      x = (x + ofs_x - W/2.) / (H/2.)
+      y = (y + ofs_y - H/2.) / (H/2.) * -1.
 
       # turn x into array of <x,0,0> vectors
       x = tf.reshape(x, [W,1]) * tf.reshape([1.,0,0], [1,3])
 
       # turn x into array of <x,0,0> vectors
       x = tf.reshape(x, [W,1]) * tf.reshape([1.,0,0], [1,3])
@@ -198,15 +208,33 @@ def main():
     with tf.name_scope('background'):
       bg = trace_bg(img_of(camera), ray)
 
     with tf.name_scope('background'):
       bg = trace_bg(img_of(camera), ray)
 
-    out = tf.select(tf.less(det, 0.), bg, sph)
+    # Mask sphere and background.
+    img = tf.select(tf.less(det, 0.), bg, sph)
+
+    # Update accumulator.
+    new_accum = accumulator + img / AA / AA
+    update = tf.assign(accumulator, new_accum)
 
     with tf.name_scope('out'):
       gamma = 2.2
 
     with tf.name_scope('out'):
       gamma = 2.2
-      out = tf.pow(out, 1. / gamma)
+      out = tf.pow(accumulator, 1. / gamma)
       out = tf.reshape(out * 255., [H,W,3])
 
     summary_writer = tf.train.SummaryWriter('log', sess.graph)
       out = tf.reshape(out * 255., [H,W,3])
 
     summary_writer = tf.train.SummaryWriter('log', sess.graph)
-    print 'evaluating'
+    sess.run(tf.initialize_all_variables())
+
+    t2 = time.time()
+    print 'initializing took %.3f sec' % (t2 - t1)
+
+    print 'accumulating'
+    for j in range(AA):
+      for i in range(AA):
+        sess.run(update, feed_dict={aa_x:i, aa_y:j})
+
+    t3 = time.time()
+    print 'took %.3f sec to render %d images' % (t3 - t2, AA*AA)
+
+    print 'finalizing'
     evald = sess.run(out)
     print 'saving'
     save(evald, 'out.png')
     evald = sess.run(out)
     print 'saving'
     save(evald, 'out.png')
@@ -214,4 +242,4 @@ def main():
 if __name__ == '__main__':
   main()
 
 if __name__ == '__main__':
   main()
 
-# vim:set ts=2 sw=2 et:
+# vim:set ts=2 sw=2 sts=2 et: