git.fiddlerwoaroof.com
Raw Blame History
(in-package :fwoar.lisp-sandbox.1)

(defun raytrace (out &optional (*samples-per-pixel* 10) (image-width 400) (max-depth 50))
  (let* ((world (append (list (sphere #(0 0 -1) .5
                                      #(0.5 0.5 0.0)
                                      (dielectric-material 0.4)
                                      #+(or)
                                      (lambda (rec ray world depth)
                                        (declare (ignore rec world depth))
                                        (with-slots (direction) ray
                                          (fw.lu:vector-destructuring-bind
                                              (x y z) (unit-vector direction)
                                            (vector (abs x)
                                                    (abs y)
                                                    (abs z)))))))
                        (loop repeat 30
                              collect (sphere (vector (rand-min-max -3 3)
                                                      (rand-min-max -0.5 2)
                                                      (rand-min-max -1.5d0 -0.5d0))
                                              (rand-min-max 0.2 0.5)
                                              (vector (random 1.0d0)
                                                      (random 1.0d0)
                                                      (random 1.0d0))
                                              (case (random 5)
                                                (0 (lambertian-material
                                                    (rand-min-max 0.25 0.75)))
                                                (1 (metal-material
                                                    (rand-min-max 0.25 0.75)))
                                                (2 (fuzzy-metal-material
                                                    (rand-min-max 0.25 0.75)
                                                    (rand-min-max 0.01 0.75)))
                                                (3 (dielectric-material
                                                    (rand-min-max 0.1 2.4)))
                                                (4 #'original-material)
                                                (5
                                                 (lambda (rec ray world depth)
                                                   (declare (ignore rec world depth))
                                                   (vector 1d0 1d0 1d0)
                                                   #+(or)
                                                   (with-slots (direction) ray
                                                     (fw.lu:vector-destructuring-bind
                                                         (x y z) (unit-vector direction)
                                                       (vector (abs x)
                                                               (abs y)
                                                               (abs z)))))))))
                        ;; #+(or)
                        (list (sphere #(0 -100.5 -1) 100
                                      #(0.5 0.5 0.5)
                                      (lambertian-material 0.2)))))
         (aspect-ratio 4/3)
         (image-height (* (floor (/ image-width aspect-ratio))))

         (camera (camera :focal-length 1.0d0)))
    (let ((mailbox (sb-concurrency:make-mailbox)))
      (loop for j in (shuffle (loop for x from 0 to image-height collect x))
            do
               (sb-concurrency:send-message
                (aref *thread-queues*
                      (mod j
                           (length *thread-queues*)))
                (list *samples-per-pixel*
                      j image-width
                      image-height camera
                      world max-depth
                      (lambda (a b)
                        (sb-concurrency:send-message
                         mailbox
                         (list a b))))))
      (write-colors nil
                    (lambda (c)
                      (loop with messages = 0
                            for it = (sb-concurrency:receive-message mailbox :timeout 2)
                            while it
                            do (destructuring-bind (color pos) it
                                 (funcall c color pos))))
                    image-width))))

(defun refraction-scene
    (out &optional (*samples-per-pixel* 10) (image-width 400) (max-depth 50))
  (let* ((world (list (sphere #(0 0 -1) .5
                              #(0.5 0.5 0.0)
                              (lambertian-material #(0.7 0.3 0.3)))
                      (sphere #(-1 0 -1) 0.5
                              #(0 0 0)
                              (dielectric-material 1.5))
                      (sphere #(-1 0 -1) -0.4
                              #(0 0 0)
                              (dielectric-material 1.5))
                      (sphere #(-1 0 -1) -0.2
                              #(0 0 0)
                              (lambertian-material
                               #(0.8 0.6 0.2)))
                      #+(or)
                      (sphere #(1 0 -1) 0.5
                              #(0 0 0)
                              (dielectric-material 2.4))
                      #+(or)
                      (sphere #(-2 0 -1) 0.5
                              #(0 0 0)
                              (metal-material #(0.8 0.8 0.8)))
                      (sphere #(1 0 -1) 0.5
                              #(0 0 0)
                              (metal-material #(0.8 0.6 0.2)))
                      (sphere #(0 -100.5 -1) 100
                              #(0.5 0.5 0.5)
                              (lambertian-material #(0.8 0.8 0.0)))))
         (aspect-ratio 16/9)
         (image-height (* (floor (/ image-width aspect-ratio))))

         (camera (camera)))
    (let ((mailbox (sb-concurrency:make-mailbox)))
      (loop for j in (shuffle (loop for x from 0 to image-height collect x))
            do
               (sb-concurrency:send-message
                (aref *thread-queues*
                      (mod j
                           (length *thread-queues*)))
                (list *samples-per-pixel*
                      j image-width
                      image-height camera
                      world max-depth
                      (lambda (a b)
                        (sb-concurrency:send-message
                         mailbox
                         (list a b))))))
      (write-colors nil
                    (lambda (c)
                      (loop with messages = 0
                            for it = (sb-concurrency:receive-message mailbox :timeout 2)
                            while it
                            do (destructuring-bind (color pos) it
                                 (funcall c color pos))))
                    image-width))))

(defun refraction-scene1
    (out &optional (*samples-per-pixel* 10) (image-width 400) (max-depth 50))
  (let* ((world (list (sphere #(0 0 -1) 1
                              #(0.5 0.5 0.0)
                              (dielectric-material 2.4))
                      (sphere #(-0.5 0 -1) 0.5
                              #(0 0 0)
                              (dielectric-material 1.5 0.2))
                      (sphere #(-0.5 0 -1) -0.4
                              #(0 0 0)
                              (dielectric-material 1.5 0.2))
                      (sphere #(-0.5 0 -1) -0.2
                              #(0 0 0)
                              (metal-material
                               #(0.8 0.6 0.2)))
                      #+(or)
                      (sphere #(1 0 -1) 0.5
                              #(0 0 0)
                              (dielectric-material 2.4))
                      #+(or)
                      (sphere #(-2 0 -1) 0.5
                              #(0 0 0)
                              (metal-material #(0.8 0.8 0.8)))
                      (sphere #(0.5 0 -1) 0.5
                              #(0 0 0)
                              (metal-material #(0.8 0.6 0.2)))
                      (sphere #(0 -100.5 -1) 100
                              #(0.5 0.5 0.5)
                              (lambertian-material #(0.8 0.8 0.0)))))
         (aspect-ratio 16/9)
         (image-height (* (floor (/ image-width aspect-ratio))))

         (camera (camera)))
    (let ((mailbox (sb-concurrency:make-mailbox)))
      (loop for j in (shuffle (loop for x from 0 to image-height collect x))
            do
               (sb-concurrency:send-message
                (aref *thread-queues*
                      (mod j
                           (length *thread-queues*)))
                (list *samples-per-pixel*
                      j image-width
                      image-height camera
                      world max-depth
                      (lambda (a b)
                        (sb-concurrency:send-message
                         mailbox
                         (list a b))))))
      (write-colors nil
                    (lambda (c)
                      (loop with messages = 0
                            for it = (sb-concurrency:receive-message mailbox :timeout 2)
                            while it
                            do (destructuring-bind (color pos) it
                                 (funcall c color pos))))
                    image-width))))

(defun refraction-scene2
    (&optional (*samples-per-pixel* 10) (image-width 400) (max-depth 50) (rows nil rows-p))
  (let* ((world (list (sphere #( 0.0 0 -1.0) 0.1 #(0.5 0.5 0.0) (dielectric-material 1.5))
                      (sphere #( 0.0 0 -1.4) 0.2 #(0.5 0.5 0.0) (dielectric-material 1.7))
                      (sphere #( 0.0 0 -2.4) 0.8 #(0.5 0.5 0.0) (dielectric-material 1.9))
                      (sphere #(-0.0 0 -3.6) 1.0 #(0.5 0.5 0.0) (dielectric-material 2.1))
                      (sphere #(-0.0 0 -5.0) 1.2 #(0.5 0.5 0.0) (dielectric-material 2.3))
                      (sphere #(-0.0 0 -6.6) 1.4 #(0.5 0.5 0.0) (dielectric-material 2.5))
                      #+foo (sphere #(-0.0 0 -1) -0.2
                                    #(0 0 0)
                                    (metal-material #(0.859375d0 0.859375d0 0.796875d0)))
                      #+foo (sphere #(0.6 0.0 -1) 0.2
                                    #(0 0 0)
                                    (metal-material #(0.859375d0 0.859375d0 0.796875d0)))
                      #+foo (sphere #(0 1 -1) 0.2
                                    nil
                                    (lambda (rec ray world depth)
                                      (declare (ignore rec ray world depth))
                                      #(1.0d0 1.0d0 1.0d0)))
                      (sphere #(0 -1000.5 -1.5) 1000
                              #(0.5 0.5 0.5)
                              (lambertian-material #(0.8 0.0 0.0))))
                #+(or)
                (list
                 (sphere #(-0.0 0 -1) 0.2
                         #(0 0 0)
                         (metal-material
                          #(0.8 0.6 0.2)))
                 (sphere #(0 -100.5 -1.5) 100
                         #(0.5 0.5 0.5)
                         (lambertian-material #(0.8 0.8 0.0)))))
         (aspect-ratio 16/9)
         (image-height (* (floor (/ image-width aspect-ratio))))

         (camera (camera)))
    (let ((mailbox (sb-concurrency:make-mailbox)))
      (loop for j in (if rows-p
                         rows
                         (shuffle (loop for x from 0 to image-height collect x)))
            do
               (sb-concurrency:send-message
                (aref *thread-queues*
                      (mod j
                           (length *thread-queues*)))
                (list *samples-per-pixel*
                      j image-width
                      image-height camera
                      world max-depth
                      (lambda (a b)
                        (sb-concurrency:send-message
                         mailbox
                         (list a b))))))
      (write-colors nil
                    (lambda (c)
                      (loop with messages = 0
                            for it = (sb-concurrency:receive-message mailbox :timeout 2)
                            while it
                            do (destructuring-bind (color pos) it
                                 (funcall c color pos))))
                    image-width))))

(defvar *planets*
  '(:mercury 3031/7917
    :venus   7520/7917
    :earth   7917/7917
    :mars    4212/7917))

(defun scene-3
    (&optional (*samples-per-pixel* 10) (image-width 400) (max-depth 50) (rows nil rows-p))
  (let* ((world (list (sphere #(-2.25 0 -2)
                              (* 0.5 (getf *planets* :mercury))
                              nil
                              (metal-material #(0.8 0.8 0)))
                      (sphere #(-0.75 0 -2)
                              (* 0.5 (getf *planets* :venus))
                              nil
                              (metal-material #(0.0 0.8 0)))
                      (sphere #(0.75 0 -2)
                              (* 0.5 (getf *planets* :earth))
                              nil
                              (metal-material #(0.0 0.0 0.8)))
                      (sphere #(2.25 -0 -2)
                              (* 0.5 (getf *planets* :mars))
                              nil
                              (metal-material #(0.8 0.0 0.0)))))

         (aspect-ratio 16/9)
         (image-height (* (floor (/ image-width aspect-ratio))))

         (camera (camera)))
    (let ((mailbox (sb-concurrency:make-mailbox)))
      (loop for j in (if rows-p
                         rows
                         (shuffle (loop for x from 0 to image-height collect x)))
            do
               (sb-concurrency:send-message
                (aref *thread-queues*
                      (mod j
                           (length *thread-queues*)))
                (list *samples-per-pixel*
                      j image-width
                      image-height camera
                      world max-depth
                      (lambda (a b)
                        (sb-concurrency:send-message
                         mailbox
                         (list a b))))))
      (write-colors nil
                    (lambda (c)
                      (loop with messages = 0
                            for it = (sb-concurrency:receive-message mailbox :timeout 2)
                            while it
                            do (destructuring-bind (color pos) it
                                 (funcall c color pos))))
                    image-width))))

(defun scene-4
    (&optional (*samples-per-pixel* 10) (image-width 400) (max-depth 50) (rows nil rows-p))
  (let* ((world (append (loop for ti from 0 by (/ pi 7)
                              for x from 0
                              repeat 20
                              collect
                              (sphere
                               (vector (- (* 2 (sin ti)) 1)
                                       (- (* 2 (cos ti)) 1)
                                       (+ -0.5 (* -0.3 x)))
                               0.25
                               nil
                               (case (random 3)
                                 (0 (metal-material (vector (/ (mod (* 20 x)
                                                                    256)
                                                               256d0)
                                                            (/ (mod (* 20 x)
                                                                    256)
                                                               256d0)
                                                            (/ (mod (* 20 x)
                                                                    256)
                                                               256d0))))
                                 (1 (lambertian-material (vector (/ (mod (* 20 x)
                                                                         256)
                                                                    256d0)
                                                                 (/ (mod (* 20 x)
                                                                         256)
                                                                    256d0)
                                                                 (/ (mod (* 20 x)
                                                                         256)
                                                                    256d0))))
                                 (2 (dielectric-material (rand-min-max 1.4 2.5)
                                                         (rand-min-max 0 0.2))))))
                        (loop for ti from 0 by (/ pi 7)
                              for x from 0
                              repeat 20
                              collect
                              (sphere
                               (vector (- (sin (+ ti (/ pi 14))) 0.5)
                                       (- (cos (+ ti (/ pi 14))) 0.5)
                                       (+ -0.5 (* -0.3 x)))
                               0.25
                               nil
                               (case (random 3)
                                 (0 (metal-material (vector (/ (mod (* 20 x)
                                                                    256)
                                                               256d0)
                                                            (/ (mod (* 20 x)
                                                                    256)
                                                               256d0)
                                                            (/ (mod (* 20 x)
                                                                    256)
                                                               256d0))))
                                 (1 (lambertian-material (vector (/ (mod (* 20 x)
                                                                         256)
                                                                    256d0)
                                                                 (/ (mod (* 20 x)
                                                                         256)
                                                                    256d0)
                                                                 (/ (mod (* 20 x)
                                                                         256)
                                                                    256d0))))
                                 (2 (dielectric-material (rand-min-max 1.4 2.5)
                                                         (rand-min-max 0 0.2)))))))
                #+(or)
                (list
                 (sphere #(-0.0 0 -1) 0.2
                         #(0 0 0)
                         (metal-material
                          #(0.8 0.6 0.2)))
                 (sphere #(0 -100.5 -1.5) 100
                         #(0.5 0.5 0.5)
                         (lambertian-material #(0.8 0.8 0.0)))))
         (aspect-ratio 16/9)
         (image-height (* (floor (/ image-width aspect-ratio))))

         (camera (camera)))
    (let ((mailbox (sb-concurrency:make-mailbox)))
      (loop for j in (if rows-p
                         rows
                         (shuffle (loop for x from 0 to image-height collect x)))
            do
               (sb-concurrency:send-message
                (aref *thread-queues*
                      (mod j
                           (length *thread-queues*)))
                (list *samples-per-pixel*
                      j image-width
                      image-height camera
                      world max-depth
                      (lambda (a b)
                        (sb-concurrency:send-message
                         mailbox
                         (list a b))))))
      (write-colors nil
                    (lambda (c)
                      (loop with messages = 0
                            for it = (sb-concurrency:receive-message mailbox :timeout 2)
                            while it
                            do (destructuring-bind (color pos) it
                                 (funcall c color pos))))
                    image-width))))

(defun sample-image (out)
  (let ((image-width 256)
        (image-height 256))
    (alexandria:with-output-to-file (s out :if-exists :supersede)
      (call-with-ppm-header
       s (make-size :width image-width :height image-height)
       (lambda (s)
         (write-colors
          s (lambda (c)
              (loop for j from (1- image-height) downto 0
                    do (format *trace-output*
                               "~&Scanlines remaining: ~d ~s~%"
                               j
                               (local-time:now))
                    do
                       (loop for i from 0 below image-width
                             collect
                             (let* ((r (/ (* i 1.0d0)
                                          (1- image-width)))
                                    (g (/ (* j 1.0d0)
                                          (1- image-height)))
                                    (b 0.15d0))
                               (funcall c (make-color :r r
                                                      :g g
                                                      :b b))))))
          image-width))
       (1- #.(expt 2 8))))))

#+(or)
((list 'quote
       (loop for ti from 0 by (/ pi 7)
             for x from 0
             repeat 20
             collect (list (vector (- (* 2 (sin ti)) 1)
                                   (- (* 2 (cos ti)) 1)
                                   (+ -0.2 (* -0.3 x)))
                           0.25
                           nil
                           (list (vector (/ (mod (* 20 x)
                                                 256)
                                            256d0)
                                         (/ (mod (* 20 x)
                                                 256)
                                            256d0)
                                         (/ (mod (* 20 x)
                                                 256)
                                            256d0))))))

 '((#(-1.0 1.0 -0.2) 0.25 NIL)
   (#(-0.13223252176488376d0 0.8019377358048383d0 -0.5) 0.25 NIL)
   (#(0.5636629649360596d0 0.2469796037174672d0 -0.8) 0.25 NIL)
   (#(0.9498558243636472d0 -0.5549581320873711d0 -1.1) 0.25 NIL)
   (#(0.9498558243636472d0 -1.4450418679126287d0 -1.4000001) 0.25 NIL)
   (#(0.5636629649360598d0 -2.2469796037174667d0 -1.7) 0.25 NIL)
   (#(-0.13223252176488354d0 -2.801937735804838d0 -2.0) 0.25 NIL)
   (#(-0.9999999999999998d0 -3.0d0 -2.3000002) 0.25 NIL)
   (#(-1.8677674782351161d0 -2.801937735804838d0 -2.6000001) 0.25 NIL)
   (#(-2.5636629649360594d0 -2.246979603717467d0 -2.9) 0.25 NIL)
   (#(-2.949855824363647d0 -1.4450418679126291d0 -3.2) 0.25 NIL)
   (#(-2.949855824363647d0 -0.5549581320873715d0 -3.5000002) 0.25 NIL)
   (#(-2.56366296493606d0 0.24697960371746674d0 -3.8000002) 0.25 NIL)
   (#(-1.8677674782351166d0 0.8019377358048381d0 -4.1) 0.25 NIL)
   (#(-1.0000000000000004d0 1.0d0 -4.4) 0.25 NIL)
   (#(-0.1322325217648842d0 0.8019377358048385d0 -4.7) 0.25 NIL)
   (#(0.5636629649360592d0 0.2469796037174674d0 -5.0) 0.25 NIL)
   (#(0.949855824363647d0 -0.5549581320873707d0 -5.3) 0.25 NIL)
   (#(0.9498558243636475d0 -1.4450418679126282d0 -5.6) 0.25 NIL)
   (#(0.56366296493606d0 -2.2469796037174667d0 -5.9) 0.25 NIL))

 (/ 1960 60.0)
 )