summaryrefslogtreecommitdiff
path: root/chickadee/graphics/sprite.scm
diff options
context:
space:
mode:
Diffstat (limited to 'chickadee/graphics/sprite.scm')
-rw-r--r--chickadee/graphics/sprite.scm363
1 files changed, 180 insertions, 183 deletions
diff --git a/chickadee/graphics/sprite.scm b/chickadee/graphics/sprite.scm
index 2f7c53d..cdb0ed9 100644
--- a/chickadee/graphics/sprite.scm
+++ b/chickadee/graphics/sprite.scm
@@ -1,5 +1,5 @@
;;; Chickadee Game Toolkit
-;;; Copyright © 2016, 2019, 2020 David Thompson <davet@gnu.org>
+;;; Copyright © 2016, 2019, 2020, 2021 David Thompson <davet@gnu.org>
;;;
;;; Chickadee is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published
@@ -23,8 +23,9 @@
#:use-module (chickadee math matrix)
#:use-module (chickadee math rect)
#:use-module (chickadee math vector)
- #:use-module (chickadee graphics)
+ #:use-module (chickadee graphics blend)
#:use-module (chickadee graphics color)
+ #:use-module (chickadee graphics engine)
#:use-module (chickadee graphics shader)
#:use-module (chickadee graphics texture)
#:use-module (chickadee graphics buffer)
@@ -45,10 +46,20 @@
draw-nine-patch*
draw-nine-patch))
-(define unbatched-sprite-shader
- (delay
- (strings->shader
- "
+(define-geometry-type <sprite-vertex>
+ sprite-vertex-ref
+ sprite-vertex-set!
+ sprite-vertex-append!
+ (position vec2)
+ (texture vec2))
+
+(define-graphics-variable sprite-geometry
+ (make-geometry <sprite-vertex> 4 #:index-capacity 6))
+(define-graphics-variable sprite-model-matrix (make-null-matrix4))
+(define-graphics-variable sprite-mvp-matrix (make-null-matrix4))
+(define-graphics-variable sprite-shader
+ (strings->shader
+ "
#ifdef GLSL330
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 tex;
@@ -71,8 +82,7 @@ void main(void) {
gl_Position = mvp * vec4(position.xy, 0.0, 1.0);
}
"
- "
-
+ "
#ifdef GLSL120
varying vec2 fragTex;
#else
@@ -91,70 +101,60 @@ void main (void) {
gl_FragColor = texture2D(colorTexture, fragTex) * tint;
#endif
}
-")))
-
-(define-geometry-type <sprite-vertex>
- sprite-vertex-ref
- sprite-vertex-set!
- sprite-vertex-append!
- (position vec2)
- (texture vec2))
-
-(define draw-sprite*
- (let* ((geometry (delay (make-geometry <sprite-vertex> 4 #:index-capacity 6)))
- (mvp (make-null-matrix4)))
- (lambda* (texture
- rect
- matrix
- #:key
- (tint white)
- (blend-mode 'alpha)
- (texcoords (texture-gl-tex-rect texture)))
- (let ((geometry (force geometry)))
- (with-geometry geometry
- (let* ((x1 (rect-x rect))
- (y1 (rect-y rect))
- (x2 (+ x1 (rect-width rect)))
- (y2 (+ y1 (rect-height rect)))
- (s1 (rect-x texcoords))
- (t1 (rect-y texcoords))
- (s2 (+ (rect-x texcoords) (rect-width texcoords)))
- (t2 (+ (rect-y texcoords) (rect-height texcoords))))
- ;; Texture origin is at the top-left, so we need to flip the Y
- ;; coordinate relative to the vertices.
- (sprite-vertex-append! geometry
- (x1 y1 s1 t2)
- (x2 y1 s2 t2)
- (x2 y2 s2 t1)
- (x1 y2 s1 t1))
- (geometry-index-append! geometry 0 3 2 0 2 1)))
- (with-blend-mode blend-mode
- (with-texture 0 texture
- (gpu-apply (force unbatched-sprite-shader)
- (geometry-vertex-array geometry)
- #:tint tint
- #:mvp (if matrix
- (begin
- (matrix4-mult! mvp matrix
- (current-projection))
- mvp)
- (current-projection)))))))))
+"))
+
+(define* (draw-sprite* texture
+ rect
+ matrix
+ #:key
+ (tint white)
+ (blend-mode 'alpha)
+ (texcoords (texture-gl-tex-rect texture)))
+ (let ((shader (graphics-variable-ref sprite-shader))
+ (geometry (graphics-variable-ref sprite-geometry))
+ (mvp (graphics-variable-ref sprite-mvp-matrix)))
+ (with-geometry geometry
+ (let* ((x1 (rect-x rect))
+ (y1 (rect-y rect))
+ (x2 (+ x1 (rect-width rect)))
+ (y2 (+ y1 (rect-height rect)))
+ (s1 (rect-x texcoords))
+ (t1 (rect-y texcoords))
+ (s2 (+ (rect-x texcoords) (rect-width texcoords)))
+ (t2 (+ (rect-y texcoords) (rect-height texcoords))))
+ ;; Texture origin is at the top-left, so we need to flip the Y
+ ;; coordinate relative to the vertices.
+ (sprite-vertex-append! geometry
+ (x1 y1 s1 t2)
+ (x2 y1 s2 t2)
+ (x2 y2 s2 t1)
+ (x1 y2 s1 t1))
+ (geometry-index-append! geometry 0 3 2 0 2 1)))
+ (with-graphics-state ((blend-mode blend-mode)
+ (texture-0 texture))
+ (shader-apply shader
+ (geometry-vertex-array geometry)
+ #:tint tint
+ #:mvp (if matrix
+ (begin
+ (matrix4-mult! mvp matrix
+ (current-projection))
+ mvp)
+ (current-projection))))))
(define %null-vec2 (vec2 0.0 0.0))
(define %default-scale (vec2 1.0 1.0))
-(define draw-sprite
- (let ((matrix (make-null-matrix4)))
- (lambda* (texture
- position
- #:key
- (tint white)
- (origin %null-vec2)
- (scale %default-scale)
- (rotation 0.0)
- (blend-mode 'alpha)
- (rect (texture-gl-rect texture)))
- "Draw TEXTURE at POSITION.
+(define* (draw-sprite texture
+ position
+ #:key
+ (tint white)
+ (origin %null-vec2)
+ (scale %default-scale)
+ (rotation 0.0)
+ (blend-mode 'alpha)
+ (rect (texture-gl-rect texture)))
+ "Draw TEXTURE at POSITION.
Optionally, other transformations may be applied to the sprite.
ROTATION specifies the angle to rotate the sprite, in radians. SCALE
@@ -166,14 +166,15 @@ By default white is used, which does no tinting at all.
By default, alpha blending is used but can be changed by specifying
BLEND-MODE."
- (matrix4-2d-transform! matrix
- #:origin origin
- #:position position
- #:rotation rotation
- #:scale scale)
- (draw-sprite* texture rect matrix
- #:tint tint
- #:blend-mode blend-mode))))
+ (let ((matrix (graphics-variable-ref sprite-model-matrix)))
+ (matrix4-2d-transform! matrix
+ #:origin origin
+ #:position position
+ #:rotation rotation
+ #:scale scale)
+ (draw-sprite* texture rect matrix
+ #:tint tint
+ #:blend-mode blend-mode)))
;;;
@@ -188,6 +189,59 @@ BLEND-MODE."
(texture vec2)
(tint vec4))
+(define-graphics-variable sprite-batch-shader
+ (strings->shader
+ "
+#ifdef GLSL330
+layout (location = 0) in vec2 position;
+layout (location = 1) in vec2 tex;
+layout (location = 2) in vec4 tint;
+#elif defined(GLSL130)
+in vec2 position;
+in vec2 tex;
+in vec4 tint;
+#elif defined(GLSL120)
+attribute vec2 position;
+attribute vec2 tex;
+attribute vec4 tint;
+#endif
+#ifdef GLSL120
+varying vec2 fragTex;
+varying vec4 fragTint;
+#else
+out vec2 fragTex;
+out vec4 fragTint;
+#endif
+uniform mat4 mvp;
+
+void main(void) {
+ fragTex = tex;
+ fragTint = tint;
+ gl_Position = mvp * vec4(position.xy, 0.0, 1.0);
+}
+"
+ "
+#ifdef GLSL120
+varying vec2 fragTex;
+varying vec4 fragTint;
+#else
+in vec2 fragTex;
+in vec4 fragTint;
+#endif
+#ifdef GLSL330
+out vec4 fragColor;
+#endif
+uniform sampler2D colorTexture;
+
+void main (void) {
+#ifdef GLSL330
+ fragColor = texture(colorTexture, fragTex) * fragTint;
+#else
+ gl_FragColor = texture2D(colorTexture, fragTex) * fragTint;
+#endif
+}
+"))
+
(define-record-type <sprite-batch>
(%make-sprite-batch texture geometry size)
sprite-batch?
@@ -258,116 +312,59 @@ texture may be specified via the TEXTURE-REGION argument."
(+ vertex-offset 1))
(set-sprite-batch-size! batch (+ (sprite-batch-size batch) 1))))
-(define sprite-batch-add!
- (let ((matrix (make-null-matrix4)))
- (lambda* (batch
- position
- #:key
- (origin %null-vec2)
- (scale %default-scale)
- (rotation 0.0)
- (tint white)
- texture-region)
- "Add sprite to BATCH at POSITION. To render a subsection of the
+(define* (sprite-batch-add! batch
+ position
+ #:key
+ (origin %null-vec2)
+ (scale %default-scale)
+ (rotation 0.0)
+ (tint white)
+ texture-region)
+ "Add sprite to BATCH at POSITION. To render a subsection of the
batch's texture, a texture object whose parent is the batch texture
may be specified via the TEXTURE-REGION argument."
- (let ((rect (texture-gl-rect
- (or texture-region (sprite-batch-texture batch)))))
- (matrix4-2d-transform! matrix
- #:origin origin
- #:position position
- #:rotation rotation
- #:scale scale)
- (sprite-batch-add* batch rect matrix
- #:tint tint
- #:texture-region texture-region)))))
-
-
-(define batched-sprite-shader
- (delay
- (strings->shader
- "
-#ifdef GLSL330
-layout (location = 0) in vec2 position;
-layout (location = 1) in vec2 tex;
-layout (location = 2) in vec4 tint;
-#elif defined(GLSL130)
-in vec2 position;
-in vec2 tex;
-in vec4 tint;
-#elif defined(GLSL120)
-attribute vec2 position;
-attribute vec2 tex;
-attribute vec4 tint;
-#endif
-#ifdef GLSL120
-varying vec2 fragTex;
-varying vec4 fragTint;
-#else
-out vec2 fragTex;
-out vec4 fragTint;
-#endif
-uniform mat4 mvp;
-
-void main(void) {
- fragTex = tex;
- fragTint = tint;
- gl_Position = mvp * vec4(position.xy, 0.0, 1.0);
-}
-"
- "
-#ifdef GLSL120
-varying vec2 fragTex;
-varying vec4 fragTint;
-#else
-in vec2 fragTex;
-in vec4 fragTint;
-#endif
-#ifdef GLSL330
-out vec4 fragColor;
-#endif
-uniform sampler2D colorTexture;
-
-void main (void) {
-#ifdef GLSL330
- fragColor = texture(colorTexture, fragTex) * fragTint;
-#else
- gl_FragColor = texture2D(colorTexture, fragTex) * fragTint;
-#endif
-}
-")))
-
-(define draw-sprite-batch*
- (let ((mvp (make-null-matrix4)))
- (lambda* (batch matrix #:key (blend-mode 'alpha))
- "Render the contents of BATCH."
- (sprite-batch-flush! batch)
- (matrix4-mult! mvp matrix (current-projection))
- (with-blend-mode blend-mode
- (with-texture 0 (sprite-batch-texture batch)
- (let ((geometry (sprite-batch-geometry batch)))
- (gpu-apply* (force batched-sprite-shader)
- (geometry-vertex-array geometry)
- 0
- (geometry-index-count geometry)
- #:mvp mvp)))))))
+ (let ((matrix (graphics-variable-ref sprite-model-matrix))
+ (rect (texture-gl-rect
+ (or texture-region (sprite-batch-texture batch)))))
+ (matrix4-2d-transform! matrix
+ #:origin origin
+ #:position position
+ #:rotation rotation
+ #:scale scale)
+ (sprite-batch-add* batch rect matrix
+ #:tint tint
+ #:texture-region texture-region)))
+
+(define* (draw-sprite-batch* batch matrix #:key (blend-mode 'alpha))
+ "Render the contents of BATCH."
+ (let ((shader (graphics-variable-ref sprite-batch-shader))
+ (mvp (graphics-variable-ref sprite-mvp-matrix)))
+ (sprite-batch-flush! batch)
+ (matrix4-mult! mvp matrix (current-projection))
+ (with-graphics-state ((blend-mode blend-mode)
+ (texture-0 (sprite-batch-texture batch)))
+ (let ((geometry (sprite-batch-geometry batch)))
+ (shader-apply* shader
+ (geometry-vertex-array geometry)
+ 0
+ (geometry-index-count geometry)
+ #:mvp mvp)))))
-(define draw-sprite-batch
- (let ((matrix (make-null-matrix4)))
- (lambda* (batch
- #:key
- (position %null-vec2)
- (origin %null-vec2)
- (scale %default-scale)
- (rotation 0.0)
- (blend-mode 'alpha))
- "Render the contents of BATCH."
- (matrix4-2d-transform! matrix
- #:origin origin
- #:position position
- #:rotation rotation
- #:scale scale)
- (draw-sprite-batch* batch matrix #:blend-mode blend-mode))))
+(define* (draw-sprite-batch batch
+ #:key
+ (position %null-vec2)
+ (origin %null-vec2)
+ (scale %default-scale)
+ (rotation 0.0)
+ (blend-mode 'alpha))
+ "Render the contents of BATCH."
+ (let ((matrix (graphics-variable-ref sprite-model-matrix)))
+ (matrix4-2d-transform! matrix
+ #:origin origin
+ #:position position
+ #:rotation rotation
+ #:scale scale)
+ (draw-sprite-batch* batch matrix #:blend-mode blend-mode)))
;;;