Implement Mesh partitioning

This commit is contained in:
2026-09-27 17:48:22 +02:00
parent 11426fe8fb
commit 850a6f601b
21 changed files with 1146638 additions and 181 deletions

View File

@@ -49,31 +49,65 @@ void Renderer::draw_scene(const Scene& scene, const Camera& camera,
{
update_global_data(scene, camera, screen_width, screen_height);
// Sort Entities: Shader -> Material -> Entities
using RenderQueue = std::unordered_map<Shader*, std::unordered_map<Material*, std::vector<const Entity*>>>;
struct DrawCommand
{
const Transform* transform;
const Mesh* mesh;
GLuint index_offset;
GLuint index_count;
};
// Sort Entities: Shader -> Material -> SubMesh Draw Commands
using RenderQueue = std::unordered_map<Shader*, std::unordered_map<Material*, std::vector<DrawCommand>>>;
RenderQueue render_queue;
for (const auto& entity : scene.get_entities()) {
if (!entity.mesh || !entity.material || !entity.material->shader) {
// Ignore empty entities
continue;
}
if (!entity.mesh) { continue; }
Shader* shader_ptr = entity.material->shader.get();
Material* material_ptr = entity.material.get();
render_queue[shader_ptr][material_ptr].push_back(&entity);
// If Entity has an explicit material override
if (entity.material) {
if (!entity.material->shader) { continue; }
Shader* shader_ptr = entity.material->shader.get();
Material* material_ptr = entity.material.get();
for (const auto& submesh : entity.mesh->get_submeshes()) {
render_queue[shader_ptr][material_ptr].push_back({
&entity.transform,
entity.mesh.get(),
submesh.index_offset,
submesh.index_count
});
}
// Otherwise use SubMesh's native material
} else {
for (const auto& submesh : entity.mesh->get_submeshes()) {
if (!submesh.material || !submesh.material->shader) { continue; }
Shader* shader_ptr = submesh.material->shader.get();
Material* material_ptr = submesh.material.get();
render_queue[shader_ptr][material_ptr].push_back({
&entity.transform,
entity.mesh.get(),
submesh.index_offset,
submesh.index_count
});
}
}
}
// Draw using the sorted queue
// Execute sorted queue for minimal state switching
for (const auto& [shader, materials] : render_queue) {
shader->bind();
for (const auto& [material, entities] : materials) {
for (const auto& [material, draw_command] : materials) {
material->bind();
for (const auto& entity : entities) {
shader->set_mat4("u_model", entity->transform.get_model_matrix());
entity->mesh->draw();
for (const auto& cmd: draw_command) {
shader->set_mat4("u_model", cmd.transform->get_model_matrix());
cmd.mesh->draw_submesh(cmd.index_offset, cmd.index_count);
}
}
}