Implement Mesh partitioning
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user