99 lines
3.1 KiB
C
99 lines
3.1 KiB
C
#include "twn_draw.h"
|
|
#include "twn_draw_c.h"
|
|
#include "twn_engine_context_c.h"
|
|
|
|
#include <stb_ds.h>
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
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);
|
|
}
|