Render dynamic meshes

This commit is contained in:
Bailey Harrison 2023-08-31 14:18:42 +01:00
parent c86809af66
commit 977da197e2
6 changed files with 127 additions and 96 deletions

View File

@ -33,7 +33,7 @@ class Renderer {
void PreRender(bool window_is_resized, glm::mat4 camera_transform);
// staticList can be nullptr to render nothing
void Render(const StaticRenderList* staticList);
void Render(const RenderList* static_list, const RenderList* dynamic_list);
// getters
@ -88,6 +88,10 @@ class Renderer {
const gfx::DescriptorSetLayout* material_set_layout; // set 2
float viewport_aspect_ratio_ = 1.0f;
const gfx::Pipeline* last_bound_pipeline_ = nullptr;
void DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list);
};
} // namespace engine

View File

@ -9,7 +9,7 @@
namespace engine {
struct StaticRenderListEntry {
struct RenderListEntry {
const gfx::Pipeline* pipeline;
const gfx::Buffer* vertex_buffer;
const gfx::Buffer* index_buffer;
@ -18,23 +18,29 @@ struct StaticRenderListEntry {
uint32_t index_count;
};
using StaticRenderList = std::vector<StaticRenderListEntry>;
using RenderList = std::vector<RenderListEntry>;
class MeshRenderSystem : public System {
public:
MeshRenderSystem(Scene* scene);
~MeshRenderSystem();
void RebuildRenderList();
const StaticRenderList* GetStaticRenderList() const { return &static_render_list_; }
void RebuildStaticRenderList();
const RenderList* GetStaticRenderList() const { return &static_render_list_; }
const RenderList* GetDynamicRenderList() const { return &dynamic_render_list_; }
void OnComponentInsert(uint32_t entity) override;
void OnUpdate(float ts) override;
private:
StaticRenderList static_render_list_;
RenderList static_render_list_;
RenderList dynamic_render_list_;
bool list_needs_rebuild_ = false;
// with_static_entities = false, build list of dynamic meshes
// with_static_entities = true, build list of static meshes
void BuildRenderList(RenderList& render_list, bool with_static_entities);
};
} // namespace engine

View File

@ -179,11 +179,12 @@ void Application::GameLoop() {
/* render */
renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix);
const StaticRenderList* staticList = nullptr;
if (scene) {
staticList = scene->GetSystem<MeshRenderSystem>()->GetStaticRenderList();
auto mesh_render_system = scene->GetSystem<MeshRenderSystem>();
const RenderList* static_list = mesh_render_system->GetStaticRenderList();
const RenderList* dynamic_list = mesh_render_system->GetDynamicRenderList();
renderer_->Render(static_list, dynamic_list);
}
renderer_->Render(staticList);
/* poll events */
window_->GetInputAndEvents();

View File

@ -90,40 +90,52 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) {
&frame_uniform.uniform_buffer_data);
}
void Renderer::Render(const StaticRenderList* staticList) {
void Renderer::Render(const RenderList* static_list,
const RenderList* dynamic_list) {
assert(static_list != nullptr);
assert(dynamic_list != nullptr);
last_bound_pipeline_ = nullptr;
gfx::DrawBuffer* draw_buffer = device_->BeginRender();
if (staticList && !staticList->empty()) {
const gfx::Pipeline* const first_pipeline = staticList->begin()->pipeline;
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline,
global_uniform.set, 0);
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline,
frame_uniform.set, 1);
device_->CmdBindPipeline(draw_buffer, first_pipeline);
const gfx::Pipeline* last_bound_pipeline = first_pipeline;
for (const auto& entry : *staticList) {
if (entry.pipeline != last_bound_pipeline) {
device_->CmdBindPipeline(draw_buffer, entry.pipeline);
last_bound_pipeline = entry.pipeline;
}
device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline,
entry.base_colour_texture, 2);
device_->CmdPushConstants(draw_buffer, entry.pipeline, 0,
sizeof(entry.model_matrix),
&entry.model_matrix);
if (entry.vertex_buffer) {
device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
}
if (entry.index_buffer) {
device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer);
}
device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
}
if (!static_list->empty()) {
DrawRenderList(draw_buffer, *static_list);
}
if (!dynamic_list->empty()) {
DrawRenderList(draw_buffer, *dynamic_list);
}
device_->FinishRender(draw_buffer);
}
void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer,
const RenderList& render_list) {
// if a pipeline hasn't been bound yet at all
if (last_bound_pipeline_ == nullptr) {
const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline;
// these bindings persist between all pipelines
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline,
global_uniform.set, 0);
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline,
frame_uniform.set, 1);
device_->CmdBindPipeline(draw_buffer, first_pipeline);
last_bound_pipeline_ = first_pipeline;
}
for (const auto& entry : render_list) {
if (entry.pipeline != last_bound_pipeline_) {
device_->CmdBindPipeline(draw_buffer, entry.pipeline);
last_bound_pipeline_ = entry.pipeline;
}
device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline,
entry.base_colour_texture, 2);
device_->CmdPushConstants(draw_buffer, entry.pipeline, 0,
sizeof(entry.model_matrix), &entry.model_matrix);
device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer);
device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
}
}
} // namespace engine

View File

