diff --git a/example/damaged_helmet/color_pass.cpp b/example/damaged_helmet/color_pass.cpp index d13b9ec..01519f5 100644 --- a/example/damaged_helmet/color_pass.cpp +++ b/example/damaged_helmet/color_pass.cpp @@ -292,4 +292,4 @@ void ColorPass::draw(RenderContext &ctx, const glm::ivec2 &g_size, // End rendering to FBO ctx.endRendering(); } -} \ No newline at end of file +} diff --git a/example/damaged_helmet/color_pass.h b/example/damaged_helmet/color_pass.h index 09a7e28..8449d27 100644 --- a/example/damaged_helmet/color_pass.h +++ b/example/damaged_helmet/color_pass.h @@ -64,4 +64,4 @@ class ColorPass { Buffer m_material_ubo; }; -} \ No newline at end of file +} diff --git a/example/damaged_helmet/final_pass.h b/example/damaged_helmet/final_pass.h index c94e8e5..fc76ead 100644 --- a/example/damaged_helmet/final_pass.h +++ b/example/damaged_helmet/final_pass.h @@ -22,4 +22,4 @@ class FinalPass { std::unique_ptr m_pipeline; }; -} // namespace paimon \ No newline at end of file +} // namespace paimon diff --git a/example/damaged_helmet/main.cpp b/example/damaged_helmet/main.cpp index 9265f9f..bd68776 100644 --- a/example/damaged_helmet/main.cpp +++ b/example/damaged_helmet/main.cpp @@ -108,9 +108,8 @@ int main() { // Create render context RenderContext ctx; - // Create screen quad (it will load shaders internally from singleton) - ColorPass color_pass(ctx); - FinalPass final_pass(ctx); + // Create Renderer (it will own per-pass resources) + Renderer renderer(ctx, texturePtrMap); LOG_INFO("Setup complete, entering render loop"); @@ -156,4 +155,4 @@ int main() { LOG_INFO("Shutting down"); return 0; -} +} \ No newline at end of file diff --git a/example/damaged_helmet/renderer.cpp b/example/damaged_helmet/renderer.cpp index e69de29..43a4545 100644 --- a/example/damaged_helmet/renderer.cpp +++ b/example/damaged_helmet/renderer.cpp @@ -0,0 +1,41 @@ +#include "renderer.h" + +using namespace paimon; + +Renderer::Renderer(RenderContext &renderContext, + const std::map, Texture *> &texturePtrMap) + : m_renderContext(renderContext), + m_colorPass(renderContext), + m_finalPass(renderContext), + m_transformUbo(), + m_materialUbo(), + m_lightingUbo(), + m_texturePtrMap(texturePtrMap) { + m_transformUbo.set_storage(sizeof(TransformUBO), nullptr, GL_DYNAMIC_STORAGE_BIT); + m_materialUbo.set_storage(sizeof(MaterialUBO), nullptr, GL_DYNAMIC_STORAGE_BIT); + m_lightingUbo.set_storage(sizeof(LightingUBO), nullptr, GL_DYNAMIC_STORAGE_BIT); +} + +void Renderer::draw(const glm::ivec2 &resolution, const Camera &camera, + const LightingUBO &lighting, + const std::vector &meshes) { + // Prepare transform UBO + TransformUBO transformData; + transformData.model = glm::mat4(1.0f); + transformData.view = glm::lookAt(camera.position, glm::vec3(0.0f, 0.0f, 0.0f), camera.up); + transformData.projection = glm::perspective(glm::radians(camera.fov), + static_cast(resolution.x) / resolution.y, + 0.1f, 100.0f); + m_transformUbo.set_sub_data(0, sizeof(TransformUBO), &transformData); + + // Update lighting UBO (copy viewPos from camera) + LightingUBO lightingData = lighting; + lightingData.viewPos = camera.position; + m_lightingUbo.set_sub_data(0, sizeof(LightingUBO), &lightingData); + + // First pass: render scene to color texture + m_colorPass.draw(m_renderContext, resolution, meshes, m_texturePtrMap, m_transformUbo, m_materialUbo, m_lightingUbo); + + // Second pass: blit color texture to default framebuffer + m_finalPass.draw(m_renderContext, *m_colorPass.getColorTexture(), resolution); +} \ No newline at end of file diff --git a/example/damaged_helmet/renderer.h b/example/damaged_helmet/renderer.h index bf3584f..1e5b095 100644 --- a/example/damaged_helmet/renderer.h +++ b/example/damaged_helmet/renderer.h @@ -1,21 +1,58 @@ #pragma once +#include +#include +#include + +#include +#include + #include "paimon/rendering/render_context.h" -#include "paimon/core/fg/transient_resources.h" +#include "paimon/opengl/buffer.h" +#include "paimon/opengl/texture.h" + +#include "color_pass.h" +#include "final_pass.h" +#include "mesh_data.h" namespace paimon { +// Camera struct used by Renderer (matches previous main.cpp fields) +struct Camera { + glm::vec3 position = glm::vec3(0.0f, 0.0f, 3.0f); + glm::vec3 front = glm::vec3(0.0f, 0.0f, -1.0f); + glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); + float yaw = -90.0f; + float pitch = 0.0f; + float fov = 45.0f; +}; + class Renderer { public: - Renderer(RenderContext &renderContext); + Renderer(RenderContext &renderContext, + const std::map, Texture *> &texturePtrMap); + + // resolution: framebuffer size in pixels + // camera: camera state (position, fov...) + // lighting: LightingUBO structure (lightPos, viewPos) + // meshes: list of MeshData to render + void draw(const glm::ivec2 &resolution, const Camera &camera, + const LightingUBO &lighting, + const std::vector &meshes); - void render(); + // expose color texture for tests or external use if needed + const Texture *getColorTexture() const { return m_colorPass.getColorTexture(); } private: RenderContext &m_renderContext; - TransientResources m_transientResources; + ColorPass m_colorPass; + FinalPass m_finalPass; - - float m_rotation = 0.0f; + Buffer m_transformUbo; + Buffer m_materialUbo; + Buffer m_lightingUbo; + + const std::map, Texture *> &m_texturePtrMap; }; -} \ No newline at end of file + +} // namespace paimon diff --git a/example/frame_graph/main.cpp b/example/frame_graph/main.cpp index 67df2f3..9d46474 100644 --- a/example/frame_graph/main.cpp +++ b/example/frame_graph/main.cpp @@ -6,6 +6,7 @@ #include #include "paimon/app/window.h" +#include "paimon/core/log_system.h" #include "paimon/core/fg/frame_graph.h" #include "paimon/core/fg/frame_graph_texture.h" #include "paimon/core/fg/transient_resources.h" @@ -388,6 +389,8 @@ void renderScene(RenderData &rd, Program &program, bool isShadowPass) { } int main() { + LogSystem::init(); + auto window = Window::create(WindowConfig{ .title = "Frame Graph Shadow Mapping Example", .format = @@ -404,6 +407,9 @@ int main() { .vsync = true, }); + RenderContext rc; + TransientResources allocator(rc); + RenderData renderData; // Setup geometry and shaders @@ -463,7 +469,7 @@ int main() { }); data.shadow_map = builder.write(data.shadow_map); }, - [&renderData](FrameGraphResources &resources, void *context) { + [&renderData](const ShadowPassData &data, FrameGraphResources &resources, void *context) { std::cout << "Executing Shadow Pass\n"; // Bind shadow framebuffer @@ -493,7 +499,7 @@ int main() { [&](FrameGraph::Builder &builder, ScenePassData &data) { data.shadow_input = builder.read(shadow_pass.shadow_map); }, - [&renderData](FrameGraphResources &resources, void *context) { + [&renderData](const ScenePassData &data, FrameGraphResources &resources, void *context) { std::cout << "Executing Scene Pass\n"; // Render to default framebuffer @@ -548,8 +554,6 @@ int main() { while (!window->shouldClose()) { window->pollEvents(); - RenderContext rc; - TransientResources allocator(rc); fg.execute(&rc, &allocator); window->swapBuffers(); diff --git a/source/paimon/core/ecs/entity.h b/source/paimon/core/ecs/entity.h index 71377e7..078f1f3 100644 --- a/source/paimon/core/ecs/entity.h +++ b/source/paimon/core/ecs/entity.h @@ -107,4 +107,4 @@ class Entity { }; } // namespace ecs -} // namespace paimon \ No newline at end of file +} // namespace paimon diff --git a/source/paimon/core/fg/frame_graph.h b/source/paimon/core/fg/frame_graph.h index 882e8d7..73a8f71 100644 --- a/source/paimon/core/fg/frame_graph.h +++ b/source/paimon/core/fg/frame_graph.h @@ -51,7 +51,7 @@ class FrameGraph { template requires std::invocable && - std::invocable + std::invocable const TData &create_pass(std::string name, TSetup &&setup, TExecutor &&executor) { auto id = m_pass_nodes.size(); diff --git a/source/paimon/core/fg/frame_graph_texture.cpp b/source/paimon/core/fg/frame_graph_texture.cpp index d73eaad..a3e5547 100644 --- a/source/paimon/core/fg/frame_graph_texture.cpp +++ b/source/paimon/core/fg/frame_graph_texture.cpp @@ -12,7 +12,6 @@ void FrameGraphTexture::create(void *allocator, const Descriptor &desc) { void FrameGraphTexture::destroy(void *allocator, const Descriptor &desc) { auto *transientResources = static_cast(allocator); transientResources->releaseTexture(desc, m_texture); - m_texture = nullptr; } void FrameGraphTexture::preRead(void *context, const Descriptor &desc, diff --git a/source/paimon/core/fg/frame_graph_texture.h b/source/paimon/core/fg/frame_graph_texture.h index e8e1d5e..ed78d43 100644 --- a/source/paimon/core/fg/frame_graph_texture.h +++ b/source/paimon/core/fg/frame_graph_texture.h @@ -26,6 +26,9 @@ class FrameGraphTexture { void preWrite(void *context, const Descriptor &desc, uint32_t flags = 0); + Texture *getTexture() { return m_texture; } + const Texture *getTexture() const { return m_texture; } + private: Texture *m_texture = nullptr; }; diff --git a/source/paimon/core/fg/pass.h b/source/paimon/core/fg/pass.h index c6a121c..1168b8e 100644 --- a/source/paimon/core/fg/pass.h +++ b/source/paimon/core/fg/pass.h @@ -27,7 +27,7 @@ class Pass : public PassConcept { ~Pass() override = default; void execute(FrameGraphResources &resources, void *context) const override { - std::invoke(m_executor, resources, context); + std::invoke(m_executor, m_data, resources, context); } TData &get_data() { return m_data; } diff --git a/source/paimon/core/fg/resource_entry.h b/source/paimon/core/fg/resource_entry.h index a9b2058..04c497c 100644 --- a/source/paimon/core/fg/resource_entry.h +++ b/source/paimon/core/fg/resource_entry.h @@ -40,12 +40,14 @@ class ResourceEntry { template TResource &get() { - return dynamic_cast>(*m_concept).get(); + auto &resource = static_cast&>(*m_concept); + return resource.get(); } template typename TResource::Descriptor &get_desc() { - return dynamic_cast>(*m_concept).get_desc(); + auto &resource = static_cast&>(*m_concept); + return resource.get_desc(); } private: diff --git a/source/paimon/rendering/render_context.cpp b/source/paimon/rendering/render_context.cpp index 256f1e5..b2fde61 100644 --- a/source/paimon/rendering/render_context.cpp +++ b/source/paimon/rendering/render_context.cpp @@ -44,7 +44,7 @@ void RenderContext::beginRendering(const RenderingInfo& info) { if (info.depthAttachment.has_value()) { const auto& attachment = info.depthAttachment.value(); if (attachment.loadOp == AttachmentLoadOp::Clear) { - float depth = attachment.clearValue.depthStencil.depth; + float depth = attachment.clearValue.depth; m_currentFbo->clear(GL_DEPTH, 0, &depth); } } @@ -53,7 +53,7 @@ void RenderContext::beginRendering(const RenderingInfo& info) { if (info.stencilAttachment.has_value()) { const auto& attachment = info.stencilAttachment.value(); if (attachment.loadOp == AttachmentLoadOp::Clear) { - GLint stencilValue = static_cast(attachment.clearValue.depthStencil.stencil); + GLint stencilValue = static_cast(attachment.clearValue.stencil); m_currentFbo->clear(GL_STENCIL, 0, &stencilValue); } } diff --git a/source/paimon/rendering/rendering_info.h b/source/paimon/rendering/rendering_info.h index 4c02bd9..218d550 100644 --- a/source/paimon/rendering/rendering_info.h +++ b/source/paimon/rendering/rendering_info.h @@ -29,6 +29,8 @@ struct ClearValue { struct { float r, g, b, a; } color; + float depth; + uint32_t stencil; struct { float depth; uint32_t stencil; @@ -46,6 +48,18 @@ struct ClearValue { return value; } + static ClearValue Depth(float depth) { + ClearValue value; + value.depth = depth; + return value; + } + + static ClearValue Stencil(uint32_t stencil) { + ClearValue value; + value.stencil = stencil; + return value; + } + static ClearValue DepthStencil(float depth, uint32_t stencil = 0) { ClearValue value; value.depthStencil.depth = depth;