add static rendering

This commit is contained in:
Bailey Harrison 2023-08-31 10:51:12 +01:00
parent f008b8a9ee
commit c86809af66
10 changed files with 91 additions and 43 deletions

View File

@ -8,6 +8,7 @@
#include <glm/trigonometric.hpp> #include <glm/trigonometric.hpp>
#include "gfx_device.h" #include "gfx_device.h"
#include "systems/mesh_render_system.h"
namespace engine { namespace engine {
@ -31,7 +32,8 @@ class Renderer {
void PreRender(bool window_is_resized, glm::mat4 camera_transform); void PreRender(bool window_is_resized, glm::mat4 camera_transform);
void Render(); // staticList can be nullptr to render nothing
void Render(const StaticRenderList* staticList);
// getters // getters

View File

@ -21,7 +21,8 @@ class SceneManager {
// creates an empty scene and sets it as active // creates an empty scene and sets it as active
Scene* CreateEmptyScene(); Scene* CreateEmptyScene();
void UpdateActiveScene(float ts); // returns active scene, nullptr if no scene active
Scene* UpdateActiveScene(float ts);
Scene* GetActiveScene() { return scenes_.at(active_scene_index_).get(); } Scene* GetActiveScene() { return scenes_.at(active_scene_index_).get(); }
private: private:

View File

@ -9,7 +9,7 @@
namespace engine { namespace engine {
struct MeshRenderListEntry { struct StaticRenderListEntry {
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,18 +18,21 @@ struct MeshRenderListEntry {
uint32_t index_count; uint32_t index_count;
}; };
using StaticRenderList = std::vector<StaticRenderListEntry>;
class MeshRenderSystem : public System { class MeshRenderSystem : public System {
public: public:
MeshRenderSystem(Scene* scene); MeshRenderSystem(Scene* scene);
~MeshRenderSystem(); ~MeshRenderSystem();
void RebuildRenderList(); void RebuildRenderList();
const StaticRenderList* GetStaticRenderList() const { return &static_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:
std::vector<MeshRenderListEntry> static_render_list_; StaticRenderList static_render_list_;
bool list_needs_rebuild_ = false; bool list_needs_rebuild_ = false;
}; };

View File

@ -8,7 +8,7 @@
namespace engine { namespace engine {
namespace util { namespace util {
uint32_t LoadMeshFromFile(Scene* parent, const std::string& path); uint32_t LoadMeshFromFile(Scene* parent, const std::string& path, bool is_static = false);
} // namespace util } // namespace util
} // namespace engine } // namespace engine

View File

@ -17,6 +17,8 @@
#include "resources/mesh.h" #include "resources/mesh.h"
#include "resources/shader.h" #include "resources/shader.h"
#include "resources/texture.h" #include "resources/texture.h"
#include "systems/mesh_render_system.h"
#include "components/transform.h"
#include "scene.h" #include "scene.h"
#include "scene_manager.h" #include "scene_manager.h"
#include "window.h" #include "window.h"
@ -148,8 +150,7 @@ Application::Application(const char* appName, const char* appVersion,
} }
} }
Application::~Application() { Application::~Application() {}
}
void Application::GameLoop() { void Application::GameLoop() {
LOG_DEBUG("Begin game loop..."); LOG_DEBUG("Begin game loop...");
@ -165,7 +166,7 @@ void Application::GameLoop() {
// single-threaded game loop // single-threaded game loop
while (window_->IsRunning()) { while (window_->IsRunning()) {
/* logic */ /* logic */
scene_manager_->UpdateActiveScene(window_->dt()); Scene* scene = scene_manager_->UpdateActiveScene(window_->dt());
uint64_t now = window_->GetNanos(); uint64_t now = window_->GetNanos();
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] { if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
@ -176,8 +177,13 @@ void Application::GameLoop() {
} }
/* render */ /* render */
renderer_->PreRender(window()->GetWindowResized(), glm::mat4{1.0f}); renderer_->PreRender(window()->GetWindowResized(), scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix);
renderer_->Render();
const StaticRenderList* staticList = nullptr;
if (scene) {
staticList = scene->GetSystem<MeshRenderSystem>()->GetStaticRenderList();
}
renderer_->Render(staticList);
/* poll events */ /* poll events */
window_->GetInputAndEvents(); window_->GetInputAndEvents();
@ -190,7 +196,7 @@ void Application::GameLoop() {
endFrame = beginFrame + FRAMETIME_LIMIT; endFrame = beginFrame + FRAMETIME_LIMIT;
} }
renderer()->GetDevice()->WaitIdle(); renderer_->GetDevice()->WaitIdle();
} }
} // namespace engine } // namespace engine

View File

@ -90,10 +90,39 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) {
&frame_uniform.uniform_buffer_data); &frame_uniform.uniform_buffer_data);
} }
void Renderer::Render() void Renderer::Render(const StaticRenderList* staticList) {
{
gfx::DrawBuffer* draw_buffer = device_->BeginRender(); 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);
}
}
device_->FinishRender(draw_buffer); device_->FinishRender(draw_buffer);
} }