@ -14,62 +14,8 @@ MeshRenderSystem::MeshRenderSystem(Scene* scene)
MeshRenderSystem::~MeshRenderSystem() {}
void MeshRenderSystem::RebuildRenderList() {
static_render_list_.clear();
static_render_list_.reserve(entities_.size());
std::unordered_map<const gfx::Pipeline*, int> render_orders;
for (uint32_t entity : entities_) {
auto transform = scene_->GetComponent<engine::TransformComponent>(entity);
if (transform->is_static == false) continue;
auto renderable = scene_->GetComponent<engine::RenderableComponent>(entity);
const gfx::Pipeline* pipeline =
renderable->material->GetShader()->GetPipeline();
static_render_list_.emplace_back(StaticRenderListEntry{
.pipeline = pipeline,
.vertex_buffer = renderable->mesh->GetVB(),
.index_buffer = renderable->mesh->GetIB(),
.base_colour_texture =
renderable->material->texture_->GetDescriptorSet(),
.model_matrix = transform->world_matrix,
.index_count = renderable->mesh->GetCount()});
if (render_orders.contains(pipeline) == false) {
render_orders.emplace(
pipeline, renderable->material->GetShader()->GetRenderOrder());
}
}
// sort the meshes by pipeline
auto sort_by_pipeline = [&render_orders](
const StaticRenderListEntry& e1,
const StaticRenderListEntry& e2) -> bool {
return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline));
};
std::sort(static_render_list_.begin(), static_render_list_.end(),
sort_by_pipeline);
#ifndef NDEBUG
LOG_TRACE("\nPRINTING RENDER LIST:\n");
for (const auto& entry : static_render_list_) {
LOG_TRACE("pipeline: {}", static_cast<const void*>(entry.pipeline));
LOG_TRACE("vertex_buffer: {}",
static_cast<const void*>(entry.vertex_buffer));
LOG_TRACE("index_buffer: {}", static_cast<const void*>(entry.index_buffer));
LOG_TRACE("base_color_texture: {}",
static_cast<const void*>(entry.base_colour_texture));
LOG_TRACE("transform position: {}, {}, {}", entry.model_matrix[3][0],
entry.model_matrix[3][1], entry.model_matrix[3][2]);
}
LOG_TRACE("\nRENDER LIST END\n");
#endif
void MeshRenderSystem::RebuildStaticRenderList() {
BuildRenderList(static_render_list_, true);
list_needs_rebuild_ = false;
}
@ -81,7 +27,66 @@ void MeshRenderSystem::OnComponentInsert(uint32_t entity) {
void MeshRenderSystem::OnUpdate(float ts) {
// do stuff
(void)ts;
if (list_needs_rebuild_) RebuildRenderList();
if (list_needs_rebuild_) {
RebuildStaticRenderList();
}
BuildRenderList(dynamic_render_list_, false);
}
void MeshRenderSystem::BuildRenderList(RenderList& render_list,
bool with_static_entities) {
render_list.clear();
render_list.reserve(entities_.size());
std::unordered_map<const gfx::Pipeline*, int> render_orders;
for (uint32_t entity : entities_) {
auto transform = scene_->GetComponent<engine::TransformComponent>(entity);
if (transform->is_static != with_static_entities) continue;
auto renderable = scene_->GetComponent<engine::RenderableComponent>(entity);
const gfx::Pipeline* pipeline =
renderable->material->GetShader()->GetPipeline();
render_list.emplace_back(
RenderListEntry{.pipeline = pipeline,
.vertex_buffer = renderable->mesh->GetVB(),
.index_buffer = renderable->mesh->GetIB(),
.base_colour_texture =
renderable->material->texture_->GetDescriptorSet(),
.model_matrix = transform->world_matrix,
.index_count = renderable->mesh->GetCount()});
if (render_orders.contains(pipeline) == false) {
render_orders.emplace(
pipeline, renderable->material->GetShader()->GetRenderOrder());
}
}
// sort the meshes by pipeline
auto sort_by_pipeline = [&render_orders](const RenderListEntry& e1,
const RenderListEntry& e2) -> bool {
return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline));
};
std::sort(render_list.begin(), render_list.end(), sort_by_pipeline);
#if 0
LOG_TRACE("\nPRINTING RENDER LIST ({})\n", with_static_entities ? "STATIC" : "DYNAMIC");
for (const auto& entry : render_list) {
LOG_TRACE("pipeline: {}", static_cast<const void*>(entry.pipeline));
LOG_TRACE("vertex_buffer: {}",
static_cast<const void*>(entry.vertex_buffer));
LOG_TRACE("index_buffer: {}", static_cast<const void*>(entry.index_buffer));
LOG_TRACE("base_color_texture: {}",
static_cast<const void*>(entry.base_colour_texture));
LOG_TRACE("transform position: {}, {}, {}", entry.model_matrix[3][0],
entry.model_matrix[3][1], entry.model_matrix[3][2]);
}
LOG_TRACE("\nRENDER LIST END\n");
#endif
}
} // namespace engine

View File

@ -136,7 +136,7 @@ void PlayGame(GameSettings settings) {
// app.GetResourcePath("models/test_scene.dae"));
auto cobbleHouse = engine::util::LoadMeshFromFile(
my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), true);
my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), false);
my_scene->GetComponent<engine::TransformComponent>(cobbleHouse)->position +=
glm::vec3{33.0f, 0.1f, 35.0f};
auto cobbleCustom =
@ -148,6 +148,9 @@ void PlayGame(GameSettings settings) {
static auto t =
my_scene->GetComponent<engine::TransformComponent>(cobbleHouse);
t->rotation *= glm::angleAxis(ts, glm::vec3{0.0f, 0.0f, 1.0f});
if (app.window()->GetKeyPress(engine::inputs::Key::K_F)) {
my_scene->GetSystem<engine::MeshRenderSystem>()->RebuildStaticRenderList();
}
};
/* some text */