Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
662e35c
feat: generic ecs material with texture type slots + shader uniforms
gimploo Jul 10, 2026
8354f12
fix: remove typeof, fix animation_filter_t, fix ASSET_TYPE_TEXTURE
gimploo Jul 10, 2026
8d1ddc6
fix: str_lit -> str in assignments, fix collision-scene material fields
gimploo Jul 10, 2026
f1e49d6
fix: cap ecs material pool capacity to avoid OOM with larger struct
gimploo Jul 10, 2026
819cff7
fix: increase component buffer to fit larger material struct
gimploo Jul 10, 2026
ed6baf6
fix: keep light uniforms auto-injected for backward compat
gimploo Jul 10, 2026
23facc0
feat: replace flat texture ids with gltexturelist_t in render pipeline
gimploo Jul 10, 2026
44f0351
fix: workbench .textures -> .texture, assimp animation filter call
gimploo Jul 10, 2026
0308984
fix: address review - gltexturelist_t textures in material, simplify …
gimploo Jul 10, 2026
4b5e8cf
feat: uniform registry — name-keyed lookup table for model/mesh systems
gimploo Jul 10, 2026
5088107
fix: vec3f macro usage in uniform_registry.h
gimploo Jul 10, 2026
eb512b3
fix: address review — inline material overrides, identity fallback fo…
gimploo Jul 10, 2026
70c71cb
fix: address review — strip compute ctx, inline source switch, INTERN…
gimploo Jul 10, 2026
ac15698
fix: address review — separate material override pass with crash on u…
gimploo Jul 10, 2026
daf9a06
fix: material is sole authority for light.* uniforms, no defaults
gimploo Jul 10, 2026
61d53a8
fix: drop uniform registry, hardcode assignments directly
gimploo Jul 10, 2026
d94338b
feat: separate uniform resolution from render systems
gimploo Jul 10, 2026
9288cc3
fix: update ecs serialization tests for new material format
gimploo Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ecs/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -190,7 +191,8 @@ 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};
//NOTE: buffer sized for largest component (ecs_component_material_t ~2.3KB + header)
buffer(KB * 3) buf = {0};

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does it need 3KB ?


//NOTE: sets the entity id
memcpy(buf.raw_data, &entity_id, sizeof(entity_id));
Expand Down
9 changes: 7 additions & 2 deletions ecs/component/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <poglib/math.h>
#include <poglib/physics/jolt-wrapper.h>
#include <poglib/util/glcamera.h>
#include <poglib/gfx/gl/shader.h>
#include <poglib/gfx/gl/texture_types.h>

#define ECS_CMP_INVALID_IDX -1

Expand Down Expand Up @@ -98,8 +100,11 @@ 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;
gltexturelist_t textures;
struct {
u32 asset_id;
gluniforms_t uniforms;
} shader;
};

/* =========================== CAMERA ================================== */
Expand Down
10 changes: 4 additions & 6 deletions ecs/serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),

@gimploo gimploo Jul 10, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks wrong ?

}
},
[ECS_CMP_CAMERA_IDX] = {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure tests are updated for ecs serialization

if (mat->shader.asset_id) mat->shader.asset_id = ecs_deserializer__internal_ensure_asset_loaded(assets, mat->shader.asset_id, assets_parsed);
} break;
}
}
Expand Down
8 changes: 8 additions & 0 deletions ecs/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down
34 changes: 9 additions & 25 deletions ecs/systems/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -47,15 +47,8 @@ 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;


rendercommand_t command = {
.mesh = gpu_loaded_asset->meshes.data,
.draw_mode = RENDER_COMMAND_DRAW_MODE_TRIANGLE,
Expand All @@ -71,31 +64,22 @@ 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 = {
.data = shader,
.uniforms = {
.count = 2,
.data = {
[0] = {
.name = str("projection"),
.value = perspective_projection
},
[1] = {
.name = str("view"),
.value = glcamera_getview(ctx.active_camera),
}
}
}
.uniforms = material->shader.uniforms,
}
}
};

renderqueue_pass_command(&global_engine->systems.renderqueue, command);
}
}

128 changes: 47 additions & 81 deletions ecs/systems/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
#include "poglib/poggen.h"
#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)
{
Expand All @@ -28,111 +26,79 @@ 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
);
}


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,
&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(
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];
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);
ASSERT(transform);

const matrix4f_t perspective_projection = glms_perspective(
radians(45),
global_engine->handle.app->window.aspect_ratio,
1.0f, 1000.0f
);

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)
}
}
}
}
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],
.draw_mode = RENDER_COMMAND_DRAW_MODE_TRIANGLE,
.enable_wireframe = false,
.instance = {0},
.material = {
.texture = model_textures,
.shader = {
.data = shader,
.uniforms = material->shader.uniforms,
}
}
);
};

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];
}
}
}

gluniforms_t *u = &cmd.material.shader.uniforms;

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++;
}

renderqueue_pass_command(&global_engine->systems.renderqueue, cmd);
}
}
}

21 changes: 21 additions & 0 deletions ecs/systems/uniform_resolve.h
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading