mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Render dynamic meshes
This commit is contained in:
parent
c86809af66
commit
977da197e2
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
if (!dynamic_list->empty()) {
|
||||||
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline,
|
DrawRenderList(draw_buffer, *dynamic_list);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
@ -14,62 +14,8 @@ 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());
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
list_needs_rebuild_ = false;
|
list_needs_rebuild_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +27,66 @@ void MeshRenderSystem::OnComponentInsert(uint32_t entity) {
|
|||||||
void MeshRenderSystem::OnUpdate(float ts) {
|
void MeshRenderSystem::OnUpdate(float ts) {
|
||||||
// do stuff
|
// do stuff
|
||||||
(void)ts;
|
(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
|
} // namespace engine
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user