aboutsummaryrefslogtreecommitdiff
path: root/src/platform/opengl/opengl_device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/opengl/opengl_device.cpp')
-rw-r--r--src/platform/opengl/opengl_device.cpp34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/platform/opengl/opengl_device.cpp b/src/platform/opengl/opengl_device.cpp
index 82fdae1..7ef0ba1 100644
--- a/src/platform/opengl/opengl_device.cpp
+++ b/src/platform/opengl/opengl_device.cpp
@@ -7,6 +7,7 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
+#include <algorithm>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
@@ -18,7 +19,7 @@ namespace Donut::RHI
auto gl_topology(Topology t) -> GLenum { return t == Topology::Lines ? GL_LINES : GL_TRIANGLES; }
auto gl_compare(CompareOp o) -> GLenum { return o == CompareOp::Always ? GL_ALWAYS : o == CompareOp::LessEqual ? GL_LEQUAL : GL_LESS; }
auto gl_filter(Filter f) -> GLint { return f == Filter::Nearest ? GL_NEAREST : GL_LINEAR; }
- auto gl_internal(Format f) -> GLint { return f == Format::RGBA16F ? GL_RGBA16F : f == Format::D32 ? GL_DEPTH_COMPONENT32F : GL_RGBA8; }
+ auto gl_internal(Format f) -> GLint { return f == Format::RGBA16F ? GL_RGBA16F : f == Format::RGBA32F ? GL_RGBA32F : f == Format::D32 ? GL_DEPTH_COMPONENT32F : GL_RGBA8; }
// ---- Buffer -------------------------------------------------------
class GLBuffer : public Buffer
@@ -255,6 +256,37 @@ namespace Donut::RHI
}
auto end_frame() -> void override { glfwSwapBuffers(static_cast<GLFWwindow*>(m_window)); }
+ auto run_offscreen(const std::function<void(CommandList&)>& record) -> void override
+ {
+ glBindVertexArray(m_vao); // GL is immediate: record executes now
+ record(*m_cmds);
+ glFinish();
+ }
+ auto read_render_target(RenderTarget* target, std::vector<uint8_t>& out) -> void override
+ {
+ auto* rt = static_cast<GLRenderTarget*>(target);
+ int w = rt->m_w, h = rt->m_h;
+ out.resize((size_t)w * h * 4);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->m_fbo);
+ glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, out.data());
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ const size_t row = (size_t)w * 4; // GL is bottom-up -> flip to top-left
+ for (int y = 0; y < h / 2; ++y)
+ std::swap_ranges(out.begin() + y * row, out.begin() + (y + 1) * row, out.begin() + (h - 1 - y) * row);
+ }
+ auto read_render_target_float(RenderTarget* target, std::vector<float>& out) -> void override
+ {
+ auto* rt = static_cast<GLRenderTarget*>(target);
+ int w = rt->m_w, h = rt->m_h;
+ out.resize((size_t)w * h * 4);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->m_fbo);
+ glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, out.data()); // GL converts to float32
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ const size_t row = (size_t)w * 4; // GL is bottom-up -> flip to top-left
+ for (int y = 0; y < h / 2; ++y)
+ std::swap_ranges(out.begin() + y * row, out.begin() + (y + 1) * row, out.begin() + (h - 1 - y) * row);
+ }
+
auto init_imgui() -> void override
{
IMGUI_CHECKVERSION(); ImGui::CreateContext();