diff --git a/app/runtime/src/main_window.cpp b/app/runtime/src/main_window.cpp index 1e081d1..85e832e 100644 --- a/app/runtime/src/main_window.cpp +++ b/app/runtime/src/main_window.cpp @@ -54,6 +54,8 @@ namespace zephyr { ZEPHYR_INFO("metalness={}", pbr_material->GetParameter("metalness")); ZEPHYR_INFO("roughness={}", pbr_material->GetParameter("roughness")); } + + m_render_engine = std::make_unique(); } MainWindow::~MainWindow() { @@ -84,6 +86,8 @@ namespace zephyr { return true; }); + m_render_engine->RenderScene(m_scene_root.get()); + const Mesh3D* current_mesh = nullptr; const Material* current_material = nullptr; GraphicsPipeline* current_pipeline = nullptr; diff --git a/app/runtime/src/main_window.hpp b/app/runtime/src/main_window.hpp index b64f6a5..c1869e3 100644 --- a/app/runtime/src/main_window.hpp +++ b/app/runtime/src/main_window.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,8 @@ namespace zephyr { std::unique_ptr m_scene_root; + std::unique_ptr m_render_engine; + Matrix4 m_projection_matrix; uint m_frame{0}; uint m_frames_in_flight{}; diff --git a/zephyr/renderer/CMakeLists.txt b/zephyr/renderer/CMakeLists.txt index 0f8370f..044c044 100644 --- a/zephyr/renderer/CMakeLists.txt +++ b/zephyr/renderer/CMakeLists.txt @@ -1,6 +1,6 @@ set(SOURCES - src/placeholder.cpp + src/render_engine.cpp ) set(HEADERS @@ -21,11 +21,12 @@ set(HEADERS_PUBLIC include/zephyr/renderer/texture/texture_cube.hpp include/zephyr/renderer/texture/texture_resource.hpp include/zephyr/renderer/mesh.hpp + include/zephyr/renderer/render_engine.hpp include/zephyr/renderer/resource.hpp ) add_library(zephyr-renderer ${SOURCES} ${HEADERS} ${HEADERS_PUBLIC}) -target_link_libraries(zephyr-renderer PUBLIC zephyr-common zephyr-cxx-opts) +target_link_libraries(zephyr-renderer PUBLIC zephyr-common zephyr-math zephyr-gpu zephyr-scene zephyr-cxx-opts) target_include_directories(zephyr-renderer PUBLIC include) target_include_directories(zephyr-renderer PRIVATE src) \ No newline at end of file diff --git a/zephyr/renderer/include/zephyr/renderer/render_engine.hpp b/zephyr/renderer/include/zephyr/renderer/render_engine.hpp new file mode 100644 index 0000000..f5732ae --- /dev/null +++ b/zephyr/renderer/include/zephyr/renderer/render_engine.hpp @@ -0,0 +1,39 @@ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace zephyr { + + struct RenderObject { + Matrix4 local_to_world_transform; + }; + + class RenderEngine { + public: + RenderEngine(); + ~RenderEngine(); + + void RenderScene(SceneNode* scene_root); + + private: + void CreateRenderThread(); + void JoinRenderThread(); + void RenderThreadMain(); + + std::thread m_render_thread; + std::atomic_bool m_render_thread_running; + std::atomic_bool m_render_thread_is_waiting; + std::binary_semaphore m_caller_thread_semaphore{0}; //> Semaphore signalled by the calling thread + std::binary_semaphore m_render_thread_semaphore{1}; //> Semaphore signalled by the rendering thread + + std::vector m_render_objects; + }; + +} // namespace zephyr diff --git a/zephyr/renderer/src/placeholder.cpp b/zephyr/renderer/src/placeholder.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/zephyr/renderer/src/render_engine.cpp b/zephyr/renderer/src/render_engine.cpp new file mode 100644 index 0000000..2bea7f8 --- /dev/null +++ b/zephyr/renderer/src/render_engine.cpp @@ -0,0 +1,65 @@ + +#include +#include + +namespace zephyr { + + RenderEngine::RenderEngine() { + CreateRenderThread(); + } + + RenderEngine::~RenderEngine() { + JoinRenderThread(); + } + + void RenderEngine::RenderScene(SceneNode* scene_root) { + // Wait for the render thread to complete reading the internal render structures. + m_render_thread_semaphore.acquire(); + + m_render_objects.clear(); + + scene_root->Traverse([&](SceneNode* node) -> bool { + if(!node->IsVisible()) return false; + + if(node->HasComponent()) { + m_render_objects.push_back({ + .local_to_world_transform = node->GetTransform().GetWorld() + }); + } + + return true; + }); + + // Signal to the render thread that the next frame is ready + m_caller_thread_semaphore.release(); + } + + void RenderEngine::CreateRenderThread() { + m_render_thread_running = true; + m_render_thread_is_waiting = false; + m_render_thread = std::thread{[this] { RenderThreadMain(); }}; + } + + void RenderEngine::JoinRenderThread() { + m_render_thread_running = false; + if(m_render_thread_is_waiting) { + m_caller_thread_semaphore.release(); + } + m_render_thread.join(); + } + + void RenderEngine::RenderThreadMain() { + while(m_render_thread_running) { + // Wait for the caller thread to prepare the internal render structures for the next frame. + m_render_thread_is_waiting = true; + m_caller_thread_semaphore.acquire(); + m_render_thread_is_waiting = false; + + fmt::print("got {} render objects\n", m_render_objects.size()); + + // Signal to the caller thread that we are done reading the internal render structures. + m_render_thread_semaphore.release(); + } + } + +} // namespace zephyr \ No newline at end of file diff --git a/zephyr/scene/include/zephyr/scene/mesh.hpp b/zephyr/scene/include/zephyr/scene/mesh.hpp index 37407b5..639bbef 100644 --- a/zephyr/scene/include/zephyr/scene/mesh.hpp +++ b/zephyr/scene/include/zephyr/scene/mesh.hpp @@ -4,6 +4,8 @@ #include #include +#pragma once + namespace zephyr { struct MeshComponent : Component { diff --git a/zephyr/scene/include/zephyr/scene/node.hpp b/zephyr/scene/include/zephyr/scene/node.hpp index 1590b9f..0e40ace 100644 --- a/zephyr/scene/include/zephyr/scene/node.hpp +++ b/zephyr/scene/include/zephyr/scene/node.hpp @@ -72,11 +72,19 @@ namespace zephyr { } [[nodiscard]] bool IsVisible() const { - return m_visible; + return m_is_visible; } void SetVisible(bool visible) { - m_visible = visible; + m_is_visible = visible; + } + + [[nodiscard]] bool IsRendererStatic() const { + return m_is_renderer_static; + } + + void MakeRendererStatic() { + m_is_renderer_static = true; } [[nodiscard]] const Transform3D& GetTransform() const { @@ -143,7 +151,8 @@ namespace zephyr { SceneNode* m_parent{}; std::vector> m_children; std::string m_name; - bool m_visible{true}; + bool m_is_visible{true}; + bool m_is_renderer_static{false}; Transform3D m_transform{this}; std::unordered_map> m_components; };