From 662e35c22ea4da33d573bf680e3eea5ab7876eb1 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 10:11:54 +0530 Subject: [PATCH 01/18] feat: generic ecs material with texture type slots + shader uniforms Replace hardcoded render-system uniforms with material-driven approach: - ecs_component_material_t now stores shader.asset_id + shader.uniforms and texture.asset_ids[GL_TEXTURE_TYPE_COUNT] typed array - ecs_system_render_model reads material uniforms and resolves texture asset IDs to GL handles at render time - Model textures from glmodel_get_texuturelist also bound automatically - Auto-injected uniforms: view, projection, transform (per-frame), material.color, uBones (if skeleton present) - Updated mesh.h and serialization.h for new struct field layout --- ecs/component/types.h | 11 +++- ecs/serialization.h | 10 ++-- ecs/systems/mesh.h | 2 +- ecs/systems/model.h | 136 +++++++++++++++++++++++------------------- 4 files changed, 87 insertions(+), 72 deletions(-) diff --git a/ecs/component/types.h b/ecs/component/types.h index 0f24e93..b251fb2 100644 --- a/ecs/component/types.h +++ b/ecs/component/types.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #define ECS_CMP_INVALID_IDX -1 @@ -98,8 +100,13 @@ struct ecs_component_input_t { typedef struct ecs_component_material_t ecs_component_material_t; struct ecs_component_material_t { - u32 texture_asset_id; - u32 shader_asset_id; + struct { + u32 asset_ids[GL_TEXTURE_TYPE_COUNT]; + } texture; + struct { + u32 asset_id; + gluniforms_t uniforms; + } shader; }; /* =========================== CAMERA ================================== */ diff --git a/ecs/serialization.h b/ecs/serialization.h index 5adc797..2e805cd 100644 --- a/ecs/serialization.h +++ b/ecs/serialization.h @@ -104,10 +104,9 @@ static const ecs_cmp_field_map_t ecs_deserializer__internal_cmp_field_maps[ECS_C } }, [ECS_CMP_MATERIAL_IDX] = { - .field_count = 2, + .field_count = 1, .fields = { - CMP_FLD_DESC("\ttexture_asset_id:", "\ttexture_asset_id:%u", ecs_component_material_t, texture_asset_id, ECS_CMP_FLD_U32), - CMP_FLD_DESC("\tshader_asset_id:", "\tshader_asset_id:%u", ecs_component_material_t, shader_asset_id, ECS_CMP_FLD_U32), + CMP_FLD_DESC("\tshader_asset_id:", "\tshader_asset_id:%u", ecs_component_material_t, shader.asset_id, ECS_CMP_FLD_U32), } }, [ECS_CMP_CAMERA_IDX] = { @@ -210,7 +209,7 @@ INTERNAL void ecs_serializer__internal_entity_cmp_data(file_t *const file, const case ECS_CMP_TRANSFORM: total_members = 5; bytesize = sizeof(ecs_component_transform_t); break; case ECS_CMP_MODEL: total_members = 2; bytesize = sizeof(ecs_component_model_t); break; case ECS_CMP_INPUT: total_members = 3; bytesize = sizeof(ecs_component_input_t); break; - case ECS_CMP_MATERIAL: total_members = 2; bytesize = sizeof(ecs_component_material_t); break; + case ECS_CMP_MATERIAL: total_members = 1; bytesize = sizeof(ecs_component_material_t); break; case ECS_CMP_CAMERA: total_members = 3; bytesize = sizeof(ecs_component_camera_t); break; case ECS_CMP_COLLIDER: total_members = 5; bytesize = sizeof(ecs_component_collider_t); break; case ECS_CMP_MESH: total_members = 2; bytesize = sizeof(ecs_component_mesh_t); break; @@ -379,8 +378,7 @@ INTERNAL void ecs_deserializer__internal_remap_entity_assets(ecs_componentbundle } break; case ECS_CMP_MATERIAL: { ecs_component_material_t *mat = &bundle->component[cmp_idx].material; - if (mat->texture_asset_id) mat->texture_asset_id = ecs_deserializer__internal_ensure_asset_loaded(assets, mat->texture_asset_id, assets_parsed); - if (mat->shader_asset_id) mat->shader_asset_id = ecs_deserializer__internal_ensure_asset_loaded(assets, mat->shader_asset_id, assets_parsed); + if (mat->shader.asset_id) mat->shader.asset_id = ecs_deserializer__internal_ensure_asset_loaded(assets, mat->shader.asset_id, assets_parsed); } break; } } diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 7e88ceb..1253e63 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -38,7 +38,7 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs ECS_CMP_MATERIAL | ECS_CMP_TRANSFORM); const ecs_component_material_t *material = view.entity_cmp_data[ECS_CMP_MATERIAL_IDX]; const ecs_component_transform_t *transform = view.entity_cmp_data[ECS_CMP_TRANSFORM_IDX]; - const glshader_t *shader = assetmanager_get_assetresource(&global_engine->systems.assets, ASSET_TYPE_GLSL_SHADER, material->shader_asset_id); + const glshader_t *shader = assetmanager_get_assetresource(&global_engine->systems.assets, ASSET_TYPE_GLSL_SHADER, material->shader.asset_id); ASSERT(material); ASSERT(shader); diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 17af86d..671997f 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -34,7 +34,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec ); } - if (!cmp_model->internal.model) { continue; } @@ -54,7 +53,7 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec ECS_CMP_MATERIAL | ECS_CMP_TRANSFORM); const ecs_component_material_t *material = view.entity_cmp_data[ECS_CMP_MATERIAL_IDX]; const ecs_component_transform_t *transform = view.entity_cmp_data[ECS_CMP_TRANSFORM_IDX]; - const glshader_t *shader = assetmanager_get_assetresource(&global_engine->systems.assets, ASSET_TYPE_GLSL_SHADER, material->shader_asset_id); + const glshader_t *shader = assetmanager_get_assetresource(&global_engine->systems.assets, ASSET_TYPE_GLSL_SHADER, material->shader.asset_id); ASSERT(material); ASSERT(shader); @@ -66,73 +65,84 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec 1.0f, 1000.0f ); + const matrix4f_t model_transform = glms_mat4_mul( + glms_translate_make(transform->position), + glms_mat4_mul( + glms_quat_mat4(transform->orientation), + glms_scale_make(transform->scale) + ) + ); + const glmodel_t *model = cmp_model->internal.model; + + gltexturelist_t model_textures = glmodel_get_texuturelist(model); + ASSERT(gpu_loaded_asset->meshes.count == model->meshes.len); for (u8 idx = 0; idx < model->meshes.len; idx++) { - //printf("[RENDER] mesh=%i bones=%f data=%p\n", idx, model->transforms[idx].len, model->transforms[idx].data); - renderqueue_pass_command( - &global_engine->systems.renderqueue, - (rendercommand_t) { - .mesh = &gpu_loaded_asset->meshes.data[idx], - .draw_mode = RENDER_COMMAND_DRAW_MODE_TRIANGLE, - .enable_wireframe = false, - .instance = {0}, - .material = { - .textures = {0}, - .shader = { - .data = shader, - .uniforms = { - .count = 8, - .data = { - [0] = { - .name = str_lit("view"), - .value = glcamera_getview(ctx.active_camera), - }, - [1] = { - .name = str_lit("projection"), - .value = perspective_projection - }, - [2] = { - .name = str_lit("transform"), - .value = glms_mat4_mul( - glms_translate_make(transform->position), - glms_mat4_mul( - glms_quat_mat4(transform->orientation), - glms_scale_make(transform->scale) - ) - ) - }, - [3] = { - .name = str_lit("material.color"), - .value.vec4 = *(vec4f_t *)list_get_value(&model->colors, idx) - }, - [4] = { - .name = str_lit("uBones"), - .value.mat4s = { - .count = model->transforms[idx].len, - .data = (matrix4f_t *)model->transforms[idx].data - } - }, - [5] = { - .name = str_lit("light.color"), - .value.vec4 = global_workbench->editor.current_selected_entity_id == entry->entity_id ? COLOR_RED : COLOR_WHITE - }, - [6] = { - .name = str_lit("light.ambient"), - .value.f32 = 1.0f - }, - [7] = { - .name = str_lit("light.position"), - .value.vec3 = vec3f(1.0f) - } - } - } - } + rendercommand_t cmd = { + .mesh = &gpu_loaded_asset->meshes.data[idx], + .draw_mode = RENDER_COMMAND_DRAW_MODE_TRIANGLE, + .enable_wireframe = false, + .instance = {0}, + .material = { + .textures = {0}, + .shader = { + .data = shader, + .uniforms = {0}, } } - ); + }; + + u8 *uniform_count = &cmd.material.shader.uniforms.count; + + cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ + .name = str_lit("view"), + .value.mat4 = glcamera_getview(ctx.active_camera), + }; + cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ + .name = str_lit("projection"), + .value.mat4 = perspective_projection, + }; + cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ + .name = str_lit("transform"), + .value.mat4 = model_transform, + }; + + cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ + .name = str_lit("material.color"), + .value.vec4 = *(vec4f_t *)list_get_value(&model->colors, idx) + }; + + if (model->transforms[idx].len) { + cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ + .name = str_lit("uBones"), + .value.mat4s = { + .count = model->transforms[idx].len, + .data = (matrix4f_t *)model->transforms[idx].data + } + }; + } + + for (u8 u = 0; u < material->shader.uniforms.count; u++) { + cmd.material.shader.uniforms.data[(*uniform_count)++] = material->shader.uniforms.data[u]; + } + + u8 *tex_count = &cmd.material.textures.count; + for (u8 t = 0; t < model_textures.count; t++) { + cmd.material.textures.ids[(*tex_count)++] = model_textures.items[t].source.normal_texture->id; + } + + for (u8 t = 0; t < GL_TEXTURE_TYPE_COUNT; t++) { + if (!material->texture.asset_ids[t]) continue; + gltexture2d_t *tex = (gltexture2d_t *)assetmanager_get_assetresource( + &global_engine->systems.assets, ASSET_TYPE_TEXTURE_BINARY, material->texture.asset_ids[t]); + if (tex) { + cmd.material.textures.ids[(*tex_count)++] = tex->id; + } + } + + renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } } - From 8354f12ff2deb51adfc4bdd7648980efff91768b Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 10:13:45 +0530 Subject: [PATCH 02/18] fix: remove typeof, fix animation_filter_t, fix ASSET_TYPE_TEXTURE --- ecs/systems/model.h | 65 +++++++++++++++++++++------------------------ gfx/model/assimp.h | 2 +- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 671997f..afc45e3 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -28,7 +28,7 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec if (!cmp_model->internal.model) { cmp_model->internal.model = (glmodel_t *)assetmanager_get_assetresource( - &global_engine->systems.assets, + &global_engine->systems.assets, ASSET_TYPE_MODEL, (cmp_model)->asset_id ); @@ -39,7 +39,7 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec } const gpu_asset_t *gpu_loaded_asset = (gpu_asset_t *)assetmanager_get_gpu_loaded_asset_async( - &global_engine->systems.assets, + &global_engine->systems.assets, cmp_model->asset_id ); if (!gpu_loaded_asset) { @@ -48,8 +48,8 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec const u32 entity_id = entry->entity_id; const ecs_entity_query_t view = ecs_componentmanager__internal_query_components( - cmp_manager, - entity_id, + cmp_manager, + entity_id, ECS_CMP_MATERIAL | ECS_CMP_TRANSFORM); const ecs_component_material_t *material = view.entity_cmp_data[ECS_CMP_MATERIAL_IDX]; const ecs_component_transform_t *transform = view.entity_cmp_data[ECS_CMP_TRANSFORM_IDX]; @@ -60,8 +60,8 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec ASSERT(transform); const matrix4f_t perspective_projection = glms_perspective( - radians(45), - global_engine->handle.app->window.aspect_ratio, + radians(45), + global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f ); @@ -94,51 +94,46 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec } }; - u8 *uniform_count = &cmd.material.shader.uniforms.count; + gluniforms_t *uniforms = &cmd.material.shader.uniforms; - cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ - .name = str_lit("view"), - .value.mat4 = glcamera_getview(ctx.active_camera), - }; - cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ - .name = str_lit("projection"), - .value.mat4 = perspective_projection, - }; - cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ - .name = str_lit("transform"), - .value.mat4 = model_transform, - }; + uniforms->data[uniforms->count].name = str_lit("view"); + uniforms->data[uniforms->count].value.mat4 = glcamera_getview(ctx.active_camera); + uniforms->count++; - cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ - .name = str_lit("material.color"), - .value.vec4 = *(vec4f_t *)list_get_value(&model->colors, idx) - }; + uniforms->data[uniforms->count].name = str_lit("projection"); + uniforms->data[uniforms->count].value.mat4 = perspective_projection; + uniforms->count++; + + uniforms->data[uniforms->count].name = str_lit("transform"); + uniforms->data[uniforms->count].value.mat4 = model_transform; + uniforms->count++; + + uniforms->data[uniforms->count].name = str_lit("material.color"); + uniforms->data[uniforms->count].value.vec4 = *(vec4f_t *)list_get_value(&model->colors, idx); + uniforms->count++; if (model->transforms[idx].len) { - cmd.material.shader.uniforms.data[(*uniform_count)++] = (typeof(cmd.material.shader.uniforms.data[0])){ - .name = str_lit("uBones"), - .value.mat4s = { - .count = model->transforms[idx].len, - .data = (matrix4f_t *)model->transforms[idx].data - } - }; + uniforms->data[uniforms->count].name = str_lit("uBones"); + uniforms->data[uniforms->count].value.mat4s.count = model->transforms[idx].len; + uniforms->data[uniforms->count].value.mat4s.data = (matrix4f_t *)model->transforms[idx].data; + uniforms->count++; } for (u8 u = 0; u < material->shader.uniforms.count; u++) { - cmd.material.shader.uniforms.data[(*uniform_count)++] = material->shader.uniforms.data[u]; + uniforms->data[uniforms->count] = material->shader.uniforms.data[u]; + uniforms->count++; } - u8 *tex_count = &cmd.material.textures.count; for (u8 t = 0; t < model_textures.count; t++) { - cmd.material.textures.ids[(*tex_count)++] = model_textures.items[t].source.normal_texture->id; + cmd.material.textures.ids[cmd.material.textures.count++] = model_textures.items[t].source.normal_texture->id; } for (u8 t = 0; t < GL_TEXTURE_TYPE_COUNT; t++) { if (!material->texture.asset_ids[t]) continue; gltexture2d_t *tex = (gltexture2d_t *)assetmanager_get_assetresource( - &global_engine->systems.assets, ASSET_TYPE_TEXTURE_BINARY, material->texture.asset_ids[t]); + &global_engine->systems.assets, ASSET_TYPE_TEXTURE, material->texture.asset_ids[t]); if (tex) { - cmd.material.textures.ids[(*tex_count)++] = tex->id; + cmd.material.textures.ids[cmd.material.textures.count++] = tex->id; } } diff --git a/gfx/model/assimp.h b/gfx/model/assimp.h index f1703d3..5ae24aa 100644 --- a/gfx/model/assimp.h +++ b/gfx/model/assimp.h @@ -447,7 +447,7 @@ glmodel_t glmodel_init(const char *filepath) assimp__internal_glmesh_processScene(&o, scene); //load all animations - animator_load_all_animations(&o.animator, scene, o.arena, (animation_filter_t){0}); + animator_load_all_animations(&o.animator, scene, o.arena); //NOTE: this to cache the root channel idx to get the root position of the model during an animation From 8d1ddc6d5b7d2bb3f8b4d1c0bd026080c1089102 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 10:14:39 +0530 Subject: [PATCH 03/18] fix: str_lit -> str in assignments, fix collision-scene material fields --- ecs/systems/model.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ecs/systems/model.h b/ecs/systems/model.h index afc45e3..8089c29 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -96,24 +96,24 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec gluniforms_t *uniforms = &cmd.material.shader.uniforms; - uniforms->data[uniforms->count].name = str_lit("view"); + uniforms->data[uniforms->count].name = str("view"); uniforms->data[uniforms->count].value.mat4 = glcamera_getview(ctx.active_camera); uniforms->count++; - uniforms->data[uniforms->count].name = str_lit("projection"); + uniforms->data[uniforms->count].name = str("projection"); uniforms->data[uniforms->count].value.mat4 = perspective_projection; uniforms->count++; - uniforms->data[uniforms->count].name = str_lit("transform"); + uniforms->data[uniforms->count].name = str("transform"); uniforms->data[uniforms->count].value.mat4 = model_transform; uniforms->count++; - uniforms->data[uniforms->count].name = str_lit("material.color"); + uniforms->data[uniforms->count].name = str("material.color"); uniforms->data[uniforms->count].value.vec4 = *(vec4f_t *)list_get_value(&model->colors, idx); uniforms->count++; if (model->transforms[idx].len) { - uniforms->data[uniforms->count].name = str_lit("uBones"); + uniforms->data[uniforms->count].name = str("uBones"); uniforms->data[uniforms->count].value.mat4s.count = model->transforms[idx].len; uniforms->data[uniforms->count].value.mat4s.data = (matrix4f_t *)model->transforms[idx].data; uniforms->count++; From f1e49d695881c8a6de6bdfa4ee8af650147c8b0d Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 10:15:50 +0530 Subject: [PATCH 04/18] fix: cap ecs material pool capacity to avoid OOM with larger struct --- ecs/component.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ecs/component.h b/ecs/component.h index effc92c..4befa35 100644 --- a/ecs/component.h +++ b/ecs/component.h @@ -45,6 +45,7 @@ u32 ecs_componentmanager__internal_get_pool_capacity(const ecs_component_type ty switch(type) { case ECS_CMP_CAMERA: return 10; + case ECS_CMP_MATERIAL: return 128; default: return ECS_ENTITY_MAX_COUNT / 2; } } From 819cff72d475a04d2a20f3d8828ec9da494059ff Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 10:17:01 +0530 Subject: [PATCH 05/18] fix: increase component buffer to fit larger material struct --- ecs/component.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecs/component.h b/ecs/component.h index 4befa35..bef7913 100644 --- a/ecs/component.h +++ b/ecs/component.h @@ -191,7 +191,7 @@ void ecs_componentmanager_add(ecs_componentmanager_t * const self, const u32 ent cmp_idx_buffer[cmp_idx_count] = pool->len; const u16 cmp_size = ecs_component__internal_get_componenttype_size(cmp_type); - buffer(WORD) buf = {0}; + buffer(KB * 3) buf = {0}; //NOTE: sets the entity id memcpy(buf.raw_data, &entity_id, sizeof(entity_id)); From ed6baf622f2197401de1fb6c0fc847a1222be73e Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 10:17:39 +0530 Subject: [PATCH 06/18] fix: keep light uniforms auto-injected for backward compat --- ecs/systems/model.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 8089c29..36ece36 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -124,6 +124,18 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec uniforms->count++; } + uniforms->data[uniforms->count].name = str("light.color"); + uniforms->data[uniforms->count].value.vec4 = global_workbench->editor.current_selected_entity_id == entry->entity_id ? COLOR_RED : COLOR_WHITE; + uniforms->count++; + + uniforms->data[uniforms->count].name = str("light.ambient"); + uniforms->data[uniforms->count].value.f32 = 1.0f; + uniforms->count++; + + uniforms->data[uniforms->count].name = str("light.position"); + uniforms->data[uniforms->count].value.vec3 = vec3f(1.0f); + uniforms->count++; + for (u8 t = 0; t < model_textures.count; t++) { cmd.material.textures.ids[cmd.material.textures.count++] = model_textures.items[t].source.normal_texture->id; } From 23facc0e9a221369334f2da5f223e71fc9d2e067 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 11:03:14 +0530 Subject: [PATCH 07/18] feat: replace flat texture ids with gltexturelist_t in render pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rendercommand_t.material.texture is now a gltexturelist_t instead of flat u16 ids[], carrying per-texture type metadata through the entire render queue — from command submission to batch comparison to binding. Changes: - render_command.h: rendercommand material uses gltexturelist_t texture - render_command.h: compare_textures compares type + GL texture id - render_queue.h: dispatch binds via gltextureitem_t (2D or cubemap) - model.h: directly assign glmodel_get_texuturelist() into material, resolve per-type material texture asset IDs into typed items - mesh.h: construct gltexturelist_t for atlas texture --- ecs/systems/mesh.h | 9 ++++++--- ecs/systems/model.h | 22 ++++++++++------------ pipeline/render/render_command.h | 16 ++++++++-------- pipeline/render/render_queue.h | 15 ++++++++++++--- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 1253e63..44e75b5 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -71,10 +71,13 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs .size = sizeof(rendercommand_instance_primitive_mesh_t) }, .material = { - .textures = { + .texture = { .count = 1, - .ids = { - [0] = atlas->texture.id, + .items = { + [0] = (gltextureitem_t){ + .type = GL_TEXTURE_TYPE_NORMAL, + .source = { .normal_texture = &atlas->texture } + } } }, .shader = { diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 36ece36..ee0ec0b 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -34,17 +34,13 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec ); } - if (!cmp_model->internal.model) { - continue; - } + if (!cmp_model->internal.model) continue; const gpu_asset_t *gpu_loaded_asset = (gpu_asset_t *)assetmanager_get_gpu_loaded_asset_async( &global_engine->systems.assets, cmp_model->asset_id ); - if (!gpu_loaded_asset) { - continue; - } + if (!gpu_loaded_asset) continue; const u32 entity_id = entry->entity_id; const ecs_entity_query_t view = ecs_componentmanager__internal_query_components( @@ -86,7 +82,7 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec .enable_wireframe = false, .instance = {0}, .material = { - .textures = {0}, + .texture = {0}, .shader = { .data = shader, .uniforms = {0}, @@ -136,16 +132,18 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec uniforms->data[uniforms->count].value.vec3 = vec3f(1.0f); uniforms->count++; - for (u8 t = 0; t < model_textures.count; t++) { - cmd.material.textures.ids[cmd.material.textures.count++] = model_textures.items[t].source.normal_texture->id; - } + cmd.material.texture = model_textures; + gltexturelist_t *texlist = &cmd.material.texture; for (u8 t = 0; t < GL_TEXTURE_TYPE_COUNT; t++) { if (!material->texture.asset_ids[t]) continue; gltexture2d_t *tex = (gltexture2d_t *)assetmanager_get_assetresource( &global_engine->systems.assets, ASSET_TYPE_TEXTURE, material->texture.asset_ids[t]); - if (tex) { - cmd.material.textures.ids[cmd.material.textures.count++] = tex->id; + if (tex && texlist->count < MAX_SUPPORTED_TEXTURE_COUNT_PER_DRAW_CALL) { + texlist->items[texlist->count++] = (gltextureitem_t){ + .type = (gltexturetype)t, + .source = { .normal_texture = tex } + }; } } diff --git a/pipeline/render/render_command.h b/pipeline/render/render_command.h index a58c192..c765ecd 100644 --- a/pipeline/render/render_command.h +++ b/pipeline/render/render_command.h @@ -34,10 +34,7 @@ struct rendercommand_t { gluniforms_t uniforms; const glshader_t *data; } shader; - struct { - u16 count; - u16 ids[MAX_TEXTURES_ALLOWED_PER_RENDER]; - } textures; + gltexturelist_t texture; } material; buffer_t instance; @@ -51,12 +48,15 @@ bool rendercommand__internal_compare_textures_ids(const rendercommand_t *const r { ASSERT(rc1 && rc2); - if (rc1->material.textures.count != rc2->material.textures.count) + if (rc1->material.texture.count != rc2->material.texture.count) return false; - for (u8 tex_idx = 0; tex_idx < rc1->material.textures.count; tex_idx++) - if(rc1->material.textures.ids[tex_idx] != rc2->material.textures.ids[tex_idx]) - return false; + for (u8 tex_idx = 0; tex_idx < rc1->material.texture.count; tex_idx++) { + const gltextureitem_t *a = &rc1->material.texture.items[tex_idx]; + const gltextureitem_t *b = &rc2->material.texture.items[tex_idx]; + if (a->type != b->type) return false; + if (a->source.normal_texture->id != b->source.normal_texture->id) return false; + } return true; diff --git a/pipeline/render/render_queue.h b/pipeline/render/render_queue.h index ae2f8a3..144966e 100644 --- a/pipeline/render/render_queue.h +++ b/pipeline/render/render_queue.h @@ -247,9 +247,18 @@ void renderqueue_dispatch(renderqueue_t *const self) } //NOTE: bind textures - for(u8 tex_idx = 0; tex_idx < first_command->material.textures.count; tex_idx++) { - GL_CHECK(glActiveTexture(GL_TEXTURE0 + tex_idx)); - GL_CHECK(glBindTexture(GL_TEXTURE_2D, first_command->material.textures.ids[tex_idx])); + for(u8 tex_idx = 0; tex_idx < first_command->material.texture.count; tex_idx++) { + const gltextureitem_t *item = &first_command->material.texture.items[tex_idx]; + switch (item->type) { + case GL_TEXTURE_TYPE_CUBEMAP: + GL_CHECK(glDepthMask(false)); + GL_CHECK(glDepthFunc(GL_LEQUAL)); + glcubemap_bind(item->source.cubemap); + break; + default: + gltexture2d_bind(item->source.normal_texture, tex_idx); + break; + } } //NOTE: Use instance if configured From 44f035102cc0c26224b896c72b067eee2c8116f7 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 11:05:51 +0530 Subject: [PATCH 08/18] fix: workbench .textures -> .texture, assimp animation filter call --- gfx/model/assimp.h | 2 +- util/workbench.h | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gfx/model/assimp.h b/gfx/model/assimp.h index 5ae24aa..f1703d3 100644 --- a/gfx/model/assimp.h +++ b/gfx/model/assimp.h @@ -447,7 +447,7 @@ glmodel_t glmodel_init(const char *filepath) assimp__internal_glmesh_processScene(&o, scene); //load all animations - animator_load_all_animations(&o.animator, scene, o.arena); + animator_load_all_animations(&o.animator, scene, o.arena, (animation_filter_t){0}); //NOTE: this to cache the root channel idx to get the root position of the model during an animation diff --git a/util/workbench.h b/util/workbench.h index 97d9dbf..a930368 100644 --- a/util/workbench.h +++ b/util/workbench.h @@ -524,7 +524,7 @@ void workbench_render_camera( .size = sizeof(rendercommand_instance_primitive_mesh_t) }, .material = { - .textures = {0}, + .texture = {0}, .shader = { .data = assetmanager_get_assetresource(assetmanager, ASSET_TYPE_GLSL_SHADER, global_workbench->primitives.mesh_shader_id), .uniforms = { @@ -588,10 +588,13 @@ void workbench_render_marker( .size = sizeof(rendercommand_instance_primitive_mesh_t) }, .material = { - .textures = { + .texture = { .count = 1, - .ids = { - atlas->texture.id + .items = { + [0] = (gltextureitem_t){ + .type = GL_TEXTURE_TYPE_NORMAL, + .source = { .normal_texture = &atlas->texture } + } } }, .shader = { From 0308984824048c98aeba6c48581711042fcd6cff Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 11:15:04 +0530 Subject: [PATCH 09/18] fix: address review - gltexturelist_t textures in material, simplify model.h --- ecs/component/types.h | 4 +--- ecs/systems/model.h | 15 +++++---------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/ecs/component/types.h b/ecs/component/types.h index b251fb2..03c46fa 100644 --- a/ecs/component/types.h +++ b/ecs/component/types.h @@ -100,9 +100,7 @@ struct ecs_component_input_t { typedef struct ecs_component_material_t ecs_component_material_t; struct ecs_component_material_t { - struct { - u32 asset_ids[GL_TEXTURE_TYPE_COUNT]; - } texture; + gltexturelist_t textures; struct { u32 asset_id; gluniforms_t uniforms; diff --git a/ecs/systems/model.h b/ecs/systems/model.h index ee0ec0b..c2d9d6d 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -134,16 +134,11 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec cmd.material.texture = model_textures; - gltexturelist_t *texlist = &cmd.material.texture; - for (u8 t = 0; t < GL_TEXTURE_TYPE_COUNT; t++) { - if (!material->texture.asset_ids[t]) continue; - gltexture2d_t *tex = (gltexture2d_t *)assetmanager_get_assetresource( - &global_engine->systems.assets, ASSET_TYPE_TEXTURE, material->texture.asset_ids[t]); - if (tex && texlist->count < MAX_SUPPORTED_TEXTURE_COUNT_PER_DRAW_CALL) { - texlist->items[texlist->count++] = (gltextureitem_t){ - .type = (gltexturetype)t, - .source = { .normal_texture = tex } - }; + if (material->textures.count) { + for (u8 t = 0; t < material->textures.count; t++) { + if (cmd.material.texture.count < MAX_SUPPORTED_TEXTURE_COUNT_PER_DRAW_CALL) { + cmd.material.texture.items[cmd.material.texture.count++] = material->textures.items[t]; + } } } From 4b5e8cf29e4d9fe8b90b6dd05aa6f87a5c089e13 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 11:43:07 +0530 Subject: [PATCH 10/18] =?UTF-8?q?feat:=20uniform=20registry=20=E2=80=94=20?= =?UTF-8?q?name-keyed=20lookup=20table=20for=20model/mesh=20systems?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces hardcoded uniform injection blocks with a static registry table mapping uniform names to value sources: - ecs/uniform_registry.h: UNIFORM_REGISTRY[] table with 8 entries (view, projection, transform, material.color, uBones, light.*) plus uniform_registry_lookup(), uniform_registry_compute(), and uniform_registry_apply_material_overrides() - model.h / mesh.h: iterate shader->internal.uniformlocs, resolve each name via registry, eprint() crash on unknowns. Material.shader.uniforms overrides registry defaults. --- ecs/systems/mesh.h | 46 +++++++++------- ecs/systems/model.h | 90 +++++++++++-------------------- ecs/uniform_registry.h | 120 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 80 deletions(-) create mode 100644 ecs/uniform_registry.h diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 44e75b5..9ccfcee 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -4,6 +4,7 @@ #include "poglib/ecs/common.h" #include "poglib/ecs/component.h" #include "poglib/ecs/component/types.h" +#include "poglib/ecs/uniform_registry.h" #include "poglib/math/la.h" #include "poglib/pipeline/render/render_queue.h" #include "poglib/poggen.h" @@ -47,14 +48,14 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs spriteatlas_t *atlas = (spriteatlas_t *)assetmanager_get_assetresource( &global_engine->systems.assets, ASSET_TYPE_TEXTURE_SPRITE_ATLAS, global_workbench->primitives.atlas_id); - const matrix4f_t perspective_projection = glms_perspective( - radians(45), - global_engine->handle.app->window.aspect_ratio, - 1.0f, 1000.0f - ); - const bool is_editor_selected = global_workbench->editor.current_selected_entity_id == entry->entity_id; + uniform_compute_ctx_t uniform_ctx = { + .active_camera = ctx.active_camera, + .aspect_ratio = global_engine->handle.app->window.aspect_ratio, + .transform = transform, + .is_selected = is_editor_selected, + }; rendercommand_t command = { .mesh = gpu_loaded_asset->meshes.data, @@ -82,23 +83,28 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs }, .shader = { .data = shader, - .uniforms = { - .count = 2, - .data = { - [0] = { - .name = str("projection"), - .value = perspective_projection - }, - [1] = { - .name = str("view"), - .value = glcamera_getview(ctx.active_camera), - } - } - } + .uniforms = {0}, } } }; + + gluniforms_t *uniforms = &command.material.shader.uniforms; + + hashtable_iterator(&shader->internal.uniformlocs, loc_entry) + { + const hashtable_entry_t *he = loc_entry; + const str_t uniform_name = he->key.str; + const uniform_binding_t *binding = uniform_registry_lookup(uniform_name); + if (!binding) + eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + + uniforms->data[uniforms->count].name = uniform_name; + uniforms->data[uniforms->count].value = uniform_registry_compute(binding->source, &uniform_ctx); + uniforms->count++; + } + + uniform_registry_apply_material_overrides(uniforms, &material->shader.uniforms); + renderqueue_pass_command(&global_engine->systems.renderqueue, command); } } - diff --git a/ecs/systems/model.h b/ecs/systems/model.h index c2d9d6d..10e75cd 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -3,6 +3,7 @@ #include "poglib/ecs/common.h" #include "poglib/ecs/component.h" #include "poglib/ecs/component/types.h" +#include "poglib/ecs/uniform_registry.h" #include "poglib/external/cglm/struct/mat4.h" #include "poglib/gfx/model/assimp.h" #include "poglib/math/la.h" @@ -55,34 +56,30 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec ASSERT(shader); ASSERT(transform); - const matrix4f_t perspective_projection = glms_perspective( - radians(45), - global_engine->handle.app->window.aspect_ratio, - 1.0f, 1000.0f - ); - - const matrix4f_t model_transform = glms_mat4_mul( - glms_translate_make(transform->position), - glms_mat4_mul( - glms_quat_mat4(transform->orientation), - glms_scale_make(transform->scale) - ) - ); - const glmodel_t *model = cmp_model->internal.model; - gltexturelist_t model_textures = glmodel_get_texuturelist(model); + uniform_compute_ctx_t uniform_ctx = { + .active_camera = ctx.active_camera, + .aspect_ratio = global_engine->handle.app->window.aspect_ratio, + .transform = transform, + .is_selected = global_workbench->editor.current_selected_entity_id == entity_id, + }; + ASSERT(gpu_loaded_asset->meshes.count == model->meshes.len); for (u8 idx = 0; idx < model->meshes.len; idx++) { + uniform_ctx.model_color = *(vec4f_t *)list_get_value(&model->colors, idx); + uniform_ctx.bones.count = model->transforms[idx].len; + uniform_ctx.bones.data = (matrix4f_t *)model->transforms[idx].data; + rendercommand_t cmd = { .mesh = &gpu_loaded_asset->meshes.data[idx], .draw_mode = RENDER_COMMAND_DRAW_MODE_TRIANGLE, .enable_wireframe = false, .instance = {0}, .material = { - .texture = {0}, + .texture = model_textures, .shader = { .data = shader, .uniforms = {0}, @@ -90,50 +87,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec } }; - gluniforms_t *uniforms = &cmd.material.shader.uniforms; - - uniforms->data[uniforms->count].name = str("view"); - uniforms->data[uniforms->count].value.mat4 = glcamera_getview(ctx.active_camera); - uniforms->count++; - - uniforms->data[uniforms->count].name = str("projection"); - uniforms->data[uniforms->count].value.mat4 = perspective_projection; - uniforms->count++; - - uniforms->data[uniforms->count].name = str("transform"); - uniforms->data[uniforms->count].value.mat4 = model_transform; - uniforms->count++; - - uniforms->data[uniforms->count].name = str("material.color"); - uniforms->data[uniforms->count].value.vec4 = *(vec4f_t *)list_get_value(&model->colors, idx); - uniforms->count++; - - if (model->transforms[idx].len) { - uniforms->data[uniforms->count].name = str("uBones"); - uniforms->data[uniforms->count].value.mat4s.count = model->transforms[idx].len; - uniforms->data[uniforms->count].value.mat4s.data = (matrix4f_t *)model->transforms[idx].data; - uniforms->count++; - } - - for (u8 u = 0; u < material->shader.uniforms.count; u++) { - uniforms->data[uniforms->count] = material->shader.uniforms.data[u]; - uniforms->count++; - } - - uniforms->data[uniforms->count].name = str("light.color"); - uniforms->data[uniforms->count].value.vec4 = global_workbench->editor.current_selected_entity_id == entry->entity_id ? COLOR_RED : COLOR_WHITE; - uniforms->count++; - - uniforms->data[uniforms->count].name = str("light.ambient"); - uniforms->data[uniforms->count].value.f32 = 1.0f; - uniforms->count++; - - uniforms->data[uniforms->count].name = str("light.position"); - uniforms->data[uniforms->count].value.vec3 = vec3f(1.0f); - uniforms->count++; - - cmd.material.texture = model_textures; - if (material->textures.count) { for (u8 t = 0; t < material->textures.count; t++) { if (cmd.material.texture.count < MAX_SUPPORTED_TEXTURE_COUNT_PER_DRAW_CALL) { @@ -142,6 +95,23 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec } } + gluniforms_t *uniforms = &cmd.material.shader.uniforms; + + hashtable_iterator(&shader->internal.uniformlocs, loc_entry) + { + const hashtable_entry_t *he = loc_entry; + const str_t uniform_name = he->key.str; + const uniform_binding_t *binding = uniform_registry_lookup(uniform_name); + if (!binding) + eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + + uniforms->data[uniforms->count].name = uniform_name; + uniforms->data[uniforms->count].value = uniform_registry_compute(binding->source, &uniform_ctx); + uniforms->count++; + } + + uniform_registry_apply_material_overrides(uniforms, &material->shader.uniforms); + renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h new file mode 100644 index 0000000..6d9de40 --- /dev/null +++ b/ecs/uniform_registry.h @@ -0,0 +1,120 @@ +#pragma once +#include "poglib/ecs/component/types.h" +#include "poglib/external/cglm/struct/mat4.h" +#include "poglib/gfx/gl/shader.h" +#include "poglib/gfx/model/assimp.h" +#include "poglib/math/la.h" +#include "poglib/util/glcamera.h" +#include + +typedef enum { + UNIFORM_SOURCE_CAMERA_VIEW, + UNIFORM_SOURCE_CAMERA_PROJECTION, + UNIFORM_SOURCE_ENTITY_TRANSFORM, + UNIFORM_SOURCE_MODEL_COLOR, + UNIFORM_SOURCE_BONE_TRANSFORMS, + UNIFORM_SOURCE_LIGHT_COLOR, + UNIFORM_SOURCE_LIGHT_AMBIENT, + UNIFORM_SOURCE_LIGHT_POSITION, + UNIFORM_SOURCE_COUNT +} uniform_source_t; + +typedef struct { + str_t name; + gluniform_type type; + uniform_source_t source; +} uniform_binding_t; + +typedef struct { + const glcamera_t *active_camera; + f32 aspect_ratio; + const ecs_component_transform_t *transform; + vec4f_t model_color; + struct { + u32 count; + matrix4f_t *data; + } bones; + bool is_selected; +} uniform_compute_ctx_t; + +static const uniform_binding_t UNIFORM_REGISTRY[] = { + { str_lit("view"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_CAMERA_VIEW }, + { str_lit("projection"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_CAMERA_PROJECTION }, + { str_lit("transform"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_ENTITY_TRANSFORM }, + { str_lit("material.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_MODEL_COLOR }, + { str_lit("uBones"), GL_UNIFORM_TYPE_MATRIX4F_ARRAY, UNIFORM_SOURCE_BONE_TRANSFORMS }, + { str_lit("light.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_LIGHT_COLOR }, + { str_lit("light.ambient"), GL_UNIFORM_TYPE_F32, UNIFORM_SOURCE_LIGHT_AMBIENT }, + { str_lit("light.position"), GL_UNIFORM_TYPE_VEC3F, UNIFORM_SOURCE_LIGHT_POSITION }, +}; +#define UNIFORM_REGISTRY_COUNT ARRAY_LEN(UNIFORM_REGISTRY) + +static const uniform_binding_t *uniform_registry_lookup(const str_t name) +{ + for (u8 i = 0; i < UNIFORM_REGISTRY_COUNT; i++) + if (str_cmp(UNIFORM_REGISTRY[i].name, name)) + return &UNIFORM_REGISTRY[i]; + return NULL; +} + +static gluniform_value_t uniform_registry_compute(uniform_source_t source, const uniform_compute_ctx_t *ctx) +{ + switch (source) + { + case UNIFORM_SOURCE_CAMERA_VIEW: + if (ctx->active_camera) return (gluniform_value_t){ .mat4 = glcamera_getview(ctx->active_camera) }; + break; + + case UNIFORM_SOURCE_CAMERA_PROJECTION: + return (gluniform_value_t){ .mat4 = glms_perspective(radians(45), ctx->aspect_ratio, 1.0f, 1000.0f) }; + + case UNIFORM_SOURCE_ENTITY_TRANSFORM: + if (ctx->transform) + return (gluniform_value_t){ .mat4 = glms_mat4_mul( + glms_translate_make(ctx->transform->position), + glms_mat4_mul( + glms_quat_mat4(ctx->transform->orientation), + glms_scale_make(ctx->transform->scale) + ) + )}; + break; + + case UNIFORM_SOURCE_MODEL_COLOR: + return (gluniform_value_t){ .vec4 = ctx->model_color }; + + case UNIFORM_SOURCE_BONE_TRANSFORMS: + return (gluniform_value_t){ .mat4s = { .count = ctx->bones.count, .data = ctx->bones.data } }; + + case UNIFORM_SOURCE_LIGHT_COLOR: + return (gluniform_value_t){ .vec4 = ctx->is_selected ? COLOR_RED : COLOR_WHITE }; + + case UNIFORM_SOURCE_LIGHT_AMBIENT: + return (gluniform_value_t){ .f32 = 1.0f }; + + case UNIFORM_SOURCE_LIGHT_POSITION: + return (gluniform_value_t){ .vec3 = vec3f(1.0f, 1.0f, 1.0f) }; + + case UNIFORM_SOURCE_COUNT: + break; + } + return (gluniform_value_t){0}; +} + +static bool uniform_registry_apply_material_overrides(gluniforms_t *cmd_uniforms, const gluniforms_t *material_overrides) +{ + for (u8 m = 0; m < material_overrides->count; m++) + { + const uniform_binding_t *binding = uniform_registry_lookup(material_overrides->data[m].name); + if (!binding) continue; + + for (u8 c = 0; c < cmd_uniforms->count; c++) + { + if (str_cmp(cmd_uniforms->data[c].name, material_overrides->data[m].name)) { + cmd_uniforms->data[c].value = material_overrides->data[m].value; + goto next_override; + } + } + next_override:; + } + return true; +} From 5088107fd1bd53b0a5c25a36be96b827d78f2b1e Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 11:46:28 +0530 Subject: [PATCH 11/18] fix: vec3f macro usage in uniform_registry.h --- ecs/uniform_registry.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h index 6d9de40..72b46eb 100644 --- a/ecs/uniform_registry.h +++ b/ecs/uniform_registry.h @@ -92,7 +92,7 @@ static gluniform_value_t uniform_registry_compute(uniform_source_t source, const return (gluniform_value_t){ .f32 = 1.0f }; case UNIFORM_SOURCE_LIGHT_POSITION: - return (gluniform_value_t){ .vec3 = vec3f(1.0f, 1.0f, 1.0f) }; + return (gluniform_value_t){ .vec3 = (vec3f_t){1.0f, 1.0f, 1.0f} }; case UNIFORM_SOURCE_COUNT: break; From eb512b39855fae7db5d799d50a1477b95db02ef1 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 13:35:31 +0530 Subject: [PATCH 12/18] =?UTF-8?q?fix:=20address=20review=20=E2=80=94=20inl?= =?UTF-8?q?ine=20material=20overrides,=20identity=20fallback=20for=20stati?= =?UTF-8?q?c=20bones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - model.h / mesh.h: material.shader.uniforms overrides checked inline during registry iteration, removed standalone apply function - uniform_registry.h: UNIFORM_SOURCE_BONE_TRANSFORMS returns single identity matrix when bones.count == 0 (static models) - Removed now-unused uniform_registry_apply_material_overrides() --- ecs/systems/mesh.h | 10 +++++++--- ecs/systems/model.h | 10 +++++++--- ecs/uniform_registry.h | 26 ++++++-------------------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 9ccfcee..3fefccd 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -98,13 +98,17 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs if (!binding) eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + gluniform_value_t value = uniform_registry_compute(binding->source, &uniform_ctx); + + for (u8 o = 0; o < material->shader.uniforms.count; o++) + if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) + value = material->shader.uniforms.data[o].value; + uniforms->data[uniforms->count].name = uniform_name; - uniforms->data[uniforms->count].value = uniform_registry_compute(binding->source, &uniform_ctx); + uniforms->data[uniforms->count].value = value; uniforms->count++; } - uniform_registry_apply_material_overrides(uniforms, &material->shader.uniforms); - renderqueue_pass_command(&global_engine->systems.renderqueue, command); } } diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 10e75cd..b084117 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -105,13 +105,17 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec if (!binding) eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + gluniform_value_t value = uniform_registry_compute(binding->source, &uniform_ctx); + + for (u8 o = 0; o < material->shader.uniforms.count; o++) + if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) + value = material->shader.uniforms.data[o].value; + uniforms->data[uniforms->count].name = uniform_name; - uniforms->data[uniforms->count].value = uniform_registry_compute(binding->source, &uniform_ctx); + uniforms->data[uniforms->count].value = value; uniforms->count++; } - uniform_registry_apply_material_overrides(uniforms, &material->shader.uniforms); - renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h index 72b46eb..a92c35b 100644 --- a/ecs/uniform_registry.h +++ b/ecs/uniform_registry.h @@ -83,7 +83,12 @@ static gluniform_value_t uniform_registry_compute(uniform_source_t source, const return (gluniform_value_t){ .vec4 = ctx->model_color }; case UNIFORM_SOURCE_BONE_TRANSFORMS: - return (gluniform_value_t){ .mat4s = { .count = ctx->bones.count, .data = ctx->bones.data } }; + if (ctx->bones.count > 0) + return (gluniform_value_t){ .mat4s = { .count = ctx->bones.count, .data = ctx->bones.data } }; + { + static matrix4f_t identity = GLMS_MAT4_IDENTITY_INIT; + return (gluniform_value_t){ .mat4s = { .count = 1, .data = &identity } }; + } case UNIFORM_SOURCE_LIGHT_COLOR: return (gluniform_value_t){ .vec4 = ctx->is_selected ? COLOR_RED : COLOR_WHITE }; @@ -99,22 +104,3 @@ static gluniform_value_t uniform_registry_compute(uniform_source_t source, const } return (gluniform_value_t){0}; } - -static bool uniform_registry_apply_material_overrides(gluniforms_t *cmd_uniforms, const gluniforms_t *material_overrides) -{ - for (u8 m = 0; m < material_overrides->count; m++) - { - const uniform_binding_t *binding = uniform_registry_lookup(material_overrides->data[m].name); - if (!binding) continue; - - for (u8 c = 0; c < cmd_uniforms->count; c++) - { - if (str_cmp(cmd_uniforms->data[c].name, material_overrides->data[m].name)) { - cmd_uniforms->data[c].value = material_overrides->data[m].value; - goto next_override; - } - } - next_override:; - } - return true; -} From 70c71cbd655dd20ae356a29fc61cd16797478b02 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 14:17:16 +0530 Subject: [PATCH 13/18] =?UTF-8?q?fix:=20address=20review=20=E2=80=94=20str?= =?UTF-8?q?ip=20compute=20ctx,=20inline=20source=20switch,=20INTERNAL=20ma?= =?UTF-8?q?cro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - uniform_registry.h: removed uniform_compute_ctx_t and uniform_registry_compute(); registry is now pure lookup table. Functions use INTERNAL macro instead of static. - model.h / mesh.h: inline value computation via switch(binding->source) directly from local data (camera, transform, model, lights). Material overrides still applied inline. - component.h: comment justifying 3KB buffer for material component. --- ecs/component.h | 1 + ecs/systems/mesh.h | 37 ++++++++++++++++++----- ecs/systems/model.h | 57 +++++++++++++++++++++++++++++------- ecs/uniform_registry.h | 66 +----------------------------------------- 4 files changed, 79 insertions(+), 82 deletions(-) diff --git a/ecs/component.h b/ecs/component.h index bef7913..324b46d 100644 --- a/ecs/component.h +++ b/ecs/component.h @@ -191,6 +191,7 @@ void ecs_componentmanager_add(ecs_componentmanager_t * const self, const u32 ent cmp_idx_buffer[cmp_idx_count] = pool->len; const u16 cmp_size = ecs_component__internal_get_componenttype_size(cmp_type); + //NOTE: buffer sized for largest component (ecs_component_material_t ~2.3KB + header) buffer(KB * 3) buf = {0}; //NOTE: sets the entity id diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 3fefccd..21fc9c9 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -50,12 +50,12 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs const bool is_editor_selected = global_workbench->editor.current_selected_entity_id == entry->entity_id; - uniform_compute_ctx_t uniform_ctx = { - .active_camera = ctx.active_camera, - .aspect_ratio = global_engine->handle.app->window.aspect_ratio, - .transform = transform, - .is_selected = is_editor_selected, - }; + const matrix4f_t proj = glms_perspective( + radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); + const matrix4f_t view_mat = glcamera_getview(ctx.active_camera); + const matrix4f_t entity_transform = glms_mat4_mul( + glms_translate_make(transform->position), + glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); rendercommand_t command = { .mesh = gpu_loaded_asset->meshes.data, @@ -98,7 +98,30 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs if (!binding) eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); - gluniform_value_t value = uniform_registry_compute(binding->source, &uniform_ctx); + gluniform_value_t value = {0}; + switch (binding->source) + { + case UNIFORM_SOURCE_CAMERA_VIEW: + value.mat4 = view_mat; + break; + case UNIFORM_SOURCE_CAMERA_PROJECTION: + value.mat4 = proj; + break; + case UNIFORM_SOURCE_ENTITY_TRANSFORM: + value.mat4 = entity_transform; + break; + case UNIFORM_SOURCE_LIGHT_COLOR: + value.vec4 = is_editor_selected ? COLOR_RED : COLOR_WHITE; + break; + case UNIFORM_SOURCE_LIGHT_AMBIENT: + value.f32 = 1.0f; + break; + case UNIFORM_SOURCE_LIGHT_POSITION: + value.vec3 = (vec3f_t){1.0f, 1.0f, 1.0f}; + break; + default: + break; + } for (u8 o = 0; o < material->shader.uniforms.count; o++) if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) diff --git a/ecs/systems/model.h b/ecs/systems/model.h index b084117..10d4d9e 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -59,19 +59,20 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec const glmodel_t *model = cmp_model->internal.model; gltexturelist_t model_textures = glmodel_get_texuturelist(model); - uniform_compute_ctx_t uniform_ctx = { - .active_camera = ctx.active_camera, - .aspect_ratio = global_engine->handle.app->window.aspect_ratio, - .transform = transform, - .is_selected = global_workbench->editor.current_selected_entity_id == entity_id, - }; + const matrix4f_t proj = glms_perspective( + radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); + const matrix4f_t view_mat = glcamera_getview(ctx.active_camera); + const matrix4f_t entity_transform = glms_mat4_mul( + glms_translate_make(transform->position), + glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); + const bool is_selected = global_workbench->editor.current_selected_entity_id == entity_id; ASSERT(gpu_loaded_asset->meshes.count == model->meshes.len); for (u8 idx = 0; idx < model->meshes.len; idx++) { - uniform_ctx.model_color = *(vec4f_t *)list_get_value(&model->colors, idx); - uniform_ctx.bones.count = model->transforms[idx].len; - uniform_ctx.bones.data = (matrix4f_t *)model->transforms[idx].data; + const vec4f_t mesh_color = *(vec4f_t *)list_get_value(&model->colors, idx); + const u32 bone_count = model->transforms[idx].len; + matrix4f_t *bone_data = (matrix4f_t *)model->transforms[idx].data; rendercommand_t cmd = { .mesh = &gpu_loaded_asset->meshes.data[idx], @@ -105,7 +106,43 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec if (!binding) eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); - gluniform_value_t value = uniform_registry_compute(binding->source, &uniform_ctx); + gluniform_value_t value = {0}; + switch (binding->source) + { + case UNIFORM_SOURCE_CAMERA_VIEW: + value.mat4 = view_mat; + break; + case UNIFORM_SOURCE_CAMERA_PROJECTION: + value.mat4 = proj; + break; + case UNIFORM_SOURCE_ENTITY_TRANSFORM: + value.mat4 = entity_transform; + break; + case UNIFORM_SOURCE_MODEL_COLOR: + value.vec4 = mesh_color; + break; + case UNIFORM_SOURCE_BONE_TRANSFORMS: + if (bone_count > 0) { + value.mat4s.count = bone_count; + value.mat4s.data = bone_data; + } else { + static matrix4f_t identity = GLMS_MAT4_IDENTITY_INIT; + value.mat4s.count = 1; + value.mat4s.data = &identity; + } + break; + case UNIFORM_SOURCE_LIGHT_COLOR: + value.vec4 = is_selected ? COLOR_RED : COLOR_WHITE; + break; + case UNIFORM_SOURCE_LIGHT_AMBIENT: + value.f32 = 1.0f; + break; + case UNIFORM_SOURCE_LIGHT_POSITION: + value.vec3 = (vec3f_t){1.0f, 1.0f, 1.0f}; + break; + case UNIFORM_SOURCE_COUNT: + break; + } for (u8 o = 0; o < material->shader.uniforms.count; o++) if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h index a92c35b..01557f5 100644 --- a/ecs/uniform_registry.h +++ b/ecs/uniform_registry.h @@ -1,10 +1,6 @@ #pragma once #include "poglib/ecs/component/types.h" -#include "poglib/external/cglm/struct/mat4.h" #include "poglib/gfx/gl/shader.h" -#include "poglib/gfx/model/assimp.h" -#include "poglib/math/la.h" -#include "poglib/util/glcamera.h" #include typedef enum { @@ -25,18 +21,6 @@ typedef struct { uniform_source_t source; } uniform_binding_t; -typedef struct { - const glcamera_t *active_camera; - f32 aspect_ratio; - const ecs_component_transform_t *transform; - vec4f_t model_color; - struct { - u32 count; - matrix4f_t *data; - } bones; - bool is_selected; -} uniform_compute_ctx_t; - static const uniform_binding_t UNIFORM_REGISTRY[] = { { str_lit("view"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_CAMERA_VIEW }, { str_lit("projection"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_CAMERA_PROJECTION }, @@ -49,58 +33,10 @@ static const uniform_binding_t UNIFORM_REGISTRY[] = { }; #define UNIFORM_REGISTRY_COUNT ARRAY_LEN(UNIFORM_REGISTRY) -static const uniform_binding_t *uniform_registry_lookup(const str_t name) +INTERNAL const uniform_binding_t *uniform_registry_lookup(const str_t name) { for (u8 i = 0; i < UNIFORM_REGISTRY_COUNT; i++) if (str_cmp(UNIFORM_REGISTRY[i].name, name)) return &UNIFORM_REGISTRY[i]; return NULL; } - -static gluniform_value_t uniform_registry_compute(uniform_source_t source, const uniform_compute_ctx_t *ctx) -{ - switch (source) - { - case UNIFORM_SOURCE_CAMERA_VIEW: - if (ctx->active_camera) return (gluniform_value_t){ .mat4 = glcamera_getview(ctx->active_camera) }; - break; - - case UNIFORM_SOURCE_CAMERA_PROJECTION: - return (gluniform_value_t){ .mat4 = glms_perspective(radians(45), ctx->aspect_ratio, 1.0f, 1000.0f) }; - - case UNIFORM_SOURCE_ENTITY_TRANSFORM: - if (ctx->transform) - return (gluniform_value_t){ .mat4 = glms_mat4_mul( - glms_translate_make(ctx->transform->position), - glms_mat4_mul( - glms_quat_mat4(ctx->transform->orientation), - glms_scale_make(ctx->transform->scale) - ) - )}; - break; - - case UNIFORM_SOURCE_MODEL_COLOR: - return (gluniform_value_t){ .vec4 = ctx->model_color }; - - case UNIFORM_SOURCE_BONE_TRANSFORMS: - if (ctx->bones.count > 0) - return (gluniform_value_t){ .mat4s = { .count = ctx->bones.count, .data = ctx->bones.data } }; - { - static matrix4f_t identity = GLMS_MAT4_IDENTITY_INIT; - return (gluniform_value_t){ .mat4s = { .count = 1, .data = &identity } }; - } - - case UNIFORM_SOURCE_LIGHT_COLOR: - return (gluniform_value_t){ .vec4 = ctx->is_selected ? COLOR_RED : COLOR_WHITE }; - - case UNIFORM_SOURCE_LIGHT_AMBIENT: - return (gluniform_value_t){ .f32 = 1.0f }; - - case UNIFORM_SOURCE_LIGHT_POSITION: - return (gluniform_value_t){ .vec3 = (vec3f_t){1.0f, 1.0f, 1.0f} }; - - case UNIFORM_SOURCE_COUNT: - break; - } - return (gluniform_value_t){0}; -} From ac1569855d9f5eaf4bc6fcd4d01e16c9fa915c28 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 16:36:37 +0530 Subject: [PATCH 14/18] =?UTF-8?q?fix:=20address=20review=20=E2=80=94=20sep?= =?UTF-8?q?arate=20material=20override=20pass=20with=20crash=20on=20unknow?= =?UTF-8?q?ns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move material.shader.uniforms overrides to a dedicated pass after shader uniform population (instead of inline during iteration). Each material uniform is looked up in the populated list; unknown names trigger eprint() crash, catching accidental binding typos. --- ecs/systems/mesh.h | 20 ++++++++++++++++---- ecs/systems/model.h | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 21fc9c9..77ae50c 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -123,15 +123,27 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs break; } - for (u8 o = 0; o < material->shader.uniforms.count; o++) - if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) - value = material->shader.uniforms.data[o].value; - uniforms->data[uniforms->count].name = uniform_name; uniforms->data[uniforms->count].value = value; uniforms->count++; } + for (u8 o = 0; o < material->shader.uniforms.count; o++) + { + const str_t name = material->shader.uniforms.data[o].name; + bool found = false; + for (u8 u = 0; u < uniforms->count; u++) + { + if (str_cmp(uniforms->data[u].name, name)) { + uniforms->data[u].value = material->shader.uniforms.data[o].value; + found = true; + break; + } + } + if (!found) + eprint("material uniform '%.*s' not found in shader '%.*s'", name.len, name.data, shader->vs.len, shader->vs.data); + } + renderqueue_pass_command(&global_engine->systems.renderqueue, command); } } diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 10d4d9e..4b93234 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -144,15 +144,27 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec break; } - for (u8 o = 0; o < material->shader.uniforms.count; o++) - if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) - value = material->shader.uniforms.data[o].value; - uniforms->data[uniforms->count].name = uniform_name; uniforms->data[uniforms->count].value = value; uniforms->count++; } + for (u8 o = 0; o < material->shader.uniforms.count; o++) + { + const str_t name = material->shader.uniforms.data[o].name; + bool found = false; + for (u8 u = 0; u < uniforms->count; u++) + { + if (str_cmp(uniforms->data[u].name, name)) { + uniforms->data[u].value = material->shader.uniforms.data[o].value; + found = true; + break; + } + } + if (!found) + eprint("material uniform '%.*s' not found in shader '%.*s'", name.len, name.data, shader->vs.len, shader->vs.data); + } + renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } From daf9a061c13b889b2d574b44fd90d775823c6da0 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 17:15:45 +0530 Subject: [PATCH 15/18] fix: material is sole authority for light.* uniforms, no defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Registry: LIGHT_COLOR/AMBIENT/POSITION sources replaced by single UNIFORM_SOURCE_MATERIAL — material.shader.uniforms is the only source for these values, crash on missing - model.h / mesh.h: switch handles MATERIAL case inline, reads value from material component. Removed 20-line separate override pass from both files. - model.h: dropped unused is_selected variable --- ecs/systems/mesh.h | 37 +++++++++++++------------------------ ecs/systems/model.h | 38 +++++++++++++------------------------- ecs/uniform_registry.h | 10 ++++------ 3 files changed, 30 insertions(+), 55 deletions(-) diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 77ae50c..d8b14d6 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -110,14 +110,19 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs case UNIFORM_SOURCE_ENTITY_TRANSFORM: value.mat4 = entity_transform; break; - case UNIFORM_SOURCE_LIGHT_COLOR: - value.vec4 = is_editor_selected ? COLOR_RED : COLOR_WHITE; - break; - case UNIFORM_SOURCE_LIGHT_AMBIENT: - value.f32 = 1.0f; - break; - case UNIFORM_SOURCE_LIGHT_POSITION: - value.vec3 = (vec3f_t){1.0f, 1.0f, 1.0f}; + case UNIFORM_SOURCE_MATERIAL: + { + bool found = false; + for (u8 o = 0; o < material->shader.uniforms.count; o++) { + if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) { + value = material->shader.uniforms.data[o].value; + found = true; + break; + } + } + if (!found) + eprint("material uniform '%.*s' not set for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + } break; default: break; @@ -128,22 +133,6 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs uniforms->count++; } - for (u8 o = 0; o < material->shader.uniforms.count; o++) - { - const str_t name = material->shader.uniforms.data[o].name; - bool found = false; - for (u8 u = 0; u < uniforms->count; u++) - { - if (str_cmp(uniforms->data[u].name, name)) { - uniforms->data[u].value = material->shader.uniforms.data[o].value; - found = true; - break; - } - } - if (!found) - eprint("material uniform '%.*s' not found in shader '%.*s'", name.len, name.data, shader->vs.len, shader->vs.data); - } - renderqueue_pass_command(&global_engine->systems.renderqueue, command); } } diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 4b93234..7ba01dd 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -65,7 +65,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec const matrix4f_t entity_transform = glms_mat4_mul( glms_translate_make(transform->position), glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); - const bool is_selected = global_workbench->editor.current_selected_entity_id == entity_id; ASSERT(gpu_loaded_asset->meshes.count == model->meshes.len); for (u8 idx = 0; idx < model->meshes.len; idx++) @@ -131,14 +130,19 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec value.mat4s.data = &identity; } break; - case UNIFORM_SOURCE_LIGHT_COLOR: - value.vec4 = is_selected ? COLOR_RED : COLOR_WHITE; - break; - case UNIFORM_SOURCE_LIGHT_AMBIENT: - value.f32 = 1.0f; - break; - case UNIFORM_SOURCE_LIGHT_POSITION: - value.vec3 = (vec3f_t){1.0f, 1.0f, 1.0f}; + case UNIFORM_SOURCE_MATERIAL: + { + bool found = false; + for (u8 o = 0; o < material->shader.uniforms.count; o++) { + if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) { + value = material->shader.uniforms.data[o].value; + found = true; + break; + } + } + if (!found) + eprint("material uniform '%.*s' not set for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + } break; case UNIFORM_SOURCE_COUNT: break; @@ -149,22 +153,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec uniforms->count++; } - for (u8 o = 0; o < material->shader.uniforms.count; o++) - { - const str_t name = material->shader.uniforms.data[o].name; - bool found = false; - for (u8 u = 0; u < uniforms->count; u++) - { - if (str_cmp(uniforms->data[u].name, name)) { - uniforms->data[u].value = material->shader.uniforms.data[o].value; - found = true; - break; - } - } - if (!found) - eprint("material uniform '%.*s' not found in shader '%.*s'", name.len, name.data, shader->vs.len, shader->vs.data); - } - renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h index 01557f5..4862aa7 100644 --- a/ecs/uniform_registry.h +++ b/ecs/uniform_registry.h @@ -9,9 +9,7 @@ typedef enum { UNIFORM_SOURCE_ENTITY_TRANSFORM, UNIFORM_SOURCE_MODEL_COLOR, UNIFORM_SOURCE_BONE_TRANSFORMS, - UNIFORM_SOURCE_LIGHT_COLOR, - UNIFORM_SOURCE_LIGHT_AMBIENT, - UNIFORM_SOURCE_LIGHT_POSITION, + UNIFORM_SOURCE_MATERIAL, UNIFORM_SOURCE_COUNT } uniform_source_t; @@ -27,9 +25,9 @@ static const uniform_binding_t UNIFORM_REGISTRY[] = { { str_lit("transform"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_ENTITY_TRANSFORM }, { str_lit("material.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_MODEL_COLOR }, { str_lit("uBones"), GL_UNIFORM_TYPE_MATRIX4F_ARRAY, UNIFORM_SOURCE_BONE_TRANSFORMS }, - { str_lit("light.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_LIGHT_COLOR }, - { str_lit("light.ambient"), GL_UNIFORM_TYPE_F32, UNIFORM_SOURCE_LIGHT_AMBIENT }, - { str_lit("light.position"), GL_UNIFORM_TYPE_VEC3F, UNIFORM_SOURCE_LIGHT_POSITION }, + { str_lit("light.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_MATERIAL }, + { str_lit("light.ambient"), GL_UNIFORM_TYPE_F32, UNIFORM_SOURCE_MATERIAL }, + { str_lit("light.position"), GL_UNIFORM_TYPE_VEC3F, UNIFORM_SOURCE_MATERIAL }, }; #define UNIFORM_REGISTRY_COUNT ARRAY_LEN(UNIFORM_REGISTRY) From 61d53a826027673c7ae7f59f4c54db7ff5f8d7d2 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 17:35:36 +0530 Subject: [PATCH 16/18] fix: drop uniform registry, hardcode assignments directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove ecs/uniform_registry.h entirely. Each render system now writes its uniforms directly into the rendercommand — no lookup table, no source enum, no shared abstraction. model.h: view, projection, transform, material.color, uBones (conditional), material uniforms dumped wholesale. mesh.h: view, projection (instance shader baseline), material uniforms dumped wholesale. Removes ~100 lines of abstraction for no real loss at this scale. --- ecs/systems/mesh.h | 54 +++++---------------------- ecs/systems/model.h | 84 +++++++++++++----------------------------- ecs/uniform_registry.h | 40 -------------------- 3 files changed, 35 insertions(+), 143 deletions(-) delete mode 100644 ecs/uniform_registry.h diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index d8b14d6..6cc0212 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -4,7 +4,6 @@ #include "poglib/ecs/common.h" #include "poglib/ecs/component.h" #include "poglib/ecs/component/types.h" -#include "poglib/ecs/uniform_registry.h" #include "poglib/math/la.h" #include "poglib/pipeline/render/render_queue.h" #include "poglib/poggen.h" @@ -53,9 +52,6 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs const matrix4f_t proj = glms_perspective( radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); const matrix4f_t view_mat = glcamera_getview(ctx.active_camera); - const matrix4f_t entity_transform = glms_mat4_mul( - glms_translate_make(transform->position), - glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); rendercommand_t command = { .mesh = gpu_loaded_asset->meshes.data, @@ -88,50 +84,18 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs } }; - gluniforms_t *uniforms = &command.material.shader.uniforms; + gluniforms_t *u = &command.material.shader.uniforms; - hashtable_iterator(&shader->internal.uniformlocs, loc_entry) - { - const hashtable_entry_t *he = loc_entry; - const str_t uniform_name = he->key.str; - const uniform_binding_t *binding = uniform_registry_lookup(uniform_name); - if (!binding) - eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); + u->data[u->count].name = str("view"); + u->data[u->count].value.mat4 = view_mat; + u->count++; - gluniform_value_t value = {0}; - switch (binding->source) - { - case UNIFORM_SOURCE_CAMERA_VIEW: - value.mat4 = view_mat; - break; - case UNIFORM_SOURCE_CAMERA_PROJECTION: - value.mat4 = proj; - break; - case UNIFORM_SOURCE_ENTITY_TRANSFORM: - value.mat4 = entity_transform; - break; - case UNIFORM_SOURCE_MATERIAL: - { - bool found = false; - for (u8 o = 0; o < material->shader.uniforms.count; o++) { - if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) { - value = material->shader.uniforms.data[o].value; - found = true; - break; - } - } - if (!found) - eprint("material uniform '%.*s' not set for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); - } - break; - default: - break; - } + u->data[u->count].name = str("projection"); + u->data[u->count].value.mat4 = proj; + u->count++; - uniforms->data[uniforms->count].name = uniform_name; - uniforms->data[uniforms->count].value = value; - uniforms->count++; - } + for (u8 i = 0; i < material->shader.uniforms.count; i++) + u->data[u->count++] = material->shader.uniforms.data[i]; renderqueue_pass_command(&global_engine->systems.renderqueue, command); } diff --git a/ecs/systems/model.h b/ecs/systems/model.h index 7ba01dd..da8c13f 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -3,7 +3,6 @@ #include "poglib/ecs/common.h" #include "poglib/ecs/component.h" #include "poglib/ecs/component/types.h" -#include "poglib/ecs/uniform_registry.h" #include "poglib/external/cglm/struct/mat4.h" #include "poglib/gfx/model/assimp.h" #include "poglib/math/la.h" @@ -13,7 +12,6 @@ #include "poglib/util/asset.h" #include "poglib/util/assetmanager.h" #include "poglib/util/glcamera.h" -#include "poglib/util/workbench/common.h" void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ecs_system_ctx_t ctx) { @@ -62,7 +60,7 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec const matrix4f_t proj = glms_perspective( radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); const matrix4f_t view_mat = glcamera_getview(ctx.active_camera); - const matrix4f_t entity_transform = glms_mat4_mul( + const matrix4f_t model_mat = glms_mat4_mul( glms_translate_make(transform->position), glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); @@ -95,64 +93,34 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec } } - gluniforms_t *uniforms = &cmd.material.shader.uniforms; - - hashtable_iterator(&shader->internal.uniformlocs, loc_entry) - { - const hashtable_entry_t *he = loc_entry; - const str_t uniform_name = he->key.str; - const uniform_binding_t *binding = uniform_registry_lookup(uniform_name); - if (!binding) - eprint("uniform '%.*s' not found in registry for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); - - gluniform_value_t value = {0}; - switch (binding->source) - { - case UNIFORM_SOURCE_CAMERA_VIEW: - value.mat4 = view_mat; - break; - case UNIFORM_SOURCE_CAMERA_PROJECTION: - value.mat4 = proj; - break; - case UNIFORM_SOURCE_ENTITY_TRANSFORM: - value.mat4 = entity_transform; - break; - case UNIFORM_SOURCE_MODEL_COLOR: - value.vec4 = mesh_color; - break; - case UNIFORM_SOURCE_BONE_TRANSFORMS: - if (bone_count > 0) { - value.mat4s.count = bone_count; - value.mat4s.data = bone_data; - } else { - static matrix4f_t identity = GLMS_MAT4_IDENTITY_INIT; - value.mat4s.count = 1; - value.mat4s.data = &identity; - } - break; - case UNIFORM_SOURCE_MATERIAL: - { - bool found = false; - for (u8 o = 0; o < material->shader.uniforms.count; o++) { - if (str_cmp(material->shader.uniforms.data[o].name, uniform_name)) { - value = material->shader.uniforms.data[o].value; - found = true; - break; - } - } - if (!found) - eprint("material uniform '%.*s' not set for shader '%.*s'", uniform_name.len, uniform_name.data, shader->vs.len, shader->vs.data); - } - break; - case UNIFORM_SOURCE_COUNT: - break; - } + gluniforms_t *u = &cmd.material.shader.uniforms; + + u->data[u->count].name = str("view"); + u->data[u->count].value.mat4 = view_mat; + u->count++; + + u->data[u->count].name = str("projection"); + u->data[u->count].value.mat4 = proj; + u->count++; - uniforms->data[uniforms->count].name = uniform_name; - uniforms->data[uniforms->count].value = value; - uniforms->count++; + u->data[u->count].name = str("transform"); + u->data[u->count].value.mat4 = model_mat; + u->count++; + + u->data[u->count].name = str("material.color"); + u->data[u->count].value.vec4 = mesh_color; + u->count++; + + if (bone_count) { + u->data[u->count].name = str("uBones"); + u->data[u->count].value.mat4s.count = bone_count; + u->data[u->count].value.mat4s.data = bone_data; + u->count++; } + for (u8 i = 0; i < material->shader.uniforms.count; i++) + u->data[u->count++] = material->shader.uniforms.data[i]; + renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h deleted file mode 100644 index 4862aa7..0000000 --- a/ecs/uniform_registry.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "poglib/ecs/component/types.h" -#include "poglib/gfx/gl/shader.h" -#include - -typedef enum { - UNIFORM_SOURCE_CAMERA_VIEW, - UNIFORM_SOURCE_CAMERA_PROJECTION, - UNIFORM_SOURCE_ENTITY_TRANSFORM, - UNIFORM_SOURCE_MODEL_COLOR, - UNIFORM_SOURCE_BONE_TRANSFORMS, - UNIFORM_SOURCE_MATERIAL, - UNIFORM_SOURCE_COUNT -} uniform_source_t; - -typedef struct { - str_t name; - gluniform_type type; - uniform_source_t source; -} uniform_binding_t; - -static const uniform_binding_t UNIFORM_REGISTRY[] = { - { str_lit("view"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_CAMERA_VIEW }, - { str_lit("projection"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_CAMERA_PROJECTION }, - { str_lit("transform"), GL_UNIFORM_TYPE_MATRIX4F, UNIFORM_SOURCE_ENTITY_TRANSFORM }, - { str_lit("material.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_MODEL_COLOR }, - { str_lit("uBones"), GL_UNIFORM_TYPE_MATRIX4F_ARRAY, UNIFORM_SOURCE_BONE_TRANSFORMS }, - { str_lit("light.color"), GL_UNIFORM_TYPE_VEC4F, UNIFORM_SOURCE_MATERIAL }, - { str_lit("light.ambient"), GL_UNIFORM_TYPE_F32, UNIFORM_SOURCE_MATERIAL }, - { str_lit("light.position"), GL_UNIFORM_TYPE_VEC3F, UNIFORM_SOURCE_MATERIAL }, -}; -#define UNIFORM_REGISTRY_COUNT ARRAY_LEN(UNIFORM_REGISTRY) - -INTERNAL const uniform_binding_t *uniform_registry_lookup(const str_t name) -{ - for (u8 i = 0; i < UNIFORM_REGISTRY_COUNT; i++) - if (str_cmp(UNIFORM_REGISTRY[i].name, name)) - return &UNIFORM_REGISTRY[i]; - return NULL; -} From d94338be14b58f226f3b3bf82e40c0fa84c29574 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 17:54:25 +0530 Subject: [PATCH 17/18] feat: separate uniform resolution from render systems New ecs_system_uniform_resolve runs before render systems and pre-populates material->shader.uniforms with per-frame values (view, projection, transform) from camera + entity data. Only fills uniforms the material hasn't already set. - ecs/uniform_registry.h: reinstated with resolve function - ecs/systems/uniform_resolve.h: new ECS system, iterates ECS_CMP_MATERIAL pool, resolves uniforms per entity - ecs/system.h: resolver registered after collider, before animation Render systems simplified: - model.h: copies resolved uniforms, adds only per-mesh material.color + uBones - mesh.h: copies resolved uniforms directly, zero uniform math --- ecs/system.h | 8 +++++ ecs/systems/mesh.h | 19 +---------- ecs/systems/model.h | 25 +------------- ecs/systems/uniform_resolve.h | 21 ++++++++++++ ecs/uniform_registry.h | 61 +++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 42 deletions(-) create mode 100644 ecs/systems/uniform_resolve.h create mode 100644 ecs/uniform_registry.h diff --git a/ecs/system.h b/ecs/system.h index 14e7bf3..19cbfa3 100644 --- a/ecs/system.h +++ b/ecs/system.h @@ -7,6 +7,7 @@ #include "poglib/ecs/systems/mesh.h" #include "poglib/ecs/systems/model.h" #include "poglib/ecs/systems/transform.h" +#include "poglib/ecs/systems/uniform_resolve.h" void ecs_add_system(ecs_t *const self, const ecs_system_t system) { @@ -49,6 +50,13 @@ void ecs_add_all_core_systems(ecs_t *const self) } ); + ecs_add_system( + self, + (ecs_system_t) { + .callback = ecs_system_uniform_resolve + } + ); + ecs_add_system( self, (ecs_system_t) { diff --git a/ecs/systems/mesh.h b/ecs/systems/mesh.h index 6cc0212..a111e7c 100644 --- a/ecs/systems/mesh.h +++ b/ecs/systems/mesh.h @@ -49,10 +49,6 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs const bool is_editor_selected = global_workbench->editor.current_selected_entity_id == entry->entity_id; - const matrix4f_t proj = glms_perspective( - radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); - const matrix4f_t view_mat = glcamera_getview(ctx.active_camera); - rendercommand_t command = { .mesh = gpu_loaded_asset->meshes.data, .draw_mode = RENDER_COMMAND_DRAW_MODE_TRIANGLE, @@ -79,24 +75,11 @@ void ecs_system_render_mesh(ecs_componentmanager_t *const cmp_manager, const ecs }, .shader = { .data = shader, - .uniforms = {0}, + .uniforms = material->shader.uniforms, } } }; - gluniforms_t *u = &command.material.shader.uniforms; - - u->data[u->count].name = str("view"); - u->data[u->count].value.mat4 = view_mat; - u->count++; - - u->data[u->count].name = str("projection"); - u->data[u->count].value.mat4 = proj; - u->count++; - - for (u8 i = 0; i < material->shader.uniforms.count; i++) - u->data[u->count++] = material->shader.uniforms.data[i]; - renderqueue_pass_command(&global_engine->systems.renderqueue, command); } } diff --git a/ecs/systems/model.h b/ecs/systems/model.h index da8c13f..4d1c6cb 100644 --- a/ecs/systems/model.h +++ b/ecs/systems/model.h @@ -11,7 +11,6 @@ #include "poglib/poggen.h" #include "poglib/util/asset.h" #include "poglib/util/assetmanager.h" -#include "poglib/util/glcamera.h" void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ecs_system_ctx_t ctx) { @@ -57,13 +56,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec const glmodel_t *model = cmp_model->internal.model; gltexturelist_t model_textures = glmodel_get_texuturelist(model); - const matrix4f_t proj = glms_perspective( - radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); - const matrix4f_t view_mat = glcamera_getview(ctx.active_camera); - const matrix4f_t model_mat = glms_mat4_mul( - glms_translate_make(transform->position), - glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); - ASSERT(gpu_loaded_asset->meshes.count == model->meshes.len); for (u8 idx = 0; idx < model->meshes.len; idx++) { @@ -80,7 +72,7 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec .texture = model_textures, .shader = { .data = shader, - .uniforms = {0}, + .uniforms = material->shader.uniforms, } } }; @@ -95,18 +87,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec gluniforms_t *u = &cmd.material.shader.uniforms; - u->data[u->count].name = str("view"); - u->data[u->count].value.mat4 = view_mat; - u->count++; - - u->data[u->count].name = str("projection"); - u->data[u->count].value.mat4 = proj; - u->count++; - - u->data[u->count].name = str("transform"); - u->data[u->count].value.mat4 = model_mat; - u->count++; - u->data[u->count].name = str("material.color"); u->data[u->count].value.vec4 = mesh_color; u->count++; @@ -118,9 +98,6 @@ void ecs_system_render_model(ecs_componentmanager_t *const cmp_manager, const ec u->count++; } - for (u8 i = 0; i < material->shader.uniforms.count; i++) - u->data[u->count++] = material->shader.uniforms.data[i]; - renderqueue_pass_command(&global_engine->systems.renderqueue, cmd); } } diff --git a/ecs/systems/uniform_resolve.h b/ecs/systems/uniform_resolve.h new file mode 100644 index 0000000..6fcb8f0 --- /dev/null +++ b/ecs/systems/uniform_resolve.h @@ -0,0 +1,21 @@ +#pragma once +#include "poglib/ecs/common.h" +#include "poglib/ecs/component.h" +#include "poglib/ecs/component/types.h" +#include "poglib/ecs/uniform_registry.h" + +void ecs_system_uniform_resolve(ecs_componentmanager_t *const cmp_manager, const ecs_system_ctx_t ctx) +{ + slot_t *primary_pool = slot_get_value(&cmp_manager->componentpool_slots, ECS_CMP_MATERIAL_IDX); + + slot_iterator(primary_pool, ITER) + { + const ecs_component_poolentry_t *const entry = ITER; + ecs_component_material_t *material = (ecs_component_material_t *)entry->entity_cmpdata; + + if (!material->shader.asset_id) continue; + + uniform_registry_resolve_material_uniforms( + material, cmp_manager, entry->entity_id, ctx.active_camera); + } +} diff --git a/ecs/uniform_registry.h b/ecs/uniform_registry.h new file mode 100644 index 0000000..487ab78 --- /dev/null +++ b/ecs/uniform_registry.h @@ -0,0 +1,61 @@ +#pragma once +#include "poglib/ecs/component/types.h" +#include "poglib/ecs/common.h" +#include "poglib/gfx/gl/shader.h" +#include "poglib/poggen.h" +#include +#include +#include + +INTERNAL void uniform_registry_resolve_material_uniforms( + ecs_component_material_t *material, + const ecs_componentmanager_t *cmp_manager, + u32 entity_id, + const glcamera_t *active_camera) +{ + const glshader_t *shader = (glshader_t *)assetmanager_get_assetresource( + &global_engine->systems.assets, ASSET_TYPE_GLSL_SHADER, material->shader.asset_id); + if (!shader) return; + + const ecs_entity_query_t view = ecs_componentmanager__internal_query_components( + (ecs_componentmanager_t *)cmp_manager, entity_id, ECS_CMP_TRANSFORM); + const ecs_component_transform_t *transform = view.entity_cmp_data[ECS_CMP_TRANSFORM_IDX]; + if (!transform) return; + + const matrix4f_t proj = glms_perspective( + radians(45), global_engine->handle.app->window.aspect_ratio, 1.0f, 1000.0f); + const matrix4f_t view_mat = glcamera_getview(active_camera); + const matrix4f_t model_mat = glms_mat4_mul( + glms_translate_make(transform->position), + glms_mat4_mul(glms_quat_mat4(transform->orientation), glms_scale_make(transform->scale))); + + hashtable_iterator(&shader->internal.uniformlocs, loc_entry) + { + const hashtable_entry_t *he = loc_entry; + const str_t uniform_name = he->key.str; + + bool already_set = false; + for (u8 i = 0; i < material->shader.uniforms.count; i++) { + if (str_cmp(material->shader.uniforms.data[i].name, uniform_name)) { + already_set = true; + break; + } + } + if (already_set) continue; + + gluniform_value_t value = {0}; + if (str_cmp(uniform_name, str("view"))) + value.mat4 = view_mat; + else if (str_cmp(uniform_name, str("projection"))) + value.mat4 = proj; + else if (str_cmp(uniform_name, str("transform"))) + value.mat4 = model_mat; + else + continue; + + ASSERT(material->shader.uniforms.count < MAX_UNIFORMS_ALLOWED_IN_SHADER); + material->shader.uniforms.data[material->shader.uniforms.count].name = uniform_name; + material->shader.uniforms.data[material->shader.uniforms.count].value = value; + material->shader.uniforms.count++; + } +} From 9288cc392042d85a63e43255845ae735a629d6a6 Mon Sep 17 00:00:00 2001 From: Gokul Krishnan C M Date: Fri, 10 Jul 2026 18:07:47 +0530 Subject: [PATCH 18/18] fix: update ecs serialization tests for new material format - test save files: material {totalmembers:1,bytesize:...} with only shader_asset_id field (texture_asset_id removed) - test source: updated ecs_component_material_t initialization and assertions to use shader.asset_id - build script: fixed include path for standalone worktree builds --- test/ecs/save_load/build.sh | 7 ++++--- test/ecs/save_load/src/main.c | 9 ++++----- test/ecs/save_load/test_corruption.ecs | 9 +++------ test/ecs/save_load/test_save.ecs | 6 ++---- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/test/ecs/save_load/build.sh b/test/ecs/save_load/build.sh index 2ae91de..1d8af08 100755 --- a/test/ecs/save_load/build.sh +++ b/test/ecs/save_load/build.sh @@ -3,13 +3,14 @@ SRC_PATH="./src/main.c" EXE_NAME="ecs_save_load_test" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -POGLIB_DIR="$(cd "$SCRIPT_DIR/../../../.." && pwd)" -JOLT_DIR="$POGLIB_DIR/poglib/external/joltc/lib/linux/debug" +POGLIB_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)" +PARENT_DIR="$(dirname "$POGLIB_DIR")" +JOLT_DIR="$POGLIB_DIR/external/joltc/lib/linux/debug" CC="clang" FLAGS="-std=c11 -g -O0 -DDEBUG -W -Wall -Wextra -Wno-missing-braces -Wincompatible-pointer-types-discards-qualifiers -Wno-variadic-macros" LINKERS="-lfreetype -lSDL2 -lGLEW -lGLU -lGL -lm -lassimp -pthread -ldl -L$JOLT_DIR -ljoltcd -lJoltd -lstdc++" -INCLUDES="-I/usr/include/freetype2 -I$POGLIB_DIR -I/usr/include/SDL2" +INCLUDES="-I/usr/include/freetype2 -I$PARENT_DIR -I/usr/include/SDL2" red=$(tput setaf 1) green=$(tput bold; tput setaf 2) diff --git a/test/ecs/save_load/src/main.c b/test/ecs/save_load/src/main.c index 57613c0..8348401 100644 --- a/test/ecs/save_load/src/main.c +++ b/test/ecs/save_load/src/main.c @@ -66,7 +66,7 @@ static void test_all_component_types(void) .component = { [ECS_CMP_TRANSFORM_IDX].transform = (ecs_component_transform_t){ .scale = {1,1,1}, .source = ECS_CMP_TRANSFORM_SOURCE_NONE }, [ECS_CMP_MESH_IDX].mesh = (ecs_component_mesh_t){ .asset_id = 2, .prototype_sprite_type = 20 }, - [ECS_CMP_MATERIAL_IDX].material = (ecs_component_material_t){ .texture_asset_id = 6, .shader_asset_id = 7 }, + [ECS_CMP_MATERIAL_IDX].material = (ecs_component_material_t){ .shader = { .asset_id = 7 } }, } }); /* entity 3: input */ @@ -116,7 +116,7 @@ static void test_all_component_types(void) .component = { [ECS_CMP_TRANSFORM_IDX].transform = (ecs_component_transform_t){ .scale = {1,1,1}, .source = ECS_CMP_TRANSFORM_SOURCE_NONE }, [ECS_CMP_MODEL_IDX].model = (ecs_component_model_t){ .asset_id = 9 }, - [ECS_CMP_MATERIAL_IDX].material = (ecs_component_material_t){ .texture_asset_id = 0, .shader_asset_id = 10 }, + [ECS_CMP_MATERIAL_IDX].material = (ecs_component_material_t){ .shader = { .asset_id = 10 } }, } }); /* entities 7-9: multiple same type for multi-entity test */ @@ -155,8 +155,7 @@ static void test_all_component_types(void) TEST_ASSERT(m->asset_id == 2, "mesh: asset_id"); TEST_ASSERT(m->prototype_sprite_type == 20, "mesh: sprite_type"); TEST_ASSERT(mat, "material: present"); - TEST_ASSERT(mat->texture_asset_id == 6, "material: texture_id"); - TEST_ASSERT(mat->shader_asset_id == 7, "material: shader_id"); } + TEST_ASSERT(mat->shader.asset_id == 7, "material: shader_id"); } /* entity 3: input */ { const ecs_entity_query_t q = ecs_entity_query_components(ecs2, 3, ECS_CMP_INPUT); @@ -232,7 +231,7 @@ static void test_asset_loading_from_save(void) .component = { [ECS_CMP_TRANSFORM_IDX].transform = (ecs_component_transform_t){ .scale={1,1,1}, .source=ECS_CMP_TRANSFORM_SOURCE_NONE }, [ECS_CMP_MODEL_IDX].model = (ecs_component_model_t){ .asset_id = model_id }, - [ECS_CMP_MATERIAL_IDX].material = (ecs_component_material_t){ .texture_asset_id=0, .shader_asset_id=0 }, + [ECS_CMP_MATERIAL_IDX].material = (ecs_component_material_t){ .shader = { .asset_id = 0 } }, } }); SAVE_AND_DESTROY(ecs); diff --git a/test/ecs/save_load/test_corruption.ecs b/test/ecs/save_load/test_corruption.ecs index 7645a13..8ca01e4 100644 --- a/test/ecs/save_load/test_corruption.ecs +++ b/test/ecs/save_load/test_corruption.ecs @@ -15,8 +15,7 @@ input:{totalmembers:3,bytesize:80} state.orientation:[0.000000,0.000000,0.000000,1.000000] state.front:[-0.185430,-0.268920,-0.945144] state.right:[0.981293,0.000000,-0.192522] -material:{totalmembers:2,bytesize:8} - texture_asset_id:0 +material:{totalmembers:1,bytesize:2344} shader_asset_id:10 collider:{totalmembers:5,bytesize:96} shape_type:1 @@ -33,8 +32,7 @@ transform:{totalmembers:5,bytesize:64} scale:[1.000000,1.000000,1.000000] velocity:[0.000000,0.000000,0.000000] source:0 -material:{totalmembers:2,bytesize:8} - texture_asset_id:6 +material:{totalmembers:1,bytesize:2344} shader_asset_id:7 collider:{totalmembers:5,bytesize:96} shape_type:3 @@ -54,8 +52,7 @@ transform:{totalmembers:5,bytesize:64} scale:[1.000000,2.500000,1.000000] velocity:[0.000000,0.000000,0.000000] source:0 -material:{totalmembers:2,bytesize:8} - texture_asset_id:6 +material:{totalmembers:1,bytesize:2344} shader_asset_id:7 collider:{totalmembers:5,bytesize:96} shape_type:3 diff --git a/test/ecs/save_load/test_save.ecs b/test/ecs/save_load/test_save.ecs index 636f580..289582b 100644 --- a/test/ecs/save_load/test_save.ecs +++ b/test/ecs/save_load/test_save.ecs @@ -7,8 +7,7 @@ transform:{totalmembers:5,bytesize:64} scale:[1.000000,1.000000,1.000000] velocity:[0.000000,0.000000,0.000000] source:0 -material:{totalmembers:2,bytesize:8} - texture_asset_id:6 +material:{totalmembers:1,bytesize:2344} shader_asset_id:7 mesh:{totalmembers:2,bytesize:8} asset_id:2 @@ -76,8 +75,7 @@ transform:{totalmembers:5,bytesize:64} source:0 model:{totalmembers:2,bytesize:16} asset_id:9 -material:{totalmembers:2,bytesize:8} - texture_asset_id:0 +material:{totalmembers:1,bytesize:2344} shader_asset_id:10 entity:7 component_signature:1