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>
This commit is contained in:
2026-04-24 21:02:35 +02:00
parent 8e11c5cfce
commit c7821c4c99
14 changed files with 580 additions and 23 deletions
+12 -2
View File
@@ -3,11 +3,14 @@
#include "gfx/shader_canvas.h"
#include "gfx/gl_shader.h"
#include "gfx/uniform_parser.h"
#include "gfx/uniform_panel.h"
#include "core/fps_overlay.h"
#include "seed_shaders.h"
#include <chrono>
#include <string>
#include <vector>
static fn::gfx::ShaderCanvas g_canvas;
static std::string g_source = PLASMA;
@@ -15,10 +18,14 @@ static std::string g_last_err;
static int g_last_err_line = -1;
static std::chrono::steady_clock::time_point g_last_edit;
static bool g_dirty = true;
static std::vector<fn::gfx::UniformDescriptor> g_descs;
static fn::gfx::UniformStore g_store;
static void try_compile() {
auto r = fn::gfx::compile_fragment(g_source);
if (r.ok) {
g_descs = fn::gfx::parse_uniforms(g_source);
fn::gfx::uniforms_sync(g_store, g_descs);
fn::gfx::canvas_set_program(g_canvas, r.program);
g_last_err.clear();
g_last_err_line = -1;
@@ -91,13 +98,16 @@ static void render() {
// --- Canvas panel ---
if (ImGui::Begin("Canvas")) {
fn::gfx::canvas_render(g_canvas, static_cast<float>(ImGui::GetTime()));
fn::gfx::canvas_render(g_canvas, static_cast<float>(ImGui::GetTime()),
[](unsigned int program) {
fn::gfx::uniforms_apply(g_store, g_descs, program);
});
}
ImGui::End();
// --- Controls panel ---
if (ImGui::Begin("Controls")) {
ImGui::TextDisabled("Controls (fase 2)");
fn::gfx::uniforms_panel(g_store, g_descs);
ImGui::Spacing();
fps_overlay();
}