Advertisement
Guest User

Untitled

a guest
Aug 4th, 2019
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 6.06 KB | None | 0 0
  1. #lang racket/gui
  2.  
  3. (require racket/draw)
  4.  
  5. (struct color (r g b))
  6. (struct vec (x y z))
  7. (struct object (is get-intersect get-normal get-color get-surface-point))
  8.  
  9. (define light (vec -1 -1 -0.75))
  10. (define ambiant-color (color 15 15 30))
  11. (define bg-color (color 70 70 130))
  12. (define (make-scene)
  13.   (list (new-sphere (vec 0 0 500) 100 (color 0 200 200))
  14.     (new-sphere (vec -100 -50 500) 100 (color 250 200 100))
  15.     (new-sphere (vec 200 150 500) 100 (color 0 0 200))
  16.     (new-sphere (vec -200  200 300) 25 (color 100 100 100))
  17.     (new-sphere (vec -200  150 300) 25 (color 100 100 100))
  18.     (new-sphere (vec -200  100 300) 25 (color 100 100 100))
  19.     (new-sphere (vec -200   50 300) 25 (color 100 100 100))
  20.     (new-sphere (vec -200    0 300) 25 (color 100 100 100))
  21.     (new-sphere (vec -200  -50 300) 25 (color 100 100 100))
  22.     (new-sphere (vec -200 -100 300) 25 (color 100 100 100))
  23.     (new-sphere (vec -200 -150 300) 25 (color 100 100 100))
  24.     (new-sphere (vec -200 -200 300) 25 (color 100 100 100))
  25.     (new-plane  (vec 0 200.01 0) (vec 0 1 0)
  26.             (color 200 0 200) (color 130 0 130))
  27.     ))
  28.  
  29. (define (color-op col f)
  30.   (color (f (color-r col)) (f (color-g col)) (f (color-b col))))
  31.  
  32. (define (color-mul col m)
  33.   (color-op col (lambda [x] (* x m))))
  34.  
  35. (define (color-add c1 c2)
  36.   (color (+ (color-r c1) (color-r c2))
  37.      (+ (color-g c1) (color-g c2))
  38.      (+ (color-b c1) (color-b c2))))
  39.      
  40. (define (norm pt)
  41.   (sqrt (+ (expt (vec-x pt) 2)
  42.        (expt (vec-y pt) 2)
  43.        (expt (vec-z pt) 2))))
  44.  
  45. (define (normalized pt)
  46.   (let ([n (norm pt)])
  47.     (vec (/ (vec-x pt) n)
  48.      (/ (vec-y pt) n)
  49.      (/ (vec-z pt) n))))
  50.  
  51. (define (vec-op op)
  52.   (lambda [p1 p2]
  53.     (vec (op (vec-x p1) (vec-x p2))
  54.      (op (vec-y p1) (vec-y p2))
  55.      (op (vec-z p1) (vec-z p2)))))
  56.  
  57. (define vec-add (vec-op +))
  58. (define vec-sub (vec-op -))
  59.  
  60. (define (vec-mul p1 m)
  61.   (vec (* (vec-x p1) m)
  62.        (* (vec-y p1) m)
  63.        (* (vec-z p1) m)))
  64.        
  65. (define (dot-product v1 v2)
  66.   (+ (* (vec-x v1) (vec-x v2))
  67.      (* (vec-y v1) (vec-y v2))
  68.      (* (vec-z v1) (vec-z v2))))
  69.  
  70. (define (solve-quadratic a b c)
  71.   (let ([discr (- (* b b) (* 4 a c))])
  72.     (cond ((< discr 0) '())
  73.       ((= discr 0) (list (* -0.5 (/ b a))))
  74.       (#t (let* ([q (if (> b 0)
  75.                 (* -0.5 (+ b (sqrt discr)))
  76.                 (* -0.5 (- b (sqrt discr))))]
  77.              [x0 (/ q a)]
  78.              [x1 (/ c q)])
  79.         (if (< x0 x1)
  80.             (list x0 x1)
  81.             (list x1 x0)))))))
  82.  
  83. (define (new-sphere pos radius col)
  84.   (define (get-intersect orig dir)
  85.     (let* ([L (vec-sub orig pos)]
  86.        [a (dot-product dir dir)]
  87.        [b (* 2 (dot-product L dir))]
  88.        [c (- (dot-product L L) (* radius radius))]
  89.        [res (filter (lambda [x] (> x 0)) (solve-quadratic a b c))])
  90.       (cond ((null? res) -1)
  91.         ((null? (cdr res)) (car res))
  92.         ((< (car res) (cadr res)) (car res))
  93.         (#t (cadr res)))))
  94.   (define (get-normal pt) (normalized (vec-sub pt pos)))
  95.   (define (get-color pt) col)
  96.   (define (get-surface-point pt)
  97.             (vec-add (vec-mul (get-normal pt)
  98.                   (* 1.0000001 radius)) pos))
  99.  
  100.   (object 'sphere get-intersect get-normal get-color get-surface-point))
  101.  
  102. (define (new-plane pos normal col0 col1)
  103.   (define (get-intersect orig dir)
  104.     (let ([denom (dot-product dir normal)]
  105.       [p (vec-sub pos orig)])
  106.       (if (< denom 1e-6)
  107.       -1
  108.       (exact->inexact (/ (dot-product p normal) denom)))))
  109.   (define (get-normal pt) (normalized (vec-mul normal -1)))
  110.   (define (get-color pt)
  111.     (if (xor (= (modulo (exact-floor (* 0.01 (vec-x pt))) 2) 0)
  112.          (xor (= (modulo (exact-floor (* 0.01 (vec-y pt))) 2) 0)
  113.           (= (modulo (exact-floor (* 0.01 (vec-z pt))) 2) 0)))
  114.     col0
  115.     col1))
  116.   (define (get-surface-point pt)
  117.     (vec-add (vec-mul (normalized normal) 0.0000001) pt))
  118.  
  119.   (object 'plane get-intersect get-normal get-color get-surface-point))
  120.  
  121. (define (cast-ray from to scene)
  122.   (foldl (lambda [res acc]
  123.        (cond ((null? acc) res)
  124.          ((< (car res) (car acc)) res)
  125.          (#t acc)))
  126.      '()
  127.      (filter (lambda [res] (> (car res) 0))
  128.          (map (lambda [obj]
  129.             (cons
  130.              ((object-get-intersect obj) from to) obj)) scene))))
  131.  
  132. (define (blend-colors factor col1 col2)
  133.   (let ([c1 (color-mul col1 factor)]
  134.     [c2 (color-mul col2 (- 1 factor))])
  135.     (color-add c1 c2)))
  136.  
  137. (define (reflect-color limit from obj scene)
  138.   (let ([col ((object-get-color obj) from)])
  139.     (if (and (> limit 0) (eq? (object-is obj) 'sphere))
  140.     (blend-colors 0.75 ((ray-pixel (- limit 1) scene
  141.                        ((object-get-surface-point obj) from))
  142.                 ((object-get-normal obj) from)) col)
  143.     col)))
  144.  
  145. (define (find-color limit from obj scene)
  146.   (let* ([col (reflect-color limit from obj scene)]
  147.      [spoint ((object-get-surface-point obj) from)]
  148.      [not-occluded (null? (cast-ray spoint light scene))]
  149.      [spec (expt (/ (acos (dot-product
  150.                    (vec-mul ((object-get-normal obj) from) -1)
  151.                    (normalized light)))
  152.             (* 2 pi (/ 1 3))) 5)]
  153.      [final (color-mul col spec)])
  154.     (if not-occluded
  155.     final
  156.     (blend-colors 0.25 final ambiant-color))))
  157.  
  158. (define (ray-pixel limit scene orig)
  159.   (lambda [to]
  160.     (let ([res (cast-ray orig to scene)])
  161.       (if (null? res)
  162.       bg-color
  163.       (find-color limit (vec-mul to (car res)) (cdr res) scene)))))
  164.  
  165. (define (coords w h z)
  166.   (for/list ([n (in-range (* w h))])
  167.         (let ([x (- (modulo n w) (quotient w 2))]
  168.           [y (- (quotient n w) (quotient h 2))])
  169.           (vec x y z))))
  170.  
  171. (define (raytrace w h scene)
  172.   (map (ray-pixel 25 scene (vec 0 0 0)) (coords w h (/ w 3))))
  173.  
  174. (define (color->list col)
  175.   (let ([c (color-op col (lambda [x] (max 0 (min 255 (exact-round x)))))])
  176.     (list 255 (color-r c) (color-g c) (color-b c))))
  177.  
  178. (define (to-bytes values)
  179.   (apply bytes (flatten (map color->list values))))
  180.  
  181. (define (bitmap-raytracer w h scene)
  182.   (let* ([bm (make-bitmap w h)]
  183.      [dc (send bm make-dc)]
  184.      [pixels (raytrace w h scene)])
  185.     (send dc set-argb-pixels 0 0 w h
  186.       (to-bytes pixels))
  187.     bm))
  188.  
  189. (define (show-image bm)
  190.   (let ([f (new frame% [label "Raytracer"])])
  191.     (new message% [parent f] [label bm])
  192.     (send f show #t)))
  193.  
  194. (define (save-image bm)
  195.   (send bm save-file "raytracer.png" 'png))
  196.  
  197. (show-image (bitmap-raytracer 1920 1080 (make-scene)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement