render: Change texture origin to top-left.
authorDavid Thompson <dthompson2@worcester.edu>
Mon, 10 Sep 2018 21:42:10 +0000 (17:42 -0400)
committerDavid Thompson <dthompson2@worcester.edu>
Mon, 10 Sep 2018 21:49:49 +0000 (17:49 -0400)
This is a pretty big change, but hopefully for the best as this aligns
with graphics programs and the glTF standard that uses a top-left
origin.  We can keep using a lower-left origin for vertices, though.

* chickadee/render/texture.scm (surface->texture): Stop flipping pixel
rows.
* chickadee/render/sprites.scm (draw-sprite-unbatched,
sprite-batch-add!, draw-nine-patch*): Adjust texture y-coordinates.
* chickadee/render/font.scm (parse-fnt): Stop inverting y coordinates.
* chickadee/render/tiled.scm (load-tile-map): Stop inverting tile ids.

chickadee/render/font.scm
chickadee/render/sprite.scm
chickadee/render/texture.scm
chickadee/render/tiled.scm

index d5995a2..e1958a2 100644 (file)
@@ -255,10 +255,7 @@ extension must be either .xml or .fnt."
                          (width (attr node 'width string->number))
                          (height (attr node 'height string->number))
                          (x (attr node 'x string->number))
-                         ;; Invert the y axis.  Our origin is the
-                         ;; bottom-left corner, not top-left.
-                         (y (- image-height height
-                               (attr node 'y string->number)))
+                         (y (attr node 'y string->number))
                          (x-offset (attr node 'xoffset string->number))
                          (y-offset (- line-height height
                                       (attr node 'yoffset string->number)))
index 067384b..d8ef363 100644 (file)
@@ -99,19 +99,21 @@ void main (void) {
           (f32vector-set! bv 6 x1)
           (f32vector-set! bv 7 y2)))
       (with-mapped-typed-buffer (force texcoord-buffer)
-        (let ((s1 (rect-left texture-region))
-              (t1 (rect-bottom texture-region))
-              (s2 (rect-right texture-region))
-              (t2 (rect-top texture-region))
+        ;; Texture origin is at the top-left, so we need to flip the Y
+        ;; coordinate relative to the vertices.
+        (let ((s1 (rect-x texture-region))
+              (t1 (rect-y texture-region))
+              (s2 (+ (rect-x texture-region) (rect-width texture-region)))
+              (t2 (+ (rect-y texture-region) (rect-height texture-region)))
               (bv (typed-buffer-data (force texcoord-buffer))))
           (f32vector-set! bv 0 s1)
-          (f32vector-set! bv 1 t1)
+          (f32vector-set! bv 1 t2)
           (f32vector-set! bv 2 s2)
-          (f32vector-set! bv 3 t1)
+          (f32vector-set! bv 3 t2)
           (f32vector-set! bv 4 s2)
-          (f32vector-set! bv 5 t2)
+          (f32vector-set! bv 5 t1)
           (f32vector-set! bv 6 s1)
-          (f32vector-set! bv 7 t2)))
+          (f32vector-set! bv 7 t1)))
       (with-blend-mode blend-mode
         (with-texture 0 texture
           (gpu-apply shader (force vertex-array)
@@ -248,10 +250,10 @@ void main (void) {
                (local-y1 (rect-y region))
                (local-x2 (+ local-x1 (rect-width region)))
                (local-y2 (+ local-y1 (rect-height region)))
-               (s1 (rect-left texture-region))
-               (t1 (rect-bottom texture-region))
-               (s2 (rect-right texture-region))
-               (t2 (rect-top texture-region)))
+               (s1 (rect-x texture-region))
+               (t1 (rect-y texture-region))
+               (s2 (+ (rect-x texture-region) (rect-width texture-region)))
+               (t2 (+ (rect-y texture-region) (rect-height texture-region))))
           (set-vec2-x! world1 local-x1)
           (set-vec2-y! world1 local-y1)
           (set-vec2-x! world2 local-x2)
@@ -293,16 +295,16 @@ void main (void) {
           (set-offset (* size 8))
           ;; Bottom-left
           (f32vector-set! texcoords (offset) s1)
-          (f32vector-set! texcoords (+ (offset) 1) t1)
+          (f32vector-set! texcoords (+ (offset) 1) t2)
           ;; Bottom-right
           (f32vector-set! texcoords (+ (offset) 2) s2)
-          (f32vector-set! texcoords (+ (offset) 3) t1)
+          (f32vector-set! texcoords (+ (offset) 3) t2)
           ;; Top-right
           (f32vector-set! texcoords (+ (offset) 4) s2)
-          (f32vector-set! texcoords (+ (offset) 5) t2)
+          (f32vector-set! texcoords (+ (offset) 5) t1)
           ;; Top-left
           (f32vector-set! texcoords (+ (offset) 6) s1)
-          (f32vector-set! texcoords (+ (offset) 7) t2)
+          (f32vector-set! texcoords (+ (offset) 7) t1)
           (set-sprite-batch-size! batch (1+ size)))))))
 
 (define *batch?* #f)
@@ -407,14 +409,14 @@ rendered entirely."
              (trect (texture-gl-tex-rect texture))
              (tw (rect-width prect))
              (th (rect-height prect))
-             (border-s1 (rect-left trect))
-             (border-t1 (rect-bottom trect))
-             (border-s2 (rect-right trect))
-             (border-t2 (rect-top trect))
+             (border-s1 (rect-x trect))
+             (border-t1 (rect-y trect))
+             (border-s2 (+ (rect-x trect) (rect-width trect)))
+             (border-t2 (+ (rect-y trect) (rect-height trect)))
              (fill-s1 (+ border-s1 (/ left-margin tw)))
-             (fill-t1 (+ border-t1 (/ bottom-margin th)))
+             (fill-t1 (+ border-t1 (/ top-margin th)))
              (fill-s2 (- border-s2 (/ right-margin tw)))
-             (fill-t2 (- border-t2 (/ top-margin th))))
+             (fill-t2 (- border-t2 (/ bottom-margin th))))
         (define (draw-piece x1 y1 x2 y2 s1 t1 s2 t2)
           (set-rect-x! %rect x1)
           (set-rect-y! %rect y1)
@@ -431,31 +433,31 @@ rendered entirely."
         (with-batched-sprites
          ;; bottom-left
          (draw-piece border-x1 border-y1 fill-x1 fill-y1
-                     border-s1 border-t1 fill-s1 fill-t1)
+                     border-s1 fill-t2 fill-s1 border-t2)
          ;; bottom-center
          (draw-piece fill-x1 border-y1 fill-x2 fill-y1
-                     fill-s1 border-t1 fill-s2 fill-t1)
+                     fill-s1 fill-t2 fill-s2 border-t2)
          ;; bottom-right
          (draw-piece fill-x2 border-y1 border-x2 fill-y1
-                     fill-s2 border-t1 border-s2 fill-t1)
+                     fill-s2 fill-t2 border-s2 border-t2)
          ;; center-left
          (draw-piece border-x1 fill-y1 fill-x1 fill-y2
-                     border-s1 fill-t1 fill-s1 fill-t2)
+                     border-s1 fill-t2 fill-s1 fill-t1)
          ;; center
          (draw-piece fill-x1 fill-y1 fill-x2 fill-y2
-                     fill-s1 fill-t1 fill-s2 fill-t2)
+                     fill-s1 fill-t2 fill-s2 fill-t1)
          ;; center-right
          (draw-piece fill-x2 fill-y1 border-x2 fill-y2
-                     fill-s2 fill-t1 border-s2 fill-t2)
+                     fill-s2 fill-t2 border-s2 fill-t1)
          ;; top-left
          (draw-piece border-x1 fill-y2 fill-x1 border-y2
-                     border-s1 fill-t2 fill-s1 border-t2)
+                     border-s1 border-t1 fill-s1 fill-t1)
          ;; top-center
          (draw-piece fill-x1 fill-y2 fill-x2 border-y2
-                     fill-s1 fill-t2 fill-s2 border-t2)
+                     fill-s1 border-t1 fill-s2 fill-t1)
          ;; top-right
          (draw-piece fill-x2 fill-y2 border-x2 border-y2
-                     fill-s2 fill-t2 border-s2 border-t2))))))
+                     fill-s2 border-t1 border-s2 fill-t1))))))
 
 (define draw-nine-patch
   (let ((position (vec2 0.0 0.0))
index 960b7d0..4214c70 100644 (file)
@@ -233,12 +233,7 @@ the given MIN-FILTER and MAG-FILTER."
     (lambda (surface)
       (let* ((width (surface-width surface))
              (height (surface-height surface))
-             ;; OpenGL textures use the bottom-left corner as the
-             ;; origin, whereas SDL uses the top-left, so the rows
-             ;; of pixels must be reversed before creating a
-             ;; texture from them.
-             (pixels (flip-pixels-vertically (surface-pixels surface)
-                                             width height)))
+             (pixels (surface-pixels surface)))
         (make-texture pixels width height
                       #:min-filter min-filter
                       #:mag-filter mag-filter
index 42b6793..51f2cb9 100644 (file)
           (duration (attr node 'duration string->number)))
       ;; TODO: lookup actual tile in tileset
       (%make-animation-frame tile-id duration)))
-  (define (invert-tile-id id rows columns)
-    (let* ((x (modulo id columns))
-           (y (- rows (floor (/ id columns)) 1))
-           (t (+ (* y columns) x)))
-      (+ (* y columns) x)))
   (define (parse-tile node rows columns atlas)
     (let ((id (attr node 'id string->number))
           (animation (map parse-frame ((sxpath '(animation frame)) node)))
           (properties (map parse-property
                            ((sxpath '(properties property)) node))))
-      (%make-tile id (texture-atlas-ref atlas (invert-tile-id id rows columns))
+      (%make-tile id (texture-atlas-ref atlas id)
                   animation properties)))
   (define (parse-tiles nodes size columns atlas)
     (let ((table (make-hash-table))
         (when (< i size)
           (let ((tile
                  (or (hash-ref table i)
-                     (let* ((t (invert-tile-id i rows columns)))
-                       (%make-tile i (texture-atlas-ref atlas t) #f '())))))
+                     (%make-tile i (texture-atlas-ref atlas i) #f '()))))
             (vector-set! tiles i tile))
           (loop (+ i 1))))
       tiles))