mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-20 20:41:19 +00:00
optimise ecs; build static mesh render lists
This commit is contained in:
parent
75938ba83d
commit
6a8c8b1c3e
@ -17,6 +17,7 @@ set(SRC_FILES
|
||||
"src/input_manager.cpp"
|
||||
"src/libs/stb_image.cpp"
|
||||
"src/libs/stb_truetype.cpp"
|
||||
"src/renderer.cpp"
|
||||
"src/resources/font.cpp"
|
||||
"src/resources/material.cpp"
|
||||
"src/resources/mesh.cpp"
|
||||
@ -26,7 +27,8 @@ set(SRC_FILES
|
||||
"src/scene_manager.cpp"
|
||||
"src/systems/collisions.cpp"
|
||||
"src/systems/custom_behaviour.cpp"
|
||||
"src/systems/render.cpp"
|
||||
"src/systems/mesh_render_system.cpp"
|
||||
"src/systems/text_render_system.cpp"
|
||||
"src/systems/transform.cpp"
|
||||
"src/util/files.cpp"
|
||||
"src/util/model_loader.cpp"
|
||||
@ -45,7 +47,8 @@ set(INCLUDE_FILES
|
||||
"include/application.h"
|
||||
"include/components/collider.h"
|
||||
"include/components/custom.h"
|
||||
"include/components/renderable.h"
|
||||
"include/components/mesh_renderable.h"
|
||||
"include/components/text_renderable.h"
|
||||
"include/components/transform.h"
|
||||
"include/ecs_system.h"
|
||||
"include/engine_api.h"
|
||||
@ -57,6 +60,7 @@ set(INCLUDE_FILES
|
||||
"include/inputs/mouse.h"
|
||||
"include/log.h"
|
||||
"include/logger.h"
|
||||
"include/renderer.h"
|
||||
"include/resource_manager.h"
|
||||
"include/resources/font.h"
|
||||
"include/resources/material.h"
|
||||
@ -67,7 +71,8 @@ set(INCLUDE_FILES
|
||||
"include/scene_manager.h"
|
||||
"include/systems/collisions.h"
|
||||
"include/systems/custom_behaviour.h"
|
||||
"include/systems/render.h"
|
||||
"include/systems/mesh_render_system.h"
|
||||
"include/systems/text_render_system.h"
|
||||
"include/systems/transform.h"
|
||||
"include/util.h"
|
||||
"include/util/files.h"
|
||||
|
@ -35,4 +35,10 @@ Order of execution for rendering:
|
||||
5. Call GFXDevice::FinishRender()
|
||||
|
||||
IMRPOVING RENDER SYSTEMS
|
||||
Callbacks such as OnComponentInsert() and OnComponentRemove() should be used to
|
||||
The systems should maintain a cache of the buffer pointers, material info, etc. A RebuildCache() function
|
||||
should be added to update the cache
|
||||
|
||||
|
||||
|
||||
PROFILING
|
||||
Fps before: 3271
|
2
dependencies/VulkanMemoryAllocator
vendored
2
dependencies/VulkanMemoryAllocator
vendored
@ -1 +1 @@
|
||||
Subproject commit 0e89587db3ebee4d463f191bd296374c5fafc8ea
|
||||
Subproject commit c351692490513cdb0e5a2c925aaf7ea4a9b672f4
|
@ -13,10 +13,9 @@ struct AABB {
|
||||
};
|
||||
|
||||
struct ColliderComponent {
|
||||
bool is_static = true;
|
||||
bool is_trigger =
|
||||
false; // entity receives an event on collision enter and exit
|
||||
AABB aabb{}; // broad phase
|
||||
bool is_static;
|
||||
bool is_trigger; // entity receives an event on collision enter and exit
|
||||
AABB aabb; // broad phase
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef ENGINE_INCLUDE_COMPONENTS_RENDERABLE_H_
|
||||
#define ENGINE_INCLUDE_COMPONENTS_RENDERABLE_H_
|
||||
#ifndef ENGINE_INCLUDE_COMPONENTS_MESH_RENDERABLE_H_
|
||||
#define ENGINE_INCLUDE_COMPONENTS_MESH_RENDERABLE_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -11,9 +11,6 @@ namespace engine {
|
||||
struct RenderableComponent {
|
||||
std::shared_ptr<resources::Mesh> mesh;
|
||||
std::shared_ptr<resources::Material> material;
|
||||
bool shown = true;
|
||||
uint32_t index_count_override =
|
||||
0; // for shaders that don't use vertex/index buffers, 0 means ignored
|
||||
};
|
||||
|
||||
} // namespace engine
|
8
include/components/text_renderable.h
Normal file
8
include/components/text_renderable.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef ENGINE_INCLUDE_COMPONENTS_TEXT_RENDERABLE_H_
|
||||
#define ENGINE_INCLUDE_COMPONENTS_TEXT_RENDERABLE_H_
|
||||
|
||||
namespace engine {
|
||||
|
||||
} // namespace engine
|
||||
|
||||
#endif
|
@ -10,14 +10,16 @@
|
||||
namespace engine {
|
||||
|
||||
struct TransformComponent {
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
glm::vec3 scale;
|
||||
|
||||
glm::mat4 world_matrix;
|
||||
|
||||
glm::quat rotation;
|
||||
glm::vec3 position;
|
||||
glm::vec3 scale;
|
||||
|
||||
std::string tag;
|
||||
uint32_t parent;
|
||||
|
||||
bool is_static;
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace engine {
|
||||
@ -23,23 +24,24 @@ template <typename T>
|
||||
class ComponentArray : public IComponentArray {
|
||||
public:
|
||||
void InsertData(uint32_t entity, T component) {
|
||||
assert(component_array_.find(entity) == component_array_.end() &&
|
||||
"Adding component which already exists to entity");
|
||||
component_array_.emplace(entity, component);
|
||||
if (component_array_.size() < entity + 1) {
|
||||
component_array_.resize(entity + 1);
|
||||
}
|
||||
// bounds checking here as not performance critical
|
||||
component_array_.at(entity) = component;
|
||||
}
|
||||
|
||||
void DeleteData(uint32_t entity) { component_array_.erase(entity); }
|
||||
void DeleteData(uint32_t entity) {
|
||||
(void)entity; // TODO
|
||||
}
|
||||
|
||||
T* GetData(uint32_t entity) {
|
||||
if (component_array_.contains(entity)) {
|
||||
return &(component_array_.at(entity));
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
assert(entity < component_array_.size());
|
||||
return &component_array_[entity];
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<uint32_t, T> component_array_{};
|
||||
std::vector<T> component_array_{};
|
||||
};
|
||||
|
||||
class System {
|
||||
|
8
include/renderer.h
Normal file
8
include/renderer.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef ENGINE_INCLUDE_RENDERER_H_
|
||||
#define ENGINE_INCLUDE_RENDERER_H_
|
||||
|
||||
namespace engine {
|
||||
|
||||
} // namespace engine
|
||||
|
||||
#endif
|
@ -31,7 +31,8 @@ class Scene {
|
||||
|
||||
/* ecs stuff */
|
||||
|
||||
uint32_t CreateEntity(const std::string& tag, uint32_t parent = 0, const glm::vec3& pos = glm::vec3{0.0f, 0.0f, 0.0f});
|
||||
uint32_t CreateEntity(const std::string& tag, uint32_t parent = 0,
|
||||
const glm::vec3& pos = glm::vec3{0.0f, 0.0f, 0.0f});
|
||||
|
||||
uint32_t GetEntity(const std::string& tag, uint32_t parent = 0);
|
||||
|
||||
@ -70,7 +71,7 @@ class Scene {
|
||||
auto& signature_ref = signatures_.at(entity);
|
||||
signature_ref.set(signature_position);
|
||||
|
||||
for (auto& [system_name, system] : systems_) {
|
||||
for (auto& [system_hash, system] : ecs_systems_) {
|
||||
if (system->entities_.contains(entity)) continue;
|
||||
if ((system->signature_ & signature_ref) == system->signature_) {
|
||||
system->entities_.insert(entity);
|
||||
@ -84,27 +85,29 @@ class Scene {
|
||||
template <typename T>
|
||||
void RegisterSystem() {
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(systems_.find(hash) == systems_.end() &&
|
||||
"Registering system more than once.");
|
||||
systems_.emplace(hash, std::make_unique<T>(this));
|
||||
ecs_systems_.emplace_back(hash, std::make_unique<T>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* GetSystem() {
|
||||
size_t hash = typeid(T).hash_code();
|
||||
auto it = systems_.find(hash);
|
||||
if (it == systems_.end()) {
|
||||
throw std::runtime_error("Cannot find ecs system.");
|
||||
System* found_system = nullptr;
|
||||
for (auto& [system_hash, system] : ecs_systems_) {
|
||||
if (hash == system_hash) found_system = system.get();
|
||||
}
|
||||
if (found_system == nullptr) {
|
||||
throw std::runtime_error("Unable to find system");
|
||||
}
|
||||
T* casted_ptr = dynamic_cast<T*>(found_system);
|
||||
if (casted_ptr == nullptr) {
|
||||
throw std::runtime_error("Failed to cast system pointer!");
|
||||
}
|
||||
auto ptr = it->second.get();
|
||||
auto casted_ptr = dynamic_cast<T*>(ptr);
|
||||
assert(casted_ptr != nullptr);
|
||||
return casted_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Application* const app_;
|
||||
uint32_t next_entity_id_ = 1000;
|
||||
uint32_t next_entity_id_ = 1; // 0 is not a valid entity
|
||||
|
||||
uint64_t framecount_ = 0;
|
||||
|
||||
@ -112,13 +115,15 @@ class Scene {
|
||||
|
||||
size_t next_signature_position_ = 0;
|
||||
// maps component hashes to signature positions
|
||||
std::map<size_t, size_t> component_signature_positions_{};
|
||||
std::unordered_map<size_t, size_t> component_signature_positions_{};
|
||||
// maps entity ids to their signatures
|
||||
std::map<uint32_t, std::bitset<kMaxComponents>> signatures_{};
|
||||
std::unordered_map<uint32_t, std::bitset<kMaxComponents>> signatures_{};
|
||||
// maps component hashes to their arrays
|
||||
std::map<size_t, std::unique_ptr<IComponentArray>> component_arrays_{};
|
||||
// maps system hashes to their class instantiations
|
||||
std::map<size_t, std::unique_ptr<System>> systems_{};
|
||||
std::unordered_map<size_t, std::unique_ptr<IComponentArray>>
|
||||
component_arrays_{};
|
||||
|
||||
// hashes and associated systems
|
||||
std::vector<std::pair<size_t, std::unique_ptr<System>>> ecs_systems_{};
|
||||
|
||||
template <typename T>
|
||||
ComponentArray<T>* GetComponentArray() {
|
||||
|
@ -22,6 +22,7 @@ class SceneManager {
|
||||
Scene* CreateEmptyScene();
|
||||
|
||||
void UpdateActiveScene(float ts);
|
||||
Scene* GetActiveScene() { return scenes_.at(active_scene_index_).get(); }
|
||||
|
||||
private:
|
||||
Application* const app_;
|
||||
|
40
include/systems/mesh_render_system.h
Normal file
40
include/systems/mesh_render_system.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef ENGINE_INCLUDE_SYSTEMS_MESH_RENDER_SYSTEM_H_
|
||||
#define ENGINE_INCLUDE_SYSTEMS_MESH_RENDER_SYSTEM_H_
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
#include "ecs_system.h"
|
||||
#include "scene.h"
|
||||
#include "gfx.h"
|
||||
|
||||
namespace engine {
|
||||
|
||||
struct MeshRenderListEntry {
|
||||
const gfx::Pipeline* pipeline;
|
||||
const gfx::Buffer* vertex_buffer;
|
||||
const gfx::Buffer* index_buffer;
|
||||
const gfx::DescriptorSet* base_colour_texture;
|
||||
glm::mat4 model_matrix;
|
||||
uint32_t index_count;
|
||||
// 100 bytes
|
||||
};
|
||||
|
||||
class MeshRenderSystem : public System {
|
||||
public:
|
||||
MeshRenderSystem(Scene* scene);
|
||||
~MeshRenderSystem();
|
||||
|
||||
void RebuildRenderList();
|
||||
|
||||
void OnComponentInsert(uint32_t entity) override;
|
||||
void OnUpdate(float ts) override;
|
||||
|
||||
private:
|
||||
std::vector<MeshRenderListEntry> static_render_list_;
|
||||
bool list_needs_rebuild_ = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
#ifndef ENGINE_INCLUDE_SYSTEMS_RENDER_H_
|
||||
#define ENGINE_INCLUDE_SYSTEMS_RENDER_H_
|
||||
|
||||
#include "components/renderable.h"
|
||||
#include "components/transform.h"
|
||||
#include "ecs_system.h"
|
||||
#include "gfx.h"
|
||||
#include "gfx_device.h"
|
||||
#include "log.h"
|
||||
#include "scene.h"
|
||||
|
||||
namespace engine {
|
||||
|
||||
class RenderSystem : public System {
|
||||
public:
|
||||
RenderSystem(Scene* scene);
|
||||
~RenderSystem();
|
||||
|
||||
void OnUpdate(float ts) override;
|
||||
|
||||
void SetCameraEntity(uint32_t entity);
|
||||
|
||||
private:
|
||||
GFXDevice* const gfx_;
|
||||
|
||||
struct {
|
||||
// only uses transform component, which is required for all entities anyway
|
||||
uint32_t cam_entity = 0;
|
||||
float vertical_fov_degrees = 70.0f;
|
||||
float clip_near = 0.5f;
|
||||
float clip_far = 10000.0f;
|
||||
} camera_;
|
||||
|
||||
float viewport_aspect_ratio_ = 1.0f;
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
|
||||
#endif
|
8
include/systems/text_render_system.h
Normal file
8
include/systems/text_render_system.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef ENGINE_INCLUDE_SYSTEMS_TEXT_RENDER_SYSTEM_H_
|
||||
#define ENGINE_INCLUDE_SYSTEMS_TEXT_RENDER_SYSTEM_H_
|
||||
|
||||
namespace engine {
|
||||
|
||||
} // namespace engine
|
||||
|
||||
#endif
|
@ -233,6 +233,9 @@ void Application::GameLoop() {
|
||||
window_->ResetAvgFPS();
|
||||
}
|
||||
|
||||
/* render */
|
||||
|
||||
|
||||
/* poll events */
|
||||
window_->GetInputAndEvents();
|
||||
|
||||
|
@ -845,10 +845,11 @@ void GFXDevice::CmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount,
|
||||
}
|
||||
|
||||
void GFXDevice::CmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count,
|
||||
uint32_t instance_count, uint32_t first_vertex,
|
||||
uint32_t first_instance) {
|
||||
uint32_t instance_count, uint32_t first_vertex,
|
||||
uint32_t first_instance) {
|
||||
assert(drawBuffer != nullptr);
|
||||
vkCmdDraw(drawBuffer->frameData.drawBuf, vertex_count, instance_count, first_vertex, first_instance);
|
||||
vkCmdDraw(drawBuffer->frameData.drawBuf, vertex_count, instance_count,
|
||||
first_vertex, first_instance);
|
||||
}
|
||||
|
||||
void GFXDevice::CmdPushConstants(gfx::DrawBuffer* drawBuffer,
|
||||
@ -874,17 +875,20 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info) {
|
||||
|
||||
gfx::Pipeline* pipeline = new gfx::Pipeline;
|
||||
|
||||
auto vertShaderCode = util::ReadTextFile(info.vert_shader_path);
|
||||
auto fragShaderCode = util::ReadTextFile(info.frag_shader_path);
|
||||
|
||||
LOG_INFO("vert shader vector size: {}", vertShaderCode->size());
|
||||
|
||||
VkShaderModule vertShaderModule =
|
||||
compileShader(pimpl->device.device, shaderc_vertex_shader,
|
||||
vertShaderCode->data(), info.vert_shader_path);
|
||||
VkShaderModule fragShaderModule =
|
||||
compileShader(pimpl->device.device, shaderc_fragment_shader,
|
||||
fragShaderCode->data(), info.frag_shader_path);
|
||||
VkShaderModule vertShaderModule;
|
||||
VkShaderModule fragShaderModule;
|
||||
{
|
||||
auto vertShaderCode = util::ReadTextFile(info.vert_shader_path);
|
||||
vertShaderModule =
|
||||
compileShader(pimpl->device.device, shaderc_vertex_shader,
|
||||
vertShaderCode->data(), info.vert_shader_path);
|
||||
}
|
||||
{
|
||||
auto fragShaderCode = util::ReadTextFile(info.frag_shader_path);
|
||||
fragShaderModule =
|
||||
compileShader(pimpl->device.device, shaderc_fragment_shader,
|
||||
fragShaderCode->data(), info.frag_shader_path);
|
||||
}
|
||||
|
||||
// get vertex attrib layout:
|
||||
VkVertexInputBindingDescription bindingDescription{};
|
||||
|
5
src/renderer.cpp
Normal file
5
src/renderer.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "renderer.h"
|
||||
|
||||
namespace engine {
|
||||
|
||||
} // namespace engine
|
@ -1,11 +1,11 @@
|
||||
#include "scene.h"
|
||||
|
||||
#include "components/transform.h"
|
||||
#include "components/renderable.h"
|
||||
#include "components/mesh_renderable.h"
|
||||
#include "components/collider.h"
|
||||
#include "components/custom.h"
|
||||
#include "systems/transform.h"
|
||||
#include "systems/render.h"
|
||||
#include "systems/mesh_render_system.h"
|
||||
#include "systems/collisions.h"
|
||||
#include "systems/custom_behaviour.h"
|
||||
|
||||
@ -25,8 +25,8 @@ Scene::Scene(Application* app) : app_(app) {
|
||||
// Order here matters:
|
||||
RegisterSystem<TransformSystem>();
|
||||
RegisterSystem<PhysicsSystem>();
|
||||
RegisterSystem<RenderSystem>();
|
||||
RegisterSystem<CustomBehaviourSystem>();
|
||||
RegisterSystem<MeshRenderSystem>();
|
||||
}
|
||||
|
||||
Scene::~Scene() {}
|
||||
@ -58,7 +58,7 @@ size_t Scene::GetComponentSignaturePosition(size_t hash) {
|
||||
}
|
||||
|
||||
void Scene::Update(float ts) {
|
||||
for (auto& [name, system] : systems_) {
|
||||
for (auto& [name, system] : ecs_systems_) {
|
||||
system->OnUpdate(ts);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "components/transform.h"
|
||||
#include "components/collider.h"
|
||||
#include "components/renderable.h"
|
||||
#include "components/mesh_renderable.h"
|
||||
#include "scene.h"
|
||||
|
||||
#include "log.h"
|
||||
|
84
src/systems/mesh_render_system.cpp
Normal file
84
src/systems/mesh_render_system.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "systems/mesh_render_system.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "components/transform.h"
|
||||
#include "components/mesh_renderable.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace engine {
|
||||
|
||||
MeshRenderSystem::MeshRenderSystem(Scene* scene)
|
||||
: System(scene, {typeid(TransformComponent).hash_code(),
|
||||
typeid(RenderableComponent).hash_code()}) {}
|
||||
|
||||
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);
|
||||
auto renderable = scene_->GetComponent<engine::RenderableComponent>(entity);
|
||||
|
||||
const gfx::Pipeline* pipeline =
|
||||
renderable->material->GetShader()->GetPipeline();
|
||||
|
||||
static_render_list_.emplace_back(MeshRenderListEntry{
|
||||
.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 MeshRenderListEntry& e1,
|
||||
const MeshRenderListEntry& 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);
|
||||
|
||||
LOG_INFO("\nPRINTING RENDER LIST:\n");
|
||||
|
||||
// DEBUG PRINT
|
||||
for (const auto& entry : static_render_list_) {
|
||||
LOG_INFO("pipeline: {}", static_cast<const void*>(entry.pipeline));
|
||||
LOG_INFO("vertex_buffer: {}",
|
||||
static_cast<const void*>(entry.vertex_buffer));
|
||||
LOG_INFO("index_buffer: {}", static_cast<const void*>(entry.index_buffer));
|
||||
LOG_INFO("base_color_texture: {}",
|
||||
static_cast<const void*>(entry.base_colour_texture));
|
||||
LOG_INFO("transform position: {}, {}, {}", entry.model_matrix[3][0],
|
||||
entry.model_matrix[3][1], entry.model_matrix[3][2]);
|
||||
}
|
||||
|
||||
LOG_INFO("\nRENDER LIST END\n");
|
||||
|
||||
list_needs_rebuild_ = false;
|
||||
}
|
||||
|
||||
void MeshRenderSystem::OnComponentInsert(uint32_t entity) {
|
||||
list_needs_rebuild_ = true;
|
||||
}
|
||||
|
||||
void MeshRenderSystem::OnUpdate(float ts) {
|
||||
// do stuff
|
||||
(void)ts;
|
||||
if (list_needs_rebuild_) RebuildRenderList();
|
||||
}
|
||||
|
||||
} // namespace engine
|
@ -1,168 +0,0 @@
|
||||
#include "systems/render.h"
|
||||
|
||||
#include "application.h"
|
||||
#include "window.h"
|
||||
#include "gfx_device.h"
|
||||
|
||||
#include "resources/material.h"
|
||||
#include "resources/shader.h"
|
||||
#include "resources/texture.h"
|
||||
|
||||
#include "resources/mesh.h"
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
namespace engine {
|
||||
|
||||
RenderSystem::RenderSystem(Scene* scene)
|
||||
: System(scene, {typeid(TransformComponent).hash_code(),
|
||||
typeid(RenderableComponent).hash_code()}),
|
||||
gfx_(scene_->app()->gfxdev()) {}
|
||||
|
||||
RenderSystem::~RenderSystem() {}
|
||||
|
||||
void RenderSystem::OnUpdate(float ts) {
|
||||
(void)ts;
|
||||
|
||||
RenderData& render_data = scene_->app()->render_data_;
|
||||
|
||||
/* camera stuff */
|
||||
const auto camera_transform =
|
||||
scene_->GetComponent<TransformComponent>(camera_.cam_entity);
|
||||
|
||||
// do not render if camera is not set
|
||||
if (camera_transform == nullptr) return;
|
||||
|
||||
if (scene_->app()->window()->GetWindowResized()) {
|
||||
uint32_t w, h;
|
||||
gfx_->GetViewportSize(&w, &h);
|
||||
viewport_aspect_ratio_ = (float)w / (float)h;
|
||||
const float vertical_fov_radians =
|
||||
glm::radians(camera_.vertical_fov_degrees);
|
||||
const glm::mat4 proj_matrix =
|
||||
glm::perspectiveZO(vertical_fov_radians, viewport_aspect_ratio_,
|
||||
camera_.clip_near, camera_.clip_far);
|
||||
/* update SET 0 (rarely changing uniforms)*/
|
||||
RenderData::GlobalSetUniformBuffer global_set_uniform_buffer{};
|
||||
global_set_uniform_buffer.proj = proj_matrix;
|
||||
gfx_->WriteUniformBuffer(render_data.global_set_uniform_buffer, 0,
|
||||
sizeof(RenderData::GlobalSetUniformBuffer),
|
||||
&global_set_uniform_buffer);
|
||||
}
|
||||
|
||||
glm::mat4 view_matrix = glm::inverse(camera_transform->world_matrix);
|
||||
/* update SET 1 (per frame uniforms) */
|
||||
RenderData::FrameSetUniformBuffer frame_set_uniform_buffer{};
|
||||
frame_set_uniform_buffer.view = view_matrix;
|
||||
gfx_->WriteUniformBuffer(render_data.frame_set_uniform_buffer, 0,
|
||||
sizeof(RenderData::FrameSetUniformBuffer),
|
||||
&frame_set_uniform_buffer);
|
||||
|
||||
/* render all renderable entities */
|
||||
|
||||
struct PushConstants {
|
||||
glm::mat4 model;
|
||||
};
|
||||
|
||||
struct DrawCallData {
|
||||
const gfx::Buffer* vb;
|
||||
const gfx::Buffer* ib;
|
||||
const gfx::DescriptorSet* material_set;
|
||||
bool draw_indexed;
|
||||
uint32_t draw_count;
|
||||
PushConstants push_constants;
|
||||
};
|
||||
std::vector<std::tuple<int, const gfx::Pipeline*, DrawCallData>>
|
||||
unsorted_draw_calls{};
|
||||
|
||||
for (uint32_t entity : entities_) {
|
||||
auto r = scene_->GetComponent<RenderableComponent>(entity);
|
||||
assert(r != nullptr);
|
||||
assert(r->material != nullptr);
|
||||
assert(r->material->texture_ != nullptr);
|
||||
if (r->shown == false) continue;
|
||||
|
||||
auto t = scene_->GetComponent<TransformComponent>(entity);
|
||||
assert(t != nullptr);
|
||||
|
||||
int render_order = r->material->GetShader()->GetRenderOrder();
|
||||
|
||||
const gfx::Pipeline* pipeline = r->material->GetShader()->GetPipeline();
|
||||
|
||||
DrawCallData data{};
|
||||
if (r->mesh) {
|
||||
data.vb = r->mesh->GetVB();
|
||||
data.ib = r->mesh->GetIB();
|
||||
}
|
||||
data.material_set = r->material->texture_->GetDescriptorSet();
|
||||
if (r->index_count_override == 0) {
|
||||
assert(r->mesh != nullptr);
|
||||
data.draw_count = r->mesh->GetCount();
|
||||
data.draw_indexed = true;
|
||||
} else {
|
||||
data.draw_count = r->index_count_override;
|
||||
data.draw_indexed = false;
|
||||
}
|
||||
data.push_constants.model = t->world_matrix;
|
||||
|
||||
unsorted_draw_calls.emplace_back(
|
||||
std::make_tuple(render_order, pipeline, data));
|
||||
}
|
||||
|
||||
std::vector<std::pair<const gfx::Pipeline*, DrawCallData>> draw_calls{};
|
||||
draw_calls.reserve(unsorted_draw_calls.size());
|
||||
|
||||
/* sort the draw calls */
|
||||
for (int i = 0; i <= resources::Shader::kHighestRenderOrder; i++) {
|
||||
for (const auto& [render_order, pipeline, data] : unsorted_draw_calls) {
|
||||
if (render_order == i) {
|
||||
draw_calls.emplace_back(std::make_pair(pipeline, data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* begin rendering */
|
||||
render_data.draw_buffer = gfx_->BeginRender();
|
||||
|
||||
/* these descriptor set bindings should persist across pipeline changes */
|
||||
const gfx::Pipeline* const first_pipeline = draw_calls.begin()->first;
|
||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
||||
render_data.global_set, 0);
|
||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
||||
render_data.frame_set, 1);
|
||||
|
||||
gfx_->CmdBindPipeline(render_data.draw_buffer, first_pipeline);
|
||||
const gfx::Pipeline* last_bound_pipeline = first_pipeline;
|
||||
|
||||
for (const auto& [pipeline, draw_call] : draw_calls) {
|
||||
if (pipeline != last_bound_pipeline) {
|
||||
gfx_->CmdBindPipeline(render_data.draw_buffer, pipeline);
|
||||
last_bound_pipeline = pipeline;
|
||||
}
|
||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, pipeline,
|
||||
draw_call.material_set, 2);
|
||||
gfx_->CmdPushConstants(render_data.draw_buffer, pipeline, 0,
|
||||
sizeof(PushConstants), &draw_call.push_constants);
|
||||
if (draw_call.vb) {
|
||||
gfx_->CmdBindVertexBuffer(render_data.draw_buffer, 0, draw_call.vb);
|
||||
}
|
||||
if (draw_call.ib) {
|
||||
gfx_->CmdBindIndexBuffer(render_data.draw_buffer, draw_call.ib);
|
||||
}
|
||||
if (draw_call.draw_indexed) {
|
||||
gfx_->CmdDrawIndexed(render_data.draw_buffer, draw_call.draw_count, 1, 0,
|
||||
0, 0);
|
||||
} else {
|
||||
gfx_->CmdDraw(render_data.draw_buffer, draw_call.draw_count, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw */
|
||||
gfx_->FinishRender(render_data.draw_buffer);
|
||||
}
|
||||
|
||||
void RenderSystem::SetCameraEntity(uint32_t entity) {
|
||||
camera_.cam_entity = entity;
|
||||
}
|
||||
|
||||
} // namespace engine
|
5
src/systems/text_render_system.cpp
Normal file
5
src/systems/text_render_system.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "systems/text_render_system.h"
|
||||
|
||||
namespace engine {
|
||||
|
||||
} // namespace engine
|
@ -28,7 +28,10 @@ std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path) {
|
||||
}
|
||||
|
||||
// append zero byte
|
||||
buffer->data()[buffer->size()] = '\0';
|
||||
// this used to be:
|
||||
// buffer->data()[buffer->size()] = '\0';
|
||||
// errors happened; i'm retarded
|
||||
buffer->data()[buffer->size() - 1] = '\0';
|
||||
|
||||
file.close();
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "application.h"
|
||||
|
||||
#include "components/transform.h"
|
||||
#include "components/renderable.h"
|
||||
#include "components/mesh_renderable.h"
|
||||
|
||||
#include "resources/texture.h"
|
||||
#include "resources/material.h"
|
||||
|
@ -14,6 +14,7 @@ namespace engine {
|
||||
|
||||
void createSwapchain(Swapchain* sc, const SwapchainInfo& info)
|
||||
{
|
||||
assert(sc != nullptr);
|
||||
sc->device = info.device;
|
||||
sc->allocator = info.allocator;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "camera_controller.hpp"
|
||||
#include "components/collider.h"
|
||||
#include "components/custom.h"
|
||||
#include "components/renderable.h"
|
||||
#include "components/mesh_renderable.h"
|
||||
#include "components/transform.h"
|
||||
#include "input_manager.h"
|
||||
#include "meshgen.hpp"
|
||||
@ -13,9 +13,10 @@
|
||||
#include "resources/texture.h"
|
||||
#include "scene.h"
|
||||
#include "scene_manager.h"
|
||||
#include "systems/render.h"
|
||||
#include "systems/mesh_render_system.h"
|
||||
#include "systems/transform.h"
|
||||
#include "util/model_loader.h"
|
||||
#include "log.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "config.h"
|
||||
@ -52,7 +53,7 @@ void PlayGame(GameSettings settings) {
|
||||
|
||||
engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphics_settings);
|
||||
app.SetFrameLimiter(settings.enable_frame_limiter);
|
||||
app.window()->SetRelativeMouseMode(true);
|
||||
app.window()->SetRelativeMouseMode(false);
|
||||
ConfigureInputs(app.input_manager());
|
||||
|
||||
auto my_scene = app.scene_manager()->CreateEmptyScene();
|
||||
@ -72,8 +73,8 @@ void PlayGame(GameSettings settings) {
|
||||
camera_collider->aabb = {{-0.2f, -1.5f, -0.2f},
|
||||
{0.2f, 0.2f, 0.2f}}; // Origin is at eye level
|
||||
my_scene->AddComponent<CameraControllerComponent>(camera);
|
||||
auto render_system = my_scene->GetSystem<engine::RenderSystem>();
|
||||
render_system->SetCameraEntity(camera);
|
||||
auto render_system = my_scene->GetSystem<engine::MeshRenderSystem>();
|
||||
// render_system->SetCameraEntity(camera);
|
||||
}
|
||||
|
||||
/* shared resources */
|
||||
@ -111,7 +112,6 @@ void PlayGame(GameSettings settings) {
|
||||
floor_renderable->material->texture_ = grass_texture;
|
||||
floor_renderable->mesh =
|
||||
GenCuboidMesh(app.gfxdev(), 100.0f, 0.1f, 100.0f, 100.0f);
|
||||
floor_renderable->shown = true;
|
||||
auto floor_collider =
|
||||
my_scene->AddComponent<engine::ColliderComponent>(floor);
|
||||
floor_collider->is_static = true;
|
||||
@ -138,34 +138,10 @@ void PlayGame(GameSettings settings) {
|
||||
|
||||
/* some text */
|
||||
{
|
||||
int width, height;
|
||||
auto bitmap =
|
||||
app.GetResource<engine::resources::Font>("builtin.mono")
|
||||
->GetTextBitmap("Welcome 2 my gaem", 128.0f, width, height);
|
||||
|
||||
uint32_t textbox =
|
||||
my_scene->CreateEntity("textbox", 0, glm::vec3{0.0f, 0.8f, 0.0f});
|
||||
auto textbox_renderable =
|
||||
my_scene->AddComponent<engine::RenderableComponent>(textbox);
|
||||
textbox_renderable->material =
|
||||
std::make_unique<engine::resources::Material>(
|
||||
app.GetResource<engine::resources::Shader>("builtin.quad"));
|
||||
textbox_renderable->material->texture_ =
|
||||
std::make_unique<engine::resources::Texture>(
|
||||
&app.render_data_, bitmap->data(), width, height,
|
||||
engine::resources::Texture::Filtering::kAnisotropic);
|
||||
textbox_renderable->mesh = nullptr;
|
||||
textbox_renderable->index_count_override = 6;
|
||||
auto textTransform =
|
||||
my_scene->GetComponent<engine::TransformComponent>(textbox);
|
||||
textTransform->scale.y =
|
||||
(static_cast<float>(height) / static_cast<float>(width));
|
||||
textTransform->scale *= 0.5f;
|
||||
textbox_renderable->shown = true;
|
||||
|
||||
auto textboxComponent =
|
||||
my_scene->AddComponent<engine::CustomComponent>(textbox);
|
||||
|
||||
textboxComponent->onInit = [](void) {
|
||||
LOG_INFO("Textbox custom component initialised!");
|
||||
};
|
||||
@ -175,7 +151,7 @@ void PlayGame(GameSettings settings) {
|
||||
time_elapsed += ts;
|
||||
if (time_elapsed >= 1.0f) {
|
||||
time_elapsed = 0.0f;
|
||||
LOG_INFO("COMPONENT UPDATE");
|
||||
LOG_INFO("COMPONENT UPDATE");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user