Files
fn_registry/cpp/functions/gfx/shader_canvas.cpp
T
egutierrez 4610bb4a99 feat(shaders_lab): uniform annotations → auto-generated ImGui controls
- cpp/functions/gfx/uniform_parser: regex-based parser of @slider/@color/@toggle/@xy annotations (+ inline tests)
- cpp/functions/gfx/uniform_panel: ImGui widgets + value store + glUniform* apply
- shader_canvas: optional uniforms callback invoked per-frame
- gl_loader: +glUniform1i/3f/4f
- seed plasma: demo uniforms u_speed + u_color
- rebuild Windows .exe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 21:02:35 +02:00

88 lines
2.5 KiB
C++

#include "gfx/gl_loader.h"
#include "gfx/shader_canvas.h"
#include "imgui.h"
#include <functional>
namespace fn::gfx {
void canvas_init(ShaderCanvas& c) {
if (c.initialized) return;
gl_loader_init();
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,
const std::function<void(unsigned int program)>& uniforms_fn) {
ImVec2 avail = ImGui::GetContentRegionAvail();
int w = static_cast<int>(avail.x);
int h = static_cast<int>(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<float>(w), static_cast<float>(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<float>(h) - (mouse.y - canvas_pos.y);
glUniform2f(loc_mouse, mx, my);
}
if (uniforms_fn) uniforms_fn(c.program);
quad_draw(c.quad);
glUseProgram(0);
}
// Restore GL state
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(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