add sprite rendering

This commit is contained in:
tali 2024-01-19 19:01:20 -05:00
parent c1f8a4faec
commit 231de4b245
6 changed files with 65 additions and 48 deletions

View File

@ -2,22 +2,21 @@
uniform ivec2 Viewport;
uniform mat3 Transform;
uniform vec4 BoundingBox;
uniform sampler2D Texture;
/* TODO: instanced */
uniform vec4 Rect;
uniform vec4 Clip;
in vec2 Vert;
/* TODO: instances */
// in vec4 Rect;
// in vec4 Clip;
out vec2 TextureCoord;
void main() {
vec2 vert = mix(BoundingBox.xy, BoundingBox.zw, Vert);
vec2 vert = mix(Rect.xy, Rect.zw, Vert);
vec3 pos = Transform * vec3(vert, 1.0);
// TextureCoord = mix(Clip.st, Clip.pq, Vert) / textureSize(T, 0);
TextureCoord = Vert;
TextureCoord = mix(Clip.st, Clip.pq, Vert) / textureSize(Texture, 0);
gl_Position.xy = pos.xy * vec2(2.0, -2.0) / Viewport + vec2(-1.0, 1.0);
gl_Position.z = 0.0;

View File

@ -13,8 +13,7 @@ let main () =
let ren = Renderer.make ~wnd in
info (fun m -> m "renderer initialized");
let tex_cat = Asset.load_texture "catthumbsup.png" in
let tex_otters = Asset.load_texture "otters.jpg" in
let blocks = Asset.load_sprite_map "blocks" ~dpi:192 in
debug (fun m -> m "loaded assets");
let tg = TG.make () in
@ -29,13 +28,9 @@ let main () =
let tf = TG.model (Scene.transform root) in
begin
let tx =
Float_infix.(
Float.sin (time * 2.0) * 300.0
+ 512.0
)
in
let tx = 512.0 in
let ty = 400.0 in
let _ = time in
Mat2A.set tf ~tx ~ty ~sx:1.0 ~sy:1.0
end;
@ -43,15 +38,16 @@ let main () =
Renderer.clear ren (rgb24 0x000000);
TG.update tg;
SG.render sg ~ren;
(* SG.render sg ~ren; *)
Renderer.draw_texture ren tex_otters
~tf
~bb:(aabb 0.0 (-200.0) (300.0) (200.0));
Renderer.draw_texture ren tex_cat
~tf
~bb:(aabb (-200.0) (-100.0) 0.0 (100.0));
Renderer.draw_sprite ren (Sprite.get blocks "L")
~tf ~pos:(vec2 0.0 0.0);
Renderer.draw_sprite ren (Sprite.get blocks "O")
~tf ~pos:(vec2 32.0 0.0);
Renderer.draw_sprite ren (Sprite.get blocks "S")
~tf ~pos:(vec2 0.0 32.0);
Renderer.draw_sprite ren (Sprite.get blocks "Z")
~tf ~pos:(vec2 32.0 32.0);
Renderer.post_draw ren;

View File

@ -348,14 +348,15 @@ let draw_rect t ~tf ~bb ~fill =
let _white = Color.white ()
let draw_texture t ~tf ~bb ?(tint = _white) tex =
let draw_texture t ~tf ~rect ~clip ~tint tex =
let sh = t.sprite in
begin
(* TODO: cache/store uniform locations in some way *)
use sh;
set_mat2a (uniform sh "Transform") tf;
set_aabb (uniform sh "BoundingBox") bb;
set_tex (uniform sh "Texture") tex;
set_aabb (uniform sh "Rect") rect;
set_aabb (uniform sh "Clip") clip;
set_color (uniform sh "Tint") tint;
draw_geometry t.sprite_rect;
end

View File

@ -1,7 +1,10 @@
module Window = Window
module Renderer = Renderer
module Texture = Texture
module Sprite = Sprite
module Renderer = struct
include Renderer
include Sprite.Renderer
end
module Asset = struct
include Asset
include Texture.Asset

View File

@ -37,8 +37,7 @@ module Renderer : sig
val post_draw : t -> unit
val clear : t -> color -> unit
val draw_rect : t -> tf:mat2a -> bb:aabb -> fill:color -> unit
val draw_texture : t -> tf:mat2a -> bb:aabb -> ?tint:color -> Texture.t -> unit
(* val draw_sprite : t -> tf:mat2a -> ?tint:color -> ?off:vec2 -> Sprite.t -> unit *)
val draw_sprite : t -> tf:mat2a -> ?tint:color -> ?pos:vec2 -> Sprite.t -> unit
end
module Asset : sig
@ -49,5 +48,5 @@ module Asset : sig
val load_file : string -> string
val load_sexp_conv : string -> (Sexp.t -> 'a) -> 'a
val load_texture : string -> Texture.t
val load_sprite_map : string -> Sprite.map
val load_sprite_map : ?dpi:int -> string -> Sprite.map
end

View File

@ -8,22 +8,37 @@ include (val Ohlog.sublogs logger "Sprite")
type t = {
texture : Texture.t;
clip : aabb;
origin : vec2;
offs : aabb;
}
let make ~texture ~x ~y ~w ~h ~ox ~oy =
let x0 = Float.of_int x
and y0 = Float.of_int y
and x1 = Float.of_int (w - x)
and y1 = Float.of_int (h - x)
and ox = Float.of_int (ox - x)
and oy = Float.of_int (oy - y) in
{
let make ~texture ~pdf ~x ~y ~w ~h ~ox ~oy =
let x0 = Float.of_int x *. pdf
and y0 = Float.of_int y *. pdf
and x1 = Float.of_int (x + w) *. pdf
and y1 = Float.of_int (y + h) *. pdf
and ox0 = Float.of_int (x - ox)
and oy0 = Float.of_int (y - oy)
and ox1 = Float.of_int (x - ox + w)
and oy1 = Float.of_int (y - oy + w)
in {
texture;
clip = aabb x0 y0 x1 y1;
origin = vec2 ox oy;
offs = aabb ox0 oy0 ox1 oy1;
}
module Renderer = struct
let _white = Color.white ()
let _zero = vec2 0.0 0.0
let rect = aabb 0.0 0.0 0.0 0.0
let draw_sprite ren ~tf ?(tint = _white) ?(pos = _zero) { texture; clip; offs } =
rect.x0 <- offs.x0 +. pos.x;
rect.y0 <- offs.y0 +. pos.y;
rect.x1 <- offs.x1 +. pos.x;
rect.y1 <- offs.y1 +. pos.y;
Renderer.draw_texture ren ~tf ~rect ~clip ~tint texture
end
type map = (string, t) Hashtbl.t
let get (map : map) name : t =
@ -31,10 +46,10 @@ let get (map : map) name : t =
with Not_found ->
Format.ksprintf failwith "no sprite %S in sprite map" name
let parse_sprite ~map ~texture = function
let parse_sprite ~map ~texture ~pdf = function
| Sexp.List [Atom name; x; y; w; h; ox; oy] ->
let sprite =
make ~texture
make ~texture ~pdf
~x:(Sexp_conv.int_of_sexp x)
~y:(Sexp_conv.int_of_sexp y)
~w:(Sexp_conv.int_of_sexp w)
@ -46,24 +61,28 @@ let parse_sprite ~map ~texture = function
| sexp ->
Sexp_conv.of_sexp_error "invalid sprite" sexp
let of_sexp ~texture = function
let of_sexp ~texture ?(dpi = 96) = function
| Sexp.List (Atom "map" :: sprite_args) ->
let map = Hashtbl.create (List.length sprite_args * 2) in
List.iter (parse_sprite ~map ~texture) sprite_args;
let pdf = Float.of_int dpi /. 96.0 in
List.iter (parse_sprite ~map ~texture ~pdf) sprite_args;
map
| sexp ->
Sexp_conv.of_sexp_error "invalid sprite map" sexp
module Asset = struct
let load_sprite_map name =
let load_sprite_map ?dpi name =
let tex_path = Format.sprintf "sprites/%s.png" name in
let map_path = Format.sprintf "sprites/%s.map" name in
let texture = Texture.Asset.load_texture tex_path in
let spritemap = Asset.load_sexp_conv map_path (of_sexp ~texture) in
trace (fun m -> m "loaded sprite map %S" name);
let spritemap = Asset.load_sexp_conv map_path (of_sexp ~texture ?dpi) in
debug (fun m -> m "loaded sprite map %S" name);
trace (fun m ->
Hashtbl.iter
(fun k v -> m " %S %a %a" k AABB.pp v.clip Vec2.pp v.origin)
(fun name s ->
m " %S %a %a" name
AABB.pp s.clip
AABB.pp s.offs)
spritemap);
spritemap
end