From 2996e8ecaf4a42d6398cf7a0445070a19851a03a Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Tue, 3 Jun 2025 22:03:11 +0200 Subject: [PATCH] Sort entities by render type, bind buffers less often --- game/src/entity/#entity.h# | 22 ++++++++++++++++++++++ game/src/entity/.#entity.h | 1 + game/src/entity/entity.h | 9 ++++++++- game/src/entity/manager.c | 9 ++++++++- game/src/entity/manager.h | 29 ++++++++++++++++++++++++++++- game/src/entity/meshes.c | 6 +++++- game/src/entity/meshes.h | 1 + 7 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 game/src/entity/#entity.h# create mode 120000 game/src/entity/.#entity.h diff --git a/game/src/entity/#entity.h# b/game/src/entity/#entity.h# new file mode 100644 index 0000000..615d1b2 --- /dev/null +++ b/game/src/entity/#entity.h# @@ -0,0 +1,22 @@ +#pragma once + +#include + +/* There should also be an entity mesh type of QUAD1, as billboards + always face the camera, thus the back side need not be rendered. */ + +typedef struct Entity +{ + enum { MESH_QUAD2, MESH_QUAD_X } mesh_type; + enum { ORIGIN_CENTER, ORIGIN_BOTTOM } origin; + enum { RENDER_NORMAL, RENDER_BILLBOARD_Y, RENDER_BILLBOARD } render_type; + + void *userdata; + + void (*on_tick) (struct Entity *self); + + vec3 position; + float rotation; + vec3 scale; /* Unused for now. */ + char *texture; +} Entity; diff --git a/game/src/entity/.#entity.h b/game/src/entity/.#entity.h new file mode 120000 index 0000000..9eac588 --- /dev/null +++ b/game/src/entity/.#entity.h @@ -0,0 +1 @@ +emssej@Komputer-Ze-Smieci.2233:1748755544 \ No newline at end of file diff --git a/game/src/entity/entity.h b/game/src/entity/entity.h index 615d1b2..65299eb 100644 --- a/game/src/entity/entity.h +++ b/game/src/entity/entity.h @@ -5,11 +5,18 @@ /* There should also be an entity mesh type of QUAD1, as billboards always face the camera, thus the back side need not be rendered. */ +typedef enum EntityRenderType + { + RENDER_NORMAL, + RENDER_BILLBOARD, + RENDER_BILLBOARD_Y + } EntityRenderType; + typedef struct Entity { enum { MESH_QUAD2, MESH_QUAD_X } mesh_type; enum { ORIGIN_CENTER, ORIGIN_BOTTOM } origin; - enum { RENDER_NORMAL, RENDER_BILLBOARD_Y, RENDER_BILLBOARD } render_type; + EntityRenderType render_type; void *userdata; diff --git a/game/src/entity/manager.c b/game/src/entity/manager.c index 451e2fc..c6b18c4 100644 --- a/game/src/entity/manager.c +++ b/game/src/entity/manager.c @@ -10,6 +10,8 @@ EntityMesh mesh_quad2, mesh_quad_x; extern GameState game_state; extern Resources resources; +unsigned int last_type = -1; + void EntityManager_init () { @@ -81,7 +83,6 @@ em_render_internal (gpointer data, gpointer userdata) case RENDER_BILLBOARD_Y: /* It's not quite a "real" billboard, but the effect is much better on the eye. */ - vec3 delta; glm_vec3_sub (game_state.camera.position, entity->position, delta); delta[1] = 0.0; @@ -107,7 +108,13 @@ em_render_internal (gpointer data, gpointer userdata) glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, R_TEXGET (entity->texture)); + + if (entity->mesh_type != last_type) + { + EntityMesh_bind (&to_render); + } + last_type = entity->mesh_type; EntityMesh_render (&to_render); } diff --git a/game/src/entity/manager.h b/game/src/entity/manager.h index 80db2f1..08f635e 100644 --- a/game/src/entity/manager.h +++ b/game/src/entity/manager.h @@ -9,7 +9,34 @@ #include "../resources.h" #include "../state.h" -#define EM_ENTADD(entity) (g_sequence_append (entity_manager, entity)); +#define EM_ENTADD(entity) (g_sequence_insert_sorted (entity_manager, entity, em_compare, NULL)); + +static inline int +em_compare (gconstpointer a, gconstpointer b, gpointer userdata) +/* This function is used to sort Entities by their mesh type, so that + diferrent buffers aren't bound every single frame. */ +{ + UNUSED (userdata); + const Entity *entity1 = a; + const Entity *entity2 = b; + + if (entity1->mesh_type == entity2->mesh_type) + { + return 0; + } + + if (entity1->mesh_type == MESH_QUAD_X && entity2->mesh_type == MESH_QUAD2) + { + return -1; + } + + if (entity1->mesh_type == MESH_QUAD2 && entity2->mesh_type == MESH_QUAD_X) + { + return 1; + } + + return (int) entity1->mesh_type - (int) entity2->mesh_type; +} void EntityManager_init (); void EntityManager_tick (); diff --git a/game/src/entity/meshes.c b/game/src/entity/meshes.c index 7e43710..8a127a4 100644 --- a/game/src/entity/meshes.c +++ b/game/src/entity/meshes.c @@ -5,7 +5,7 @@ extern GameFlags game_flags; void -EntityMesh_render (EntityMesh *mesh) +EntityMesh_bind (EntityMesh *mesh) { glBindBuffer (GL_ARRAY_BUFFER, mesh->pbo); glEnableVertexAttribArray (0); @@ -16,7 +16,11 @@ EntityMesh_render (EntityMesh *mesh) glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); +} +void +EntityMesh_render (EntityMesh *mesh) +{ if (game_flags.wireframe_enabled) { glDrawElements (GL_LINES, mesh->indices_len, GL_UNSIGNED_INT, 0); diff --git a/game/src/entity/meshes.h b/game/src/entity/meshes.h index 08329aa..0959c8d 100644 --- a/game/src/entity/meshes.h +++ b/game/src/entity/meshes.h @@ -13,6 +13,7 @@ typedef struct EntityMesh unsigned int ebo; } EntityMesh; +void EntityMesh_bind (EntityMesh *mesh); void EntityMesh_render (EntityMesh *mesh); EntityMesh EntityMesh_make_quad2 (); EntityMesh EntityMesh_make_quad_x ();