diff options
-rw-r--r-- | chickadee/graphics/particles.scm | 132 |
1 files changed, 49 insertions, 83 deletions
diff --git a/chickadee/graphics/particles.scm b/chickadee/graphics/particles.scm index 167f5c7..8048ba1 100644 --- a/chickadee/graphics/particles.scm +++ b/chickadee/graphics/particles.scm @@ -77,7 +77,7 @@ indefinitely." (and life (<= life 0)))) (define-record-type <particles> - (%make-particles capacity size bv buffer shader vertex-array + (%make-particles capacity size bv shader geometry texture animation-rows animation-columns speed-range acceleration-range direction-range blend-mode start-color end-color lifetime @@ -86,9 +86,8 @@ indefinitely." (capacity particles-capacity) (size particles-size set-particles-size!) (bv particles-bv) - (buffer particles-buffer) (shader particles-shader) - (vertex-array particles-vertex-array) + (geometry particles-geometry) (texture particles-texture set-particles-texture!) (animation-rows particles-animation-rows) (animation-columns particles-animation-columns) @@ -120,16 +119,22 @@ indefinitely." layout (location = 0) in vec2 position; layout (location = 1) in vec2 tex; layout (location = 2) in vec2 offset; -layout (location = 3) in float life; +layout (location = 3) in vec2 velocity; +layout (location = 4) in vec2 acceleration; +layout (location = 5) in float life; #elif defined(GLSL130) in vec2 position; in vec2 tex; in vec2 offset; +in vec2 velocity; +in vec2 acceleration; in float life; #elif defined(GLSL120) attribute vec2 position; attribute vec2 tex; attribute vec2 offset; +attribute vec2 velocity; +attribute vec2 acceleration; attribute float life; #endif #ifdef GLSL120 @@ -180,55 +185,21 @@ void main (void) { } ")) -(define (make-particles-vertex-array capacity width height texture buffer) - (let* ((indices (make-buffer-view #:type 'scalar - #:component-type 'unsigned-int - #:divisor 0 - #:buffer (make-buffer - (u32vector 0 3 2 0 2 1) - #:target 'index))) - (verts (make-buffer-view #:type 'vec2 - #:component-type 'float - #:divisor 0 - #:buffer (make-buffer - ;; TODO: use the texture - ;; size in pixels. - (let ((hw (/ width 2.0)) - (hh (/ height 2.0))) - (f32vector (- hw) (- hh) - hw (- hh) - hw hh - (- hw) hh)) - #:target 'vertex))) - (tex (make-buffer-view #:type 'vec2 - #:component-type 'float - #:divisor 0 - #:buffer (make-buffer - (let ((tex (texture-gl-tex-rect - texture))) - (f32vector 0 0 - 1 0 - 1 1 - 0 1)) - #:target 'vertex))) - (pos (make-buffer-view #:name "particle position buffer" - #:buffer buffer - #:type 'vec2 - #:component-type 'float - #:length capacity - #:divisor 1)) - (life (make-buffer-view #:name "particle life remaining buffer" - #:buffer buffer - #:type 'scalar - #:component-type 'int - #:offset 24 - #:length capacity - #:divisor 1))) - (make-vertex-array #:indices indices - #:attributes `((0 . ,verts) - (1 . ,tex) - (2 . ,pos) - (3 . ,life))))) +(define-geometry-type <quad-vertex> + quad-vertex-ref + quad-vertex-set! + quad-vertex-append! + (position vec2) + (texture vec2)) + +(define-geometry-type <particle-vertex> + particle-vertex-ref + particle-vertex-set! + particle-vertex-append! + (position vec2) + (velocity vec2) + (acceleration vec2) + (life int)) (define* (make-particles capacity #:key (blend-mode 'alpha) @@ -302,29 +273,27 @@ default. - SORT: 'youngest' if youngest particle should be drawn last or 'oldest' for the reverse. By default, no sorting is applied at all." - (let* ((stride (+ (* 4 2) ; position - 2x f32 - (* 4 2) ; velocity - 2x f32 - (* 4 2) ; acceleration - 2x f32 - 4)) ; life remaining - 1x s32 - (buffer (make-buffer #f - #:name "packed particle data" - ;; One extra element to use as - ;; swap space for sorting - ;; particles. - #:length (* stride capacity) - #:stride stride - #:usage 'stream))) + (let ((geometry (make-geometry (list (list <quad-vertex> #:capacity 4) + (list <particle-vertex> #:divisor 1)) + capacity + #:index-capacity 6))) + (with-geometry* geometry (<quad-vertex> 'index) + (let ((hw (/ width 2.0)) + (hh (/ height 2.0))) + (quad-vertex-append! geometry + ((- hw) (- hh) 0.0 0.0) + (hw (- hh) 1.0 0.0) + (hw hh 1.0 1.0) + ((- hw) hh 0.0 1.0))) + (geometry-index-append! geometry 0 3 2 0 2 1)) (%make-particles capacity 0 ;; 1 extra element as swap space for sorting. - (make-bytevector (* (+ capacity 1) stride)) - buffer + (make-bytevector (* (+ capacity 1) + (geometry-type-stride + <particle-vertex>))) (make-particles-shader) - (make-particles-vertex-array capacity - width - height - texture - buffer) + geometry texture animation-rows animation-columns @@ -340,10 +309,7 @@ default. (define (update-particles particles) "Advance the simulation of PARTICLES." - (let* ((buffer (particles-buffer particles)) - (va (particles-vertex-array particles)) - (pos (assq-ref (vertex-array-attributes va) 2)) - (speed-range (particles-speed-range particles)) + (let* ((speed-range (particles-speed-range particles)) (acceleration-range (particles-acceleration-range particles)) (direction-range (particles-direction-range particles)) (sort (particles-sort particles)) @@ -359,7 +325,7 @@ default. (ddy-offset 20) (life-offset 24)) (let* ((bv (particles-bv particles)) - (stride (buffer-stride buffer)) + (stride (geometry-type-stride <particle-vertex>)) (capacity (particles-capacity particles))) ;; Update existing particles, removing dead ones. (let loop ((i 0) @@ -457,20 +423,20 @@ default. (inner (- j stride)))) (outer (+ i stride))))) (sort 0 (* (particles-size particles) stride)))) - (with-mapped-buffer buffer - (bytevector-copy! bv 0 (buffer-data buffer) 0 (* (particles-size particles) stride)))))) + (with-geometry* (particles-geometry particles) (<particle-vertex>) + (geometry-import! (particles-geometry particles) <particle-vertex> bv 0 + (particles-size particles)))))) (define draw-particles* (let ((mvp (make-null-matrix4))) (lambda (particles matrix) "Render PARTICLES with MATRIX applied." - (let ((size (particles-size particles)) - (va (particles-vertex-array particles))) + (let ((geometry (particles-geometry particles))) (with-blend-mode (particles-blend-mode particles) (with-texture 0 (particles-texture particles) (gpu-apply/instanced (particles-shader particles) - va - size + (geometry-vertex-array geometry) + (particles-size particles) #:mvp (if matrix (begin (matrix4-mult! mvp matrix |