View File

@ -22,11 +22,15 @@ namespace engine {
return scenes_.back().get(); return scenes_.back().get();
} }
void SceneManager::UpdateActiveScene(float ts) Scene* SceneManager::UpdateActiveScene(float ts)
{ {
if (active_scene_index_ >= 0) [[likely]] { if (active_scene_index_ >= 0) [[likely]] {
assert((size_t)active_scene_index_ < scenes_.size()); assert((size_t)active_scene_index_ < scenes_.size());
scenes_[active_scene_index_]->Update(ts); Scene* activeScene = scenes_[active_scene_index_].get();
activeScene->Update(ts);
return activeScene;
} else {
return nullptr;
} }
} }

View File

@ -30,7 +30,7 @@ void MeshRenderSystem::RebuildRenderList() {
const gfx::Pipeline* pipeline = const gfx::Pipeline* pipeline =
renderable->material->GetShader()->GetPipeline(); renderable->material->GetShader()->GetPipeline();
static_render_list_.emplace_back(MeshRenderListEntry{ static_render_list_.emplace_back(StaticRenderListEntry{
.pipeline = pipeline, .pipeline = pipeline,
.vertex_buffer = renderable->mesh->GetVB(), .vertex_buffer = renderable->mesh->GetVB(),
.index_buffer = renderable->mesh->GetIB(), .index_buffer = renderable->mesh->GetIB(),
@ -47,8 +47,8 @@ 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 MeshRenderListEntry& e1, const StaticRenderListEntry& e1,
const MeshRenderListEntry& 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));
}; };
@ -74,6 +74,7 @@ void MeshRenderSystem::RebuildRenderList() {
} }
void MeshRenderSystem::OnComponentInsert(uint32_t entity) { void MeshRenderSystem::OnComponentInsert(uint32_t entity) {
(void)entity;
list_needs_rebuild_ = true; list_needs_rebuild_ = true;
} }

View File

