Files
fn_registry/cpp/functions/gfx/dag_catalog.cpp
T
egutierrez e828af3ac1 feat(shaders_lab): Output node + Functions palette with drag-drop
- DagKind::Output (new enum): terminal sink; compiler wires fragColor to its source_ids[0]
- dag_catalog: "output" node (1 input, red)
- dag_compile: skips Output in node_<i> emission; final fragColor resolves from Output's connection
- dag_node_editor: no more Add button; drops "DAG_NODE_TYPE" payloads at mouse canvas position; Output cannot be deleted; Output has no output pin
- dag_palette (new fn): Functions window with grouped, draggable node cards
- main.cpp: "Functions" window added; ensure_dag_default seeds plasma + connected Output
2026-04-24 22:16:47 +02:00

260 lines
11 KiB
C++

#include "gfx/dag_catalog.h"
#include <string>
namespace fn::gfx {
static const std::vector<DagNodeDef>& build_catalog() {
static std::vector<DagNodeDef> catalog = []() {
std::vector<DagNodeDef> v;
// ── Gen: solid ────────────────────────────────────────────────
{
DagNodeDef n;
n.name = "solid";
n.label = "solid";
n.desc = "color constante";
n.kind = DagKind::Gen;
n.num_inputs = 0;
n.param_names = {"r", "g", "b", ""};
n.param_defaults = {0.35f, 0.25f, 0.55f, 0.0f};
n.controls = {
{ DagControl::Kind::Color, "color", {0, 1, 2}, 0.0f, 1.0f, 0.0f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" return vec4(p.x, p.y, p.z, 1.0);";
};
v.push_back(std::move(n));
}
// ── Gen: gradient ─────────────────────────────────────────────
{
DagNodeDef n;
n.name = "gradient";
n.label = "gradient";
n.desc = "gradiente direccional";
n.kind = DagKind::Gen;
n.num_inputs = 0;
n.param_names = {"angle", "hue", "", ""};
n.param_defaults = {0.8f, 0.5f, 0.0f, 0.0f};
n.controls = {
{ DagControl::Kind::Slider, "angulo", {0, -1, -1}, 0.0f, 6.2832f, 0.01f },
{ DagControl::Kind::Slider, "tono", {1, -1, -1}, 0.0f, 1.0f, 0.01f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" vec2 dir = vec2(cos(p.x), sin(p.x));\n"
" float t = dot(uv - 0.5, dir) + 0.5;\n"
" vec3 col = 0.5 + 0.5 * cos(6.28318 * (p.y + vec3(0.0, 0.33, 0.67) + t));\n"
" return vec4(col, 1.0);";
};
v.push_back(std::move(n));
}
// ── Gen: plasma ───────────────────────────────────────────────
{
DagNodeDef n;
n.name = "plasma";
n.label = "plasma";
n.desc = "onda trigonometrica";
n.kind = DagKind::Gen;
n.num_inputs = 0;
n.param_names = {"speed", "scale", "", ""};
n.param_defaults = {1.0f, 2.0f, 0.0f, 0.0f};
n.controls = {
{ DagControl::Kind::Slider, "velocidad", {0, -1, -1}, 0.0f, 3.0f, 0.01f },
{ DagControl::Kind::Slider, "escala", {1, -1, -1}, 0.5f, 10.0f, 0.1f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" vec3 col = 0.5 + 0.5 * cos(u_time * p.x + uv.xyx * p.y + vec3(0.0, 2.0, 4.0));\n"
" return vec4(col, 1.0);";
};
v.push_back(std::move(n));
}
// ── Op: circle ────────────────────────────────────────────────
// Reclassified as Op (num_inputs=1): composites circle over input 'a'
{
DagNodeDef n;
n.name = "circle";
n.label = "circle";
n.desc = "sdf de circulo (composita sobre input)";
n.kind = DagKind::Op;
n.num_inputs = 1;
n.param_names = {"cx", "cy", "radius", "soft"};
n.param_defaults = {0.0f, 0.0f, 0.35f, 0.01f};
n.controls = {
{ DagControl::Kind::XY, "centro", {0, 1, -1}, -0.8f, 0.8f, 0.01f },
{ DagControl::Kind::Slider, "radio", {2, -1, -1}, 0.0f, 1.0f, 0.01f },
{ DagControl::Kind::Slider, "suavidad", {3, -1, -1}, 0.001f, 0.1f, 0.001f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" float aspect = u_resolution.x / u_resolution.y;\n"
" vec2 pos = vec2((uv.x - 0.5) * aspect - p.x, uv.y - 0.5 - p.y);\n"
" float d = length(pos) - p.z;\n"
" float fill = smoothstep(p.w, -p.w, d);\n"
" return mix(a, vec4(1.0), fill);";
};
v.push_back(std::move(n));
}
// ── Op: invert ────────────────────────────────────────────────
{
DagNodeDef n;
n.name = "invert";
n.label = "invert";
n.desc = "1 - rgb";
n.kind = DagKind::Op;
n.num_inputs = 1;
n.param_names = {"", "", "", ""};
n.param_defaults = {0.0f, 0.0f, 0.0f, 0.0f};
n.controls = {};
n.body_glsl = [](int /*idx*/) -> std::string {
return " return vec4(1.0 - a.rgb, a.a);";
};
v.push_back(std::move(n));
}
// ── Op: gamma ─────────────────────────────────────────────────
{
DagNodeDef n;
n.name = "gamma";
n.label = "gamma";
n.desc = "pow(rgb, gamma)";
n.kind = DagKind::Op;
n.num_inputs = 1;
n.param_names = {"gamma", "", "", ""};
n.param_defaults = {1.0f, 0.0f, 0.0f, 0.0f};
n.controls = {
{ DagControl::Kind::Slider, "gamma", {0, -1, -1}, 0.1f, 4.0f, 0.01f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" return vec4(pow(a.rgb, vec3(1.0 / max(p.x, 0.001))), a.a);";
};
v.push_back(std::move(n));
}
// ── Op: hueShift ──────────────────────────────────────────────
{
DagNodeDef n;
n.name = "hueShift";
n.label = "hue shift";
n.desc = "rotar matiz";
n.kind = DagKind::Op;
n.num_inputs = 1;
n.param_names = {"h", "", "", ""};
n.param_defaults = {0.0f, 0.0f, 0.0f, 0.0f};
n.controls = {
{ DagControl::Kind::Slider, "h", {0, -1, -1}, 0.0f, 1.0f, 0.01f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" float ang = 6.28318 * p.x;\n"
" float ca = cos(ang), sa = sin(ang);\n"
" mat3 hueMat = mat3(\n"
" vec3(0.299 + 0.701 * ca + 0.168 * sa, 0.587 - 0.587 * ca + 0.330 * sa, 0.114 - 0.114 * ca - 0.497 * sa),\n"
" vec3(0.299 - 0.299 * ca - 0.328 * sa, 0.587 + 0.413 * ca + 0.035 * sa, 0.114 - 0.114 * ca + 0.292 * sa),\n"
" vec3(0.299 - 0.300 * ca + 1.250 * sa, 0.587 - 0.588 * ca - 1.050 * sa, 0.114 + 0.886 * ca - 0.203 * sa)\n"
" );\n"
" return vec4(clamp(hueMat * a.rgb, 0.0, 1.0), a.a);";
};
v.push_back(std::move(n));
}
// ── Blend: mix ────────────────────────────────────────────────
{
DagNodeDef n;
n.name = "blend_mix";
n.label = "mix";
n.desc = "interpolacion mix(a, b, t)";
n.kind = DagKind::Blend;
n.num_inputs = 2;
n.param_names = {"t", "", "", ""};
n.param_defaults = {0.5f, 0.0f, 0.0f, 0.0f};
n.controls = {
{ DagControl::Kind::Slider, "t", {0, -1, -1}, 0.0f, 1.0f, 0.01f },
};
n.body_glsl = [](int idx) -> std::string {
std::string i = std::to_string(idx);
return " vec4 p = u_params[" + i + "];\n"
" return mix(a, b, p.x);";
};
v.push_back(std::move(n));
}
// ── Blend: multiply ───────────────────────────────────────────
{
DagNodeDef n;
n.name = "blend_multiply";
n.label = "multiply";
n.desc = "a * b";
n.kind = DagKind::Blend;
n.num_inputs = 2;
n.param_names = {"", "", "", ""};
n.param_defaults = {0.0f, 0.0f, 0.0f, 0.0f};
n.controls = {};
n.body_glsl = [](int /*idx*/) -> std::string {
return " return vec4(a.rgb * b.rgb, a.a);";
};
v.push_back(std::move(n));
}
// ── Blend: screen ─────────────────────────────────────────────
{
DagNodeDef n;
n.name = "blend_screen";
n.label = "screen";
n.desc = "1 - (1-a)(1-b)";
n.kind = DagKind::Blend;
n.num_inputs = 2;
n.param_names = {"", "", "", ""};
n.param_defaults = {0.0f, 0.0f, 0.0f, 0.0f};
n.controls = {};
n.body_glsl = [](int /*idx*/) -> std::string {
return " return vec4(1.0 - (1.0 - a.rgb) * (1.0 - b.rgb), a.a);";
};
v.push_back(std::move(n));
}
// ── Output (sink — drives fragColor) ─────────────────────────
{
DagNodeDef n;
n.name = "output";
n.label = "Output";
n.desc = "canvas DAG output";
n.kind = DagKind::Output;
n.num_inputs = 1;
n.param_names = {"", "", "", ""};
n.param_defaults = {0.0f, 0.0f, 0.0f, 0.0f};
n.controls = {};
n.body_glsl = [](int) -> std::string { return ""; };
v.push_back(std::move(n));
}
return v;
}();
return catalog;
}
const std::vector<DagNodeDef>& dag_catalog() {
return build_catalog();
}
const DagNodeDef* dag_find(const std::string& name) {
for (const auto& n : dag_catalog()) {
if (n.name == name) return &n;
}
return nullptr;
}
} // namespace fn::gfx