Plot performance improvement: precalculated light, view and half dir

Color flonum-to-byte conversion handles special flonums (hopefully helps with Marijn's problem)
This commit is contained in:
Neil Toronto 2011-12-07 10:44:48 -07:00
parent 419a7ccbc0
commit 3e895b7072
3 changed files with 33 additions and 27 deletions

View File

@ -63,8 +63,10 @@
(min (max i 1) 255))
(define (real->color-byte f)
(define i (inexact->exact (floor f)))
(min (max i 0) 255))
(cond [(rational? f) (define i (inexact->exact (floor f)))
(min (max i 0) 255)]
[(eqv? f +inf.0) 255]
[else 0]))
;; Returns an immutable instance of color%. Immutable colors are faster because they don't have to
;; have immutable copies made when they're used in a dc.

View File

@ -1,6 +1,7 @@
#lang racket/base
(require racket/class racket/match racket/list racket/math racket/contract racket/vector racket/flonum
unstable/flonum
"../common/math.rkt"
"../common/plot-device.rkt"
"../common/ticks.rkt"
@ -683,8 +684,16 @@
(define light (m3-apply rotate-rho-matrix (vector (- -0.5 2.0)
(- -0.5 2.0)
(+ 0.5 5.0))))
;; View direction, in normalized view coordinates: many graph widths backward
(define view-dir (vector 0.0 -50.0 0.0))
;; Do lighting only by direction so we can precalculate light-dir and half-dir
;; Conceptually, the viewer and light are at infinity
;; Light direction
(define light-dir (vnormalize light))
;; View direction, in normalized view coordinates
(define view-dir (vector 0.0 -1.0 0.0))
;; Blinn-Phong "half angle" direction
(define half-dir (vnormalize (v* (v+ light-dir view-dir) 0.5)))
(define diffuse-light? (plot3d-diffuse-light?))
(define specular-light? (plot3d-specular-light?))
@ -695,18 +704,18 @@
[(not (or diffuse-light? specular-light?)) (λ (v normal) (values 1.0 0.0))]
[else
(λ (v normal)
; common lighting values
(define light-dir (vnormalize (v- light v)))
; diffuse lighting: typical Lambertian surface model
(define diff (if diffuse-light? (abs (vdot normal light-dir)) 1.0))
; specular highlighting: Blinn-Phong model
(define spec (cond [specular-light?
(define lv (v* (v+ light-dir view-dir) 0.5))
(define cos-angle (/ (abs (vdot normal lv)) (vmag lv)))
(* 32.0 (expt cos-angle 10.0))]
[else 0.0]))
; put it all together
(values (+ ambient-light (* (- 1.0 ambient-light) diff)) spec))]))
;; Diffuse lighting: typical Lambertian surface model (using absolute value because we
;; can't expect surface normals to point the right direction)
(define diff
(cond [diffuse-light? (flabs (vdot normal light-dir))]
[else 1.0]))
;; Specular highlighting: Blinn-Phong model
(define spec
(cond [specular-light? (fl* 32.0 (flexpt (flabs (vdot normal half-dir)) 20.0))]
[else 0.0]))
;; Blend ambient light with diffuse light, return specular as it is
;; As ambient-light -> 1.0, contribution of diffuse -> 0.0
(values (fl+ ambient-light (fl* (fl- 1.0 ambient-light) diff)) spec))]))
;; ===============================================================================================
;; Public drawing control (used by plot3d/dc)

View File

@ -2,7 +2,7 @@
(require racket/unsafe/ops)
(provide flatan2 flmodulo
(provide flatan2 flmodulo flexpt
flonum->bit-field bit-field->flonum
flonum->ordinal ordinal->flonum
flstep flnext flprev
@ -18,6 +18,11 @@
[(not (flonum? y)) (raise-type-error 'flmodulo "flonum" 1 x y)]
[else (unsafe-fl- x (unsafe-fl* y (unsafe-flfloor (unsafe-fl/ x y))))]))
(define (flexpt b x)
(cond [(not (flonum? b)) (raise-type-error 'flexpt "flonum" 0 b x)]
[(not (flonum? x)) (raise-type-error 'flexpt "flonum" 1 b x)]
[else (unsafe-flexp (unsafe-fl* x (unsafe-fllog b)))]))
(define (flonum->bit-field x)
(cond [(flonum? x) (integer-bytes->integer (real->floating-point-bytes x 8) #f)]
[else (raise-type-error 'flonum->bit-field "flonum" x)]))
@ -62,13 +67,3 @@
(define -min.0 (flprev 0.0))
(define +min.0 (flnext 0.0))
(define +max.0 (flprev +inf.0))
#|
(require plot)
(parameterize ([plot-x-ticks (log-ticks #:base 2 #:number 5)]
[y-axis-ticks? #f])
(plot (list (function (λ (x) (flonum->ordinal (exact->inexact x)))
1/4 4)
(map y-axis '(1/2 1 2)))))
|#