From 5a83381ae168e494cdadd236f796331c7c55c0af Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Sat, 15 Feb 2025 22:42:14 +0300 Subject: [PATCH] twn_draw: texture_region option for draw_billboard() --- apps/demos/scenery/scenes/ingame.c | 1 + include/twn_draw.h | 12 ++++++------ share/twn_api.json | 1 + src/rendering/twn_billboards.c | 29 ++++++++++++++++++++++++----- src/rendering/twn_draw_c.h | 2 ++ 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/apps/demos/scenery/scenes/ingame.c b/apps/demos/scenery/scenes/ingame.c index 5b80213..6a0f063 100644 --- a/apps/demos/scenery/scenes/ingame.c +++ b/apps/demos/scenery/scenes/ingame.c @@ -179,6 +179,7 @@ static void draw_terrain(SceneIngame *scn) { draw_billboard("/assets/grasses/10.png", (Vec3){ (float)x, d0 + 0.15f, (float)y }, (Vec2){0.3f, 0.3f}, + NULL, (Color){255, 255, 255, 255}, true); } } diff --git a/include/twn_draw.h b/include/twn_draw.h index 6365b38..06aec43 100644 --- a/include/twn_draw.h +++ b/include/twn_draw.h @@ -66,7 +66,6 @@ TWN_API void draw_triangle(char const *texture, Color c1, /* optional, default: all 255 */ Color c2); /* optional, default: all 255 */ -/* TODO: double sided option */ TWN_API void draw_quad(char const *texture, Vec3 v0, /* upper-left */ Vec3 v1, /* bottom-left */ @@ -75,11 +74,12 @@ TWN_API void draw_quad(char const *texture, Rect texture_region, Color color); /* optional, default: all 255 */ -TWN_API void draw_billboard(const char *texture, - Vec3 position, - Vec2 size, - Color color, /* optional, default: all 255 */ - bool cylindrical); /* optional, default: false */ +TWN_API void draw_billboard(char const *texture, + Vec3 position, + Vec2 size, + Rect const *texture_region, /* optional, default: NULL */ + Color color, /* optional, default: all 255 */ + bool cylindrical); /* optional, default: false */ TWN_API void draw_camera_2d(Vec2 position, /* optional, default: (0, 0) */ float rotation, /* optional, default: 0 */ diff --git a/share/twn_api.json b/share/twn_api.json index 447ebfb..5ea4b2f 100644 --- a/share/twn_api.json +++ b/share/twn_api.json @@ -180,6 +180,7 @@ { "name": "texture", "type": "char *" }, { "name": "position", "type": "Vec3" }, { "name": "size", "type": "Vec2" }, + { "name": "texture_region", "type": "Rect *", "default": {} }, { "name": "color", "type": "Color", "default": { "r": 255, "g": 255, "b": 255, "a": 255 } }, { "name": "cylindrical", "type": "bool", "default": false } ] diff --git a/src/rendering/twn_billboards.c b/src/rendering/twn_billboards.c index fe7b92a..ec4ec4d 100644 --- a/src/rendering/twn_billboards.c +++ b/src/rendering/twn_billboards.c @@ -9,9 +9,10 @@ #include -void draw_billboard(const char *texture, +void draw_billboard(char const *texture, Vec3 position, Vec2 size, + Rect const *texture_region, Color color, bool cylindrical) { @@ -30,8 +31,12 @@ void draw_billboard(const char *texture, .cylindrical = cylindrical, .position = position, .size = size, + .texture_region_opt_set = texture_region != NULL, }; + if (texture_region) + billboard.texture_region_opt = *texture_region; + struct SpaceBillboard *billboards = (struct SpaceBillboard *)(void *)batch_p->value.primitives; arrpush(billboards, billboard); @@ -81,10 +86,10 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch, const float xr = srcrect.x / dims.w; const float yr = srcrect.y / dims.h; - const Vec2 uv0 = { xr, yr }; - const Vec2 uv1 = { xr, yr + hr }; - const Vec2 uv2 = { xr + wr, yr + hr }; - const Vec2 uv3 = { xr + wr, yr }; + const Vec2 uv0c = { xr, yr }; + const Vec2 uv1c = { xr, yr + hr }; + const Vec2 uv2c = { xr + wr, yr + hr }; + const Vec2 uv3c = { xr + wr, yr }; for (size_t batch_n = 0; batch_n <= (primitives_len - 1) / QUAD_ELEMENT_BUFFER_LENGTH; batch_n++) { @@ -107,6 +112,20 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch, b = vec3_mul(right_minus_up, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x })); } + Vec2 uv0, uv1, uv2, uv3; + if (billboard.texture_region_opt_set) { + uv0 = (Vec2){ (srcrect.x + billboard.texture_region_opt.x) / dims.w, + (srcrect.y + billboard.texture_region_opt.y) / dims.h }; + uv1 = (Vec2){ (srcrect.x + billboard.texture_region_opt.x) / dims.w, + (srcrect.y + billboard.texture_region_opt.y + billboard.texture_region_opt.h) / dims.h }; + uv2 = (Vec2){ (srcrect.x + billboard.texture_region_opt.x + billboard.texture_region_opt.w) / dims.w, + (srcrect.y + billboard.texture_region_opt.y + billboard.texture_region_opt.h) / dims.h }; + uv3 = (Vec2){ (srcrect.x + billboard.texture_region_opt.x + billboard.texture_region_opt.w) / dims.w, + (srcrect.y + billboard.texture_region_opt.y) / dims.h }; + } else { + uv0 = uv0c; uv1 = uv1c; uv2 = uv2c; uv3 = uv3c; + } + struct ElementIndexedBillboard const payload = { /* flat shading is assumed, so we can skip setting the duplicates */ .c0 = billboard.color, diff --git a/src/rendering/twn_draw_c.h b/src/rendering/twn_draw_c.h index 72bfffc..107d638 100644 --- a/src/rendering/twn_draw_c.h +++ b/src/rendering/twn_draw_c.h @@ -121,6 +121,8 @@ typedef struct SpaceBillboard { Vec3 position; Vec2 size; Color color; + m_option_list( + Rect, texture_region ) // TextureKey texture; /* is assumed from other places */ bool cylindrical; } SpaceBillboard;