diff --git a/collects/images/private/deep-flomap-render.rkt b/collects/images/private/deep-flomap-render.rkt index 6d6dd3ce15..412323d66b 100644 --- a/collects/images/private/deep-flomap-render.rkt +++ b/collects/images/private/deep-flomap-render.rkt @@ -69,11 +69,13 @@ ;; =================================================================================================== ;; Pass 1: tracing from a directional light source -(: trace-directional-light (flomap flomap flomap flomap Integer Integer Integer Integer - -> (values flomap flomap))) -(define (trace-directional-light alpha-fm rgb-fm z-fm normal-fm x-min x-max y-min y-max) +(: trace-directional-light (flomap flomap flomap flomap + Integer Integer Integer Integer -> (values flomap flomap))) +(define (trace-directional-light alpha-fm rgb-fm z-fm normal-fm + x-min x-max y-min y-max) (match-define (flomap alpha-vs 1 w h) alpha-fm) - (match-define (list rgb-vs z-vs normal-vs) (map flomap-values (list rgb-fm z-fm normal-fm))) + (match-define (list rgb-vs z-vs normal-vs) + (map flomap-values (list rgb-fm z-fm normal-fm))) (define z-max (flomap-max-value z-fm)) (define opacity-z (/ z-max (transmission-density))) @@ -111,8 +113,12 @@ (define diffuse-fm (make-flomap 3 w h lz)) (define diffuse-vs (flomap-values diffuse-fm)) - (define sx-vs (make-flvector (* w h) +nan.0)) - (define sy-vs (make-flvector (* w h) +nan.0)) + ;(define sx-vs (make-flvector (* w h) +nan.0)) + ;(define sy-vs (make-flvector (* w h) +nan.0)) + (define sx-fm (inline-build-flomap 1 w h (λ (k x y i) (+ (fx->fl x) 0.5)))) + (define sy-fm (inline-build-flomap 1 w h (λ (k x y i) (+ (fx->fl y) 0.5)))) + (define sx-vs (flomap-values sx-fm)) + (define sy-vs (flomap-values sy-fm)) (define Irgb-vs (make-flvector (* 3 w h))) (for*: ([int-y : Integer (in-range y-min y-max)] @@ -330,9 +336,10 @@ ;; =================================================================================================== ;; Pass 2: tracing from a directional viewer -(: trace-directional-view (flomap flomap flomap flomap flomap Integer Integer Integer Integer - -> (values flomap flomap))) -(define (trace-directional-view alpha-fm rgb-fm z-fm normal-fm shadow-fm x-min x-max y-min y-max) +(: trace-directional-view (flomap flomap flomap flomap flomap + Integer Integer Integer Integer -> (values flomap flomap))) +(define (trace-directional-view alpha-fm rgb-fm z-fm normal-fm shadow-fm + x-min x-max y-min y-max) (define-values (w h) (flomap-size alpha-fm)) (match-define (list alpha-vs rgb-vs z-vs normal-vs shadow-vs) (map flomap-values (list alpha-fm rgb-fm z-fm normal-fm shadow-fm))) @@ -407,7 +414,10 @@ (unsafe-flvector-set! reflected-vs (fx+ j 2) b)))) ;; transmission (refraction) (when (Ti . > . 0.0) - (define-values (tx ty tz) (transmitted-vector nx ny nz 0.0 0.0 -1.0 1.0 η2)) + (define snx (unsafe-flvector-ref normal-vs j)) + (define sny (unsafe-flvector-ref normal-vs (fx+ j 1))) + (define snz (unsafe-flvector-ref normal-vs (fx+ j 2))) + (define-values (tx ty tz) (transmitted-vector snx sny snz 0.0 0.0 -1.0 1.0 η2)) ;; sz = z + dist * tz, so dist = (sz - z) / tz (define dist (/ (- 0.0 z) tz)) (when (and (dist . >= . 0.0) (dist . < . +inf.0)) @@ -456,38 +466,43 @@ (case-lambda [(dfm) (deep-flomap-render dfm #f)] [(dfm background-fm) - (define-values (w h) (deep-flomap-size dfm)) - (define argb-fm (flomap-divide-alpha (deep-flomap-argb dfm))) - (define alpha-fm (flomap-ref-component argb-fm 0)) - (define rgb-fm (flomap-drop-components argb-fm 1)) - (define z-fm (fmmax 0.0 (deep-flomap-z dfm))) - (define normal-fm (flomap-gradient-normal z-fm)) - (define bg-fm (if background-fm (prep-background background-fm w h) #f)) - (define-values (_1 x-min y-min _2 x-max y-max) (flomap-nonzero-rect alpha-fm)) - - ;; pass 1: trace from the light source - (define-values (diffracted-fm raw-shadow-fm) - (trace-directional-light alpha-fm rgb-fm z-fm normal-fm x-min x-max y-min y-max)) - - ;; blur the shadow to simulate internal scatter - (define σ (* (min w h) (shadow-blur))) - (define shadow-fm - (cond [bg-fm - ;; two Gaussian blurs by half-σ is equivalent to one Gaussian blur by σ - (define half-σ (* (/ 1 (sqrt 2)) σ)) - (let* ([fm (flomap-blur raw-shadow-fm half-σ)] - [fm (fm* fm bg-fm)] - [fm (flomap-blur fm half-σ)]) - fm)] - [else - (flomap-blur raw-shadow-fm σ)])) - - ;; pass 2: trace from the viewer - (define-values (reflected-fm transmitted-fm) - (trace-directional-view alpha-fm rgb-fm z-fm normal-fm shadow-fm x-min x-max y-min y-max)) - - ;; add all the light together, convert to premultiplied-alpha flomap - (let* ([fm (fm+ (fm+ diffracted-fm transmitted-fm) reflected-fm)] - [fm (flomap-append-components alpha-fm fm)] - [fm (flomap-multiply-alpha fm)]) - fm)])) + (let ([dfm (deep-flomap-inset dfm 1)]) + (define-values (w h) (deep-flomap-size dfm)) + (define argb-fm (flomap-divide-alpha (deep-flomap-argb dfm))) + (define alpha-fm (flomap-ref-component argb-fm 0)) + (define rgb-fm (flomap-drop-components argb-fm 1)) + (define z-fm (fmmax 0.0 (deep-flomap-z dfm))) + (define normal-fm (flomap-gradient-normal z-fm)) + (define bg-fm (if background-fm (prep-background background-fm w h) #f)) + (define-values (x-min y-min x-max y-max) + (let-values ([(_1 x-min y-min _2 x-max y-max) (flomap-nonzero-rect alpha-fm)]) + (values (max 0 (- x-min 1)) (max 0 (- y-min 1)) + (min w (+ x-max 1)) (min h (+ y-max 1))))) + + ;; pass 1: trace from the light source + (define-values (diffracted-fm raw-shadow-fm) + (trace-directional-light alpha-fm rgb-fm z-fm normal-fm x-min x-max y-min y-max)) + + ;; two Gaussian blurs by half of σ^2 is equivalent to one Gaussian blur by σ^2 + (define σ^2 (sqr (* (min w h) (shadow-blur)))) + + ;; blur the shadow to simulate internal scatter + (define shadow-fm + (cond [bg-fm + (let* ([fm (flomap-blur raw-shadow-fm (sqrt (* 1/3 σ^2)))] + [fm (fm* fm bg-fm)] + [fm (flomap-blur fm (sqrt (* 1/3 σ^2)))]) + fm)] + [else + (flomap-blur raw-shadow-fm (sqrt (* 2/3 σ^2)))])) + + ;; pass 2: trace from the viewer + (define-values (reflected-fm raw-transmitted-fm) + (trace-directional-view alpha-fm rgb-fm z-fm normal-fm shadow-fm x-min x-max y-min y-max)) + ;; simulate scatter some more + (define transmitted-fm (flomap-blur raw-transmitted-fm (sqrt (* 1/3 σ^2)))) + ;; add all the light together, convert to premultiplied-alpha flomap + (let* ([fm (fm+ (fm+ diffracted-fm transmitted-fm) reflected-fm)] + [fm (flomap-append-components alpha-fm fm)] + [fm (flomap-multiply-alpha fm)]) + (flomap-inset fm -1)))])) diff --git a/collects/images/private/flomap-gradient.rkt b/collects/images/private/flomap-gradient.rkt index 29986297fc..1320212be7 100644 --- a/collects/images/private/flomap-gradient.rkt +++ b/collects/images/private/flomap-gradient.rkt @@ -14,44 +14,56 @@ (: flomap-gradient-x (flomap -> flomap)) (define (flomap-gradient-x fm) (match-define (flomap vs c w h) fm) - (define cw (fx* c w)) - (define d20 (fx- 1 cw)) - (define d22 (fx+ cw 1)) + (define +x (fx* c 1)) + (define -x+y (fx* c (fx- w 1))) + (define +x+y (fx* c (fx+ w 1))) (define w-1 (fx- w 1)) (define h-1 (fx- h 1)) (inline-build-flomap c w h - (λ (_k x y i) + (λ (k x y i) (cond [(and (x . fx> . 0) (x . fx< . w-1) (y . fx> . 0) (y . fx< . h-1)) - (+ (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i d20))) - (* 0.1875 (unsafe-flvector-ref vs (fx- i d22)))) - (- (* 0.6250 (unsafe-flvector-ref vs (fx+ i 1))) - (* 0.6250 (unsafe-flvector-ref vs (fx- i 1)))) - (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i d22))) - (* 0.1875 (unsafe-flvector-ref vs (fx- i d20)))))] - [else 0.0])))) + (+ (- (* 0.1875 (unsafe-flvector-ref vs (fx- i -x+y))) + (* 0.1875 (unsafe-flvector-ref vs (fx- i +x+y)))) + (- (* 0.6250 (unsafe-flvector-ref vs (fx+ i +x))) + (* 0.6250 (unsafe-flvector-ref vs (fx- i +x)))) + (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i +x+y))) + (* 0.1875 (unsafe-flvector-ref vs (fx+ i -x+y)))))] + [else + (+ (- (* 0.1875 (flomap-ref fm k (+ x 1) (- y 1))) + (* 0.1875 (flomap-ref fm k (- x 1) (- y 1)))) + (- (* 0.6250 (flomap-ref fm k (+ x 1) y)) + (* 0.6250 (flomap-ref fm k (- x 1) y))) + (- (* 0.1875 (flomap-ref fm k (+ x 1) (+ y 1))) + (* 0.1875 (flomap-ref fm k (- x 1) (+ y 1)))))])))) (: flomap-gradient-y (flomap -> flomap)) (define (flomap-gradient-y fm) (match-define (flomap vs c w h) fm) - (define cw (fx* c w)) - (define d02 (fx- cw 1)) - (define d22 (fx+ cw 1)) + (define +y (fx* c w)) + (define -x+y (fx* c (fx- w 1))) + (define +x+y (fx* c (fx+ w 1))) (define w-1 (fx- w 1)) (define h-1 (fx- h 1)) (inline-build-flomap c w h - (λ (_k x y i) + (λ (k x y i) (cond [(and (x . fx> . 0) (x . fx< . w-1) (y . fx> . 0) (y . fx< . h-1)) - (+ (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i d02))) - (* 0.1875 (unsafe-flvector-ref vs (fx- i d22)))) - (- (* 0.6250 (unsafe-flvector-ref vs (fx+ i cw))) - (* 0.6250 (unsafe-flvector-ref vs (fx- i cw)))) - (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i d22))) - (* 0.1875 (unsafe-flvector-ref vs (fx- i d02)))))] - [else 0.0])))) + (+ (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i -x+y))) + (* 0.1875 (unsafe-flvector-ref vs (fx- i +x+y)))) + (- (* 0.6250 (unsafe-flvector-ref vs (fx+ i +y))) + (* 0.6250 (unsafe-flvector-ref vs (fx- i +y)))) + (- (* 0.1875 (unsafe-flvector-ref vs (fx+ i +x+y))) + (* 0.1875 (unsafe-flvector-ref vs (fx- i -x+y)))))] + [else + (+ (- (* 0.1875 (flomap-ref fm k (- x 1) (+ y 1))) + (* 0.1875 (flomap-ref fm k (- x 1) (- y 1)))) + (- (* 0.6250 (flomap-ref fm k x (+ y 1))) + (* 0.6250 (flomap-ref fm k x (- y 1)))) + (- (* 0.1875 (flomap-ref fm k (+ x 1) (+ y 1))) + (* 0.1875 (flomap-ref fm k (+ x 1) (- y 1)))))])))) (: flomap-gradient (flomap -> (values flomap flomap))) (define (flomap-gradient fm)