#define GL_GLEXT_PROTOTYPES #include #include #include "gfx/shader_canvas.h" #include "imgui.h" namespace fn::gfx { void canvas_init(ShaderCanvas& c) { if (c.initialized) return; fb_init(c.fb); quad_init(c.quad); c.initialized = true; } void canvas_set_program(ShaderCanvas& c, unsigned int program) { if (c.program) delete_program(c.program); c.program = program; } void canvas_render(ShaderCanvas& c, float time_seconds) { ImVec2 avail = ImGui::GetContentRegionAvail(); int w = static_cast(avail.x); int h = static_cast(avail.y); if (w < 1) w = 1; if (h < 1) h = 1; fb_resize(c.fb, w, h); // Save GL state GLint prev_fbo = 0; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo); GLint prev_vp[4]; glGetIntegerv(GL_VIEWPORT, prev_vp); // Render to FBO glBindFramebuffer(GL_FRAMEBUFFER, c.fb.fbo); glViewport(0, 0, w, h); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); if (c.program) { glUseProgram(c.program); GLint loc_res = glGetUniformLocation(c.program, "u_resolution"); GLint loc_time = glGetUniformLocation(c.program, "u_time"); GLint loc_mouse = glGetUniformLocation(c.program, "u_mouse"); if (loc_res >= 0) glUniform2f(loc_res, static_cast(w), static_cast(h)); if (loc_time >= 0) glUniform1f(loc_time, time_seconds); if (loc_mouse >= 0) { ImVec2 mouse = ImGui::GetMousePos(); ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // cursor pos is AFTER content region starts float mx = mouse.x - canvas_pos.x; float my = static_cast(h) - (mouse.y - canvas_pos.y); glUniform2f(loc_mouse, mx, my); } quad_draw(c.quad); glUseProgram(0); } // Restore GL state glBindFramebuffer(GL_FRAMEBUFFER, static_cast(prev_fbo)); glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]); // Draw texture in ImGui panel (flip V: OpenGL origin is bottom-left) ImGui::Image( (ImTextureID)(intptr_t)c.fb.tex, avail, ImVec2(0, 1), ImVec2(1, 0) ); } void canvas_destroy(ShaderCanvas& c) { if (!c.initialized) return; if (c.program) { delete_program(c.program); c.program = 0; } quad_destroy(c.quad); fb_destroy(c.fb); c.initialized = false; } } // namespace fn::gfx