@ -31,7 +31,7 @@ namespace engine::util {
const std::map<int, std::shared_ptr<resources::Texture>>& textures, const std::map<int, std::shared_ptr<resources::Texture>>& textures,
const std::vector<std::shared_ptr<resources::Mesh>>& meshes, const std::vector<std::shared_ptr<resources::Mesh>>& meshes,
const std::vector<unsigned int>& meshTextureIndices, const std::vector<unsigned int>& meshTextureIndices,
aiNode* parentNode, Scene* scene, uint32_t parentObj) aiNode* parentNode, Scene* scene, uint32_t parentObj, bool is_static)
{ {
// convert to glm column major // convert to glm column major
@ -71,10 +71,12 @@ namespace engine::util {
parentTransform->position = position; parentTransform->position = position;
parentTransform->scale = scale; parentTransform->scale = scale;
parentTransform->rotation = rotation; parentTransform->rotation = rotation;
parentTransform->is_static = is_static;
for (uint32_t i = 0; i < parentNode->mNumMeshes; i++) { for (uint32_t i = 0; i < parentNode->mNumMeshes; i++) {
// create child node for each mesh // create child node for each mesh
auto child = scene->CreateEntity("_mesh" + std::to_string(i), parentObj); auto child = scene->CreateEntity("_mesh" + std::to_string(i), parentObj);
scene->GetComponent<TransformComponent>(child)->is_static = is_static;
auto childRenderer = scene->AddComponent<RenderableComponent>(child); auto childRenderer = scene->AddComponent<RenderableComponent>(child);
childRenderer->mesh = meshes[parentNode->mMeshes[i]]; childRenderer->mesh = meshes[parentNode->mMeshes[i]];
childRenderer->material = std::make_shared<resources::Material>(scene->app()->GetResource<resources::Shader>("builtin.standard")); childRenderer->material = std::make_shared<resources::Material>(scene->app()->GetResource<resources::Shader>("builtin.standard"));
@ -92,12 +94,12 @@ namespace engine::util {
meshTextureIndices, meshTextureIndices,
parentNode->mChildren[i], parentNode->mChildren[i],
scene, scene,
scene->CreateEntity("child" + std::to_string(i), parentObj) scene->CreateEntity("child" + std::to_string(i), parentObj), is_static
); );
} }
} }
uint32_t LoadMeshFromFile(Scene* parent, const std::string& path) uint32_t LoadMeshFromFile(Scene* parent, const std::string& path, bool is_static)
{ {
Assimp::Importer importer; Assimp::Importer importer;
@ -231,7 +233,7 @@ namespace engine::util {
uint32_t obj = parent->CreateEntity(scene->GetShortFilename(path.c_str())); uint32_t obj = parent->CreateEntity(scene->GetShortFilename(path.c_str()));
buildGraph(textures, meshes, meshMaterialIndices, scene->mRootNode, parent, obj); buildGraph(textures, meshes, meshMaterialIndices, scene->mRootNode, parent, obj, is_static);
LOG_INFO("Loaded model: {}, meshes: {}, textures: {}", scene->GetShortFilename(path.c_str()), meshes.size(), textures.size()); LOG_INFO("Loaded model: {}, meshes: {}, textures: {}", scene->GetShortFilename(path.c_str()), meshes.size(), textures.size());

View File

@ -53,7 +53,7 @@ void PlayGame(GameSettings settings) {
engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphics_settings); engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphics_settings);
app.SetFrameLimiter(settings.enable_frame_limiter); app.SetFrameLimiter(settings.enable_frame_limiter);
app.window()->SetRelativeMouseMode(false); app.window()->SetRelativeMouseMode(true);
ConfigureInputs(app.input_manager()); ConfigureInputs(app.input_manager());
{ {
@ -79,14 +79,14 @@ void PlayGame(GameSettings settings) {
} }
/* shared resources */ /* shared resources */
/* auto grass_texture = std::make_shared<engine::resources::Texture>( auto grass_texture = std::make_shared<engine::resources::Texture>(
app.renderer(), app.GetResourcePath("textures/grass.jpg"), app.renderer(), app.GetResourcePath("textures/grass.jpg"),
engine::resources::Texture::Filtering::kAnisotropic); engine::resources::Texture::Filtering::kAnisotropic);
auto space_texture = std::make_shared<engine::resources::Texture>( auto space_texture = std::make_shared<engine::resources::Texture>(
app.renderer(), app.GetResourcePath("textures/space2.png"), app.renderer(), app.GetResourcePath("textures/space2.png"),
engine::resources::Texture::Filtering::kAnisotropic); engine::resources::Texture::Filtering::kAnisotropic);
*/
/* skybox */ /* skybox */
{ {
uint32_t skybox = my_scene->CreateEntity("skybox"); uint32_t skybox = my_scene->CreateEntity("skybox");
@ -97,7 +97,7 @@ void PlayGame(GameSettings settings) {
std::make_unique<engine::resources::Material>( std::make_unique<engine::resources::Material>(
app.GetResource<engine::resources::Shader>("builtin.skybox")); app.GetResource<engine::resources::Shader>("builtin.skybox"));
skybox_renderable->material->texture_ = skybox_renderable->material->texture_ =
app.GetResource<engine::resources::Texture>("builtin.white"); space_texture;
skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), skybox_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(),
10.0f, 10.0f, 10.0f, 1.0f, true); 10.0f, 10.0f, 10.0f, 1.0f, true);
@ -122,7 +122,7 @@ void PlayGame(GameSettings settings) {
std::make_shared<engine::resources::Material>( std::make_shared<engine::resources::Material>(
app.GetResource<engine::resources::Shader>("builtin.standard")); app.GetResource<engine::resources::Shader>("builtin.standard"));
floor_renderable->material->texture_ = floor_renderable->material->texture_ =
app.GetResource<engine::resources::Texture>("builtin.white"); grass_texture;
floor_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(), floor_renderable->mesh = GenCuboidMesh(app.renderer()->GetDevice(),
100.0f, 0.1f, 100.0f, 100.0f); 100.0f, 0.1f, 100.0f, 100.0f);
@ -135,20 +135,20 @@ void PlayGame(GameSettings settings) {
// engine::util::LoadMeshFromFile(my_scene, // engine::util::LoadMeshFromFile(my_scene,
// 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")); my_scene, app.GetResourcePath("models/cobble_house/cobble_house.dae"), true);
//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 =
// my_scene->AddComponent<engine::CustomComponent>(cobbleHouse); my_scene->AddComponent<engine::CustomComponent>(cobbleHouse);
//cobbleCustom->onInit = [](void) { cobbleCustom->onInit = [](void) {
// LOG_INFO("Cobble house spin component initialised!"); LOG_INFO("Cobble house spin component initialised!");
//}; };
//cobbleCustom->onUpdate = [&](float ts) { cobbleCustom->onUpdate = [&](float ts) {
// 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});
//}; };
/* some text */ /* some text */
{ {