2024-09-16 06:07:01 +00:00
|
|
|
#include "twn_rendering_c.h"
|
2024-09-16 13:17:00 +00:00
|
|
|
#include "twn_rendering.h"
|
|
|
|
#include "twn_engine_context_c.h"
|
|
|
|
#include "twn_camera.h"
|
2024-07-08 00:44:20 +00:00
|
|
|
|
|
|
|
#include <SDL2/SDL.h>
|
2024-07-27 12:10:19 +00:00
|
|
|
#include <stb_ds.h>
|
2024-07-08 00:44:20 +00:00
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
#ifdef EMSCRIPTEN
|
|
|
|
#include <GLES2/gl2.h>
|
|
|
|
#else
|
|
|
|
#include <glad/glad.h>
|
|
|
|
#endif
|
|
|
|
|
2024-07-10 16:15:28 +00:00
|
|
|
#include <stddef.h>
|
2024-07-08 00:44:20 +00:00
|
|
|
#include <tgmath.h>
|
|
|
|
|
|
|
|
|
2024-07-29 12:21:39 +00:00
|
|
|
/* TODO: have a default initialized one */
|
2024-09-23 17:43:16 +00:00
|
|
|
Matrix4 camera_projection_matrix;
|
|
|
|
Matrix4 camera_look_at_matrix;
|
2024-07-29 12:21:39 +00:00
|
|
|
|
|
|
|
|
2024-07-08 00:44:20 +00:00
|
|
|
void render_queue_clear(void) {
|
2024-09-27 18:02:24 +00:00
|
|
|
text_cache_reset_arena(&ctx.text_cache);
|
2024-08-23 02:41:52 +00:00
|
|
|
|
2024-07-08 00:44:20 +00:00
|
|
|
/* since i don't intend to free the queues, */
|
|
|
|
/* it's faster and simpler to just "start over" */
|
|
|
|
/* and start overwriting the existing data */
|
2024-07-16 02:31:54 +00:00
|
|
|
arrsetlen(ctx.render_queue_2d, 0);
|
2024-07-10 16:15:28 +00:00
|
|
|
|
2024-07-14 13:04:12 +00:00
|
|
|
for (size_t i = 0; i < hmlenu(ctx.uncolored_mesh_batches); ++i)
|
|
|
|
arrsetlen(ctx.uncolored_mesh_batches[i].value.primitives, 0);
|
2024-07-08 00:44:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* rectangle */
|
2024-09-23 17:43:16 +00:00
|
|
|
void push_rectangle(Rect rect, Color color) {
|
|
|
|
RectPrimitive rectangle = {
|
2024-07-08 00:44:20 +00:00
|
|
|
.rect = rect,
|
|
|
|
.color = color,
|
|
|
|
};
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
Primitive2D primitive = {
|
2024-07-16 02:31:54 +00:00
|
|
|
.type = PRIMITIVE_2D_RECT,
|
|
|
|
.rect = rectangle,
|
|
|
|
};
|
|
|
|
|
|
|
|
arrput(ctx.render_queue_2d, primitive);
|
2024-07-08 00:44:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-27 12:10:19 +00:00
|
|
|
static void render_2d(void) {
|
2024-09-16 06:07:01 +00:00
|
|
|
use_2d_pipeline();
|
2024-07-08 00:44:20 +00:00
|
|
|
|
2024-07-27 12:10:19 +00:00
|
|
|
const size_t render_queue_len = arrlenu(ctx.render_queue_2d);
|
2024-07-08 00:44:20 +00:00
|
|
|
|
2024-07-27 12:10:19 +00:00
|
|
|
size_t batch_count = 0;
|
2024-07-08 00:44:20 +00:00
|
|
|
|
2024-07-27 12:10:19 +00:00
|
|
|
for (size_t i = 0; i < render_queue_len; ++i) {
|
2024-09-23 17:43:16 +00:00
|
|
|
const Primitive2D *current = &ctx.render_queue_2d[i];
|
2024-07-16 02:31:54 +00:00
|
|
|
|
|
|
|
switch (current->type) {
|
2024-07-27 12:10:19 +00:00
|
|
|
case PRIMITIVE_2D_SPRITE: {
|
2024-09-23 17:43:16 +00:00
|
|
|
const struct SpriteBatch batch =
|
2024-07-27 12:10:19 +00:00
|
|
|
collect_sprite_batch(current, render_queue_len - i);
|
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
/* TODO: what's even the point? just use OR_EQUAL comparison */
|
|
|
|
set_depth_range((double)batch_count / UINT16_MAX, 1.0);
|
2024-07-28 13:06:47 +00:00
|
|
|
render_sprites(current, batch);
|
2024-07-27 12:10:19 +00:00
|
|
|
|
|
|
|
i += batch.size - 1; ++batch_count;
|
2024-07-16 02:31:54 +00:00
|
|
|
break;
|
2024-07-27 12:10:19 +00:00
|
|
|
}
|
2024-07-16 02:31:54 +00:00
|
|
|
case PRIMITIVE_2D_RECT:
|
|
|
|
render_rectangle(¤t->rect);
|
|
|
|
break;
|
|
|
|
case PRIMITIVE_2D_CIRCLE:
|
|
|
|
render_circle(¤t->circle);
|
|
|
|
break;
|
2024-08-23 02:41:52 +00:00
|
|
|
case PRIMITIVE_2D_TEXT:
|
|
|
|
render_text(¤t->text);
|
|
|
|
break;
|
2024-07-16 02:31:54 +00:00
|
|
|
}
|
2024-07-08 00:44:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-09 12:35:54 +00:00
|
|
|
static void render_space(void) {
|
2024-09-16 06:07:01 +00:00
|
|
|
/* nothing to do, abort */
|
|
|
|
/* as space pipeline isn't used we can have fewer changes and initialization costs */
|
|
|
|
if (hmlenu(ctx.uncolored_mesh_batches) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
use_space_pipeline();
|
2024-07-10 16:15:28 +00:00
|
|
|
|
2024-07-14 13:04:12 +00:00
|
|
|
for (size_t i = 0; i < hmlenu(ctx.uncolored_mesh_batches); ++i) {
|
|
|
|
draw_uncolored_space_traingle_batch(&ctx.uncolored_mesh_batches[i].value,
|
|
|
|
ctx.uncolored_mesh_batches[i].key);
|
2024-07-10 16:15:28 +00:00
|
|
|
}
|
2024-07-09 12:35:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-08 00:44:20 +00:00
|
|
|
void render(void) {
|
2024-07-14 13:04:12 +00:00
|
|
|
textures_update_atlas(&ctx.texture_cache);
|
2024-07-10 16:15:28 +00:00
|
|
|
|
2024-07-12 18:10:25 +00:00
|
|
|
/* fit rendering context onto the resizable screen */
|
2024-09-16 13:17:00 +00:00
|
|
|
if (ctx.game.window_size_has_changed) {
|
2024-10-01 00:13:58 +00:00
|
|
|
if ((float)ctx.game.window_w / (float)ctx.game.window_h > (float)(ctx.base_render_width / ctx.base_render_height)) {
|
|
|
|
float ratio = (float)ctx.game.window_h / (float)ctx.base_render_height;
|
|
|
|
int w = (int)((float)ctx.base_render_width * ratio);
|
2024-09-16 06:07:01 +00:00
|
|
|
setup_viewport(
|
2024-09-16 13:17:00 +00:00
|
|
|
ctx.game.window_w / 2 - w / 2,
|
2024-07-27 14:10:08 +00:00
|
|
|
0,
|
|
|
|
w,
|
2024-09-16 13:17:00 +00:00
|
|
|
ctx.game.window_h
|
2024-07-27 14:10:08 +00:00
|
|
|
);
|
|
|
|
} else {
|
2024-10-01 00:13:58 +00:00
|
|
|
float ratio = (float)ctx.game.window_w / (float)ctx.base_render_width;
|
|
|
|
int h = (int)((float)ctx.base_render_height * ratio);
|
2024-09-16 06:07:01 +00:00
|
|
|
setup_viewport(
|
2024-07-27 14:10:08 +00:00
|
|
|
0,
|
2024-09-16 13:17:00 +00:00
|
|
|
ctx.game.window_h / 2 - h / 2,
|
|
|
|
ctx.game.window_w,
|
2024-07-27 14:10:08 +00:00
|
|
|
h
|
|
|
|
);
|
|
|
|
}
|
2024-07-12 18:10:25 +00:00
|
|
|
}
|
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
clear_draw_buffer();
|
|
|
|
render_space();
|
2024-09-26 18:02:56 +00:00
|
|
|
render_skybox(); /* after space, as to use depth buffer for early rejection */
|
2024-09-16 06:07:01 +00:00
|
|
|
render_2d();
|
|
|
|
swap_buffers();
|
2024-07-08 00:44:20 +00:00
|
|
|
}
|
2024-07-29 12:21:39 +00:00
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void set_camera(const Camera *const camera) {
|
2024-07-29 12:21:39 +00:00
|
|
|
/* TODO: skip recaulculating if it's the same? */
|
2024-07-30 15:05:05 +00:00
|
|
|
camera_projection_matrix = camera_perspective(camera);
|
2024-09-16 06:07:01 +00:00
|
|
|
camera_look_at_matrix = camera_look_at(camera);
|
2024-07-29 12:21:39 +00:00
|
|
|
}
|