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); void PreRender(bool window_is_resized, glm::mat4 camera_transform);
// staticList can be nullptr to render nothing // staticList can be nullptr to render nothing
void Render(const StaticRenderList* staticList); void Render(const RenderList* static_list, const RenderList* dynamic_list);
// getters // getters
@ -88,6 +88,10 @@ class Renderer {
const gfx::DescriptorSetLayout* material_set_layout; // set 2 const gfx::DescriptorSetLayout* material_set_layout; // set 2
float viewport_aspect_ratio_ = 1.0f; 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 } // namespace engine

View File

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

View File

@ -179,11 +179,12 @@ void Application::GameLoop() {
/* render */ /* render */
renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix); renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix);
const StaticRenderList* staticList = nullptr;
if (scene) { 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 */ /* poll events */
window_->GetInputAndEvents(); window_->GetInputAndEvents();

View File

@ -90,40 +90,52 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) {
&frame_uniform.uniform_buffer_data); &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(); gfx::DrawBuffer* draw_buffer = device_->BeginRender();
if (staticList && !staticList->empty()) { if (!static_list->empty()) {
const gfx::Pipeline* const first_pipeline = staticList->begin()->pipeline; DrawRenderList(draw_buffer, *static_list);
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 (!dynamic_list->empty()) {
DrawRenderList(draw_buffer, *dynamic_list);
} }
device_->FinishRender(draw_buffer); 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 } // namespace engine

View File

@ -14,24 +14,44 @@ MeshRenderSystem::MeshRenderSystem(Scene* scene)
MeshRenderSystem::~MeshRenderSystem() {} MeshRenderSystem::~MeshRenderSystem() {}
void MeshRenderSystem::RebuildRenderList() { void MeshRenderSystem::RebuildStaticRenderList() {
static_render_list_.clear(); BuildRenderList(static_render_list_, true);
static_render_list_.reserve(entities_.size()); list_needs_rebuild_ = false;
}
void MeshRenderSystem::OnComponentInsert(uint32_t entity) {
(void)entity;
list_needs_rebuild_ = true;
}
void MeshRenderSystem::OnUpdate(float ts) {
// do stuff
(void)ts;
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; std::unordered_map<const gfx::Pipeline*, int> render_orders;
for (uint32_t entity : entities_) { for (uint32_t entity : entities_) {
auto transform = scene_->GetComponent<engine::TransformComponent>(entity); auto transform = scene_->GetComponent<engine::TransformComponent>(entity);
if (transform->is_static == false) continue; if (transform->is_static != with_static_entities) continue;
auto renderable = scene_->GetComponent<engine::RenderableComponent>(entity); auto renderable = scene_->GetComponent<engine::RenderableComponent>(entity);
const gfx::Pipeline* pipeline = const gfx::Pipeline* pipeline =
renderable->material->GetShader()->GetPipeline(); renderable->material->GetShader()->GetPipeline();
static_render_list_.emplace_back(StaticRenderListEntry{ render_list.emplace_back(
.pipeline = pipeline, RenderListEntry{.pipeline = pipeline,
.vertex_buffer = renderable->mesh->GetVB(), .vertex_buffer = renderable->mesh->GetVB(),
.index_buffer = renderable->mesh->GetIB(), .index_buffer = renderable->mesh->GetIB(),
.base_colour_texture = .base_colour_texture =
@ -46,18 +66,16 @@ void MeshRenderSystem::RebuildRenderList() {
} }
// sort the meshes by pipeline // sort the meshes by pipeline
auto sort_by_pipeline = [&render_orders]( auto sort_by_pipeline = [&render_orders](const RenderListEntry& e1,
const StaticRenderListEntry& e1, const RenderListEntry& e2) -> bool {
const StaticRenderListEntry& e2) -> bool {
return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline)); return (render_orders.at(e1.pipeline) < render_orders.at(e2.pipeline));
}; };
std::sort(static_render_list_.begin(), static_render_list_.end(), std::sort(render_list.begin(), render_list.end(), sort_by_pipeline);
sort_by_pipeline);
#ifndef NDEBUG #if 0
LOG_TRACE("\nPRINTING RENDER LIST:\n"); LOG_TRACE("\nPRINTING RENDER LIST ({})\n", with_static_entities ? "STATIC" : "DYNAMIC");
for (const auto& entry : static_render_list_) { for (const auto& entry : render_list) {
LOG_TRACE("pipeline: {}", static_cast<const void*>(entry.pipeline)); LOG_TRACE("pipeline: {}", static_cast<const void*>(entry.pipeline));
LOG_TRACE("vertex_buffer: {}", LOG_TRACE("vertex_buffer: {}",
static_cast<const void*>(entry.vertex_buffer)); static_cast<const void*>(entry.vertex_buffer));
@ -69,19 +87,6 @@ void MeshRenderSystem::RebuildRenderList() {
} }
LOG_TRACE("\nRENDER LIST END\n"); LOG_TRACE("\nRENDER LIST END\n");
#endif #endif
list_needs_rebuild_ = false;
}
void MeshRenderSystem::OnComponentInsert(uint32_t entity) {
(void)entity;
list_needs_rebuild_ = true;
}
void MeshRenderSystem::OnUpdate(float ts) {
// do stuff
(void)ts;
if (list_needs_rebuild_) RebuildRenderList();
} }
} // namespace engine } // namespace engine

View File

@ -136,7 +136,7 @@ void PlayGame(GameSettings settings) {
// app.GetResourcePath("models/test_scene.dae")); // app.GetResourcePath("models/test_scene.dae"));
auto cobbleHouse = engine::util::LoadMeshFromFile( 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 += my_scene->GetComponent<engine::TransformComponent>(cobbleHouse)->position +=
glm::vec3{33.0f, 0.1f, 35.0f}; glm::vec3{33.0f, 0.1f, 35.0f};
auto cobbleCustom = auto cobbleCustom =
@ -148,6 +148,9 @@ void PlayGame(GameSettings settings) {
static auto t = static auto t =
my_scene->GetComponent<engine::TransformComponent>(cobbleHouse); my_scene->GetComponent<engine::TransformComponent>(cobbleHouse);
t->rotation *= glm::angleAxis(ts, glm::vec3{0.0f, 0.0f, 1.0f}); 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 */ /* some text */