#include "twn_draw.h" #include "twn_draw_c.h" #include "twn_engine_context_c.h" #include #include #include void draw_rectangle(Rect rect, Color color) { RectPrimitive rectangle = { .rect = rect, .color = color, }; Primitive2D primitive = { .type = PRIMITIVE_2D_RECT, .rect = rectangle, }; arrput(ctx.render_queue_2d, primitive); } struct QuadBatch collect_rect_batch(const Primitive2D primitives[], size_t len) { SDL_assert(primitives[0].type == PRIMITIVE_2D_RECT); SDL_assert(primitives && len != 0); struct QuadBatch batch = { .mode = primitives[0].rect.color.a == 255 ? TEXTURE_MODE_OPAQUE : TEXTURE_MODE_GHOSTLY, .constant_colored = true, }; const uint32_t uniform_color = *(const uint32_t *)(void const *)&primitives[0].rect.color; /* batch size is clamped so that reallocated short indices could be used */ if (len >= QUAD_ELEMENT_BUFFER_LENGTH) len = QUAD_ELEMENT_BUFFER_LENGTH; for (size_t i = 0; i < len; ++i) { const Primitive2D *const current = &primitives[i]; /* don't touch things other than rectangles */ if (current->type != PRIMITIVE_2D_RECT) break; /* only collect the same blend modes */ if ((current->rect.color.a == 255 ? TEXTURE_MODE_OPAQUE : TEXTURE_MODE_GHOSTLY) != batch.mode) break; /* if all are modulated the same we can skip sending the color data */ if (*(const uint32_t *)(void const *)¤t->rect.color != uniform_color) batch.constant_colored = false; ++batch.size; } return batch; } /* assumes that orthogonal matrix setup is done already */ void render_rect_batch(const Primitive2D primitives[], const struct QuadBatch batch) { SDL_assert(primitives && batch.size != 0); SDL_assert(primitives[0].type == PRIMITIVE_2D_RECT); /* single vertex array is used for every batch with NULL glBufferData() trick at the end */ VertexBuffer const vertex_array = get_scratch_vertex_array(); use_texture_mode(batch.mode); /* vertex population over a vertex buffer builder interface */ { VertexBufferBuilder payload = build_vertex_buffer(vertex_array, get_quad_payload_size(batch) * batch.size); for (size_t i = 0; i < batch.size; ++i) { /* render opaques front to back, to gain benefit of an early z rejection */ const size_t cur = batch.mode == TEXTURE_MODE_GHOSTLY ? i : batch.size - i - 1; const RectPrimitive rect = primitives[cur].rect; Vec2 v0 = { rect.rect.x, rect.rect.y }; Vec2 v1 = { rect.rect.x, rect.rect.y + rect.rect.h }; Vec2 v2 = { rect.rect.x + rect.rect.w, rect.rect.y + rect.rect.h }; Vec2 v3 = { rect.rect.x + rect.rect.w, rect.rect.y }; push_quad_payload_to_vertex_buffer_builder( batch, &payload, v0, v1, v2, v3, (Vec2){0}, (Vec2){0}, (Vec2){0}, (Vec2){0}, rect.color); } } finally_render_quads(primitives, batch, vertex_array); }