Files
fn_registry/dev/issues/completed/0049f-graph-renderer-symbols.md
T

6.5 KiB
Raw Blame History

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0049f Renderer extendido: shapes SDF, icon atlas, flechas, edge styles completado feature
multi-app alta
2026-05-17 2026-05-17

0049f — Renderer extendido: shapes SDF, icon atlas, flechas, edge styles

Metadata

Campo Valor
ID 0049f
Estado pendiente
Prioridad alta
Tipo feature — parte de #0049

Dependencias

Bloqueada por: 0049e (necesita shape, icon_id, flags.directed, style).


Objetivo

Extender el fragment shader del renderer con una libreria de SDF (circulo, cuadrado, diamante, hex, triangulo, rounded square), un atlas de iconos Tabler renderizado a textura, flechas direccionales en aristas, y estilos solid/dashed/dotted. Una sola draw call para todos los nodos, una para todas las aristas.

Contexto

Maltego/OSINT requiere distinguir entidades de un vistazo: Person ≠ Email ≠ Domain. Color solo no escala — necesitamos forma + icono. El stack ya tiene Tabler como font (cpp/functions/core/icons_tabler.h); aqui lo bakeamos a una textura para que cada nodo pueda llevar un icono dentro.

Arquitectura

cpp/functions/viz/
├── graph_renderer.{h,cpp}            # MOD: shaders extendidos + uniform sampler de iconos
├── graph_renderer.md                  # MOD: bump version
├── graph_icons.{h,cpp}               # NEW: builder del atlas
├── graph_icons.md                     # NEW
└── (fragment shader incluye sdf_*.glsl inline)

cpp/tests/
└── test_graph_icons.cpp              # NEW

API graph_icons

struct IconAtlas;

struct IconRegion {
    uint16_t id;          // = posicion en el array al construir
    float u0, v0, u1, v1; // UVs en la textura
};

// Construye una textura 512x512 RGBA con `count` iconos Tabler renderizados a 32px.
// Codepoints son los valores `TI_*` del header.
IconAtlas* graph_icons_build(const uint16_t* codepoints, int count, int icon_px = 32);
unsigned int graph_icons_texture(const IconAtlas*);   // GL texture id
const IconRegion* graph_icons_region(const IconAtlas*, uint16_t icon_id);
void graph_icons_destroy(IconAtlas*);

Shaders extendidos

Vertex shader de nodos ya pasa type_id, shape, icon_id por instance. Fragment shader compone:

float sdf_circle (vec2 uv) { return length(uv - 0.5) - 0.5; }
float sdf_square (vec2 uv) { vec2 d = abs(uv - 0.5) - 0.5; return max(d.x, d.y); }
float sdf_diamond(vec2 uv) { vec2 d = abs(uv - 0.5); return d.x + d.y - 0.5; }
float sdf_hex    (vec2 uv) { ... }
float sdf_triangle(vec2 uv){ ... }
float sdf_rrect  (vec2 uv) { vec2 d = abs(uv - 0.5) - 0.5 + r; return length(max(d,0.0)) - r; }

float pick_sdf(uint shape, vec2 uv) {
    switch (shape) {
        case 0u: return sdf_circle(uv);
        case 1u: return sdf_square(uv);
        case 2u: return sdf_diamond(uv);
        ...
    }
}

void main() {
    float d = pick_sdf(v_shape, v_uv);
    float aa = fwidth(d);
    float a  = 1.0 - smoothstep(0.0, aa, d);
    if (a < 0.001) discard;
    vec3 col = v_color.rgb;
    if (v_icon_id != 0u) {
        // UV del icono dentro del atlas: (uv - 0.5) * scale + region_center
        vec2 atlas_uv = mix(vec2(v_icon_u0, v_icon_v0), vec2(v_icon_u1, v_icon_v1), v_uv);
        vec4 ic = texture(u_icon_atlas, atlas_uv);
        col = mix(col, vec3(1.0), ic.a * 0.85);
    }
    frag_color = vec4(col, a * v_color.a);
}

Aristas direccionales con flecha

Cada arista pasa de 2 vertices (line) a 4 vertices: 2 para el segmento + 2 para el triangulo de la flecha (solo si flags & EF_DIRECTED). Indices 0-1 = linea, 2-3 = triangulo apuntando al target. Vertex shader calcula la flecha en world coords usando direccion target-source y tamaño constante en pixels.

Edge styles

Fragment shader de aristas recibe arc_length (interpolado linealmente entre source y target en pixels). Para style=DASHED: if (mod(arc_length, 8.0) > 4.0) discard;. Para DOTTED: similar con periodo y duty diferentes.

Tareas

Fase 1 — graph_icons

  • 1.1 Crear graph_icons.{h,cpp,md}. Implementar _build usando stb_truetype (o ImGui font baker) para rasterizar codepoints Tabler a una bitmap 512×512.
  • 1.2 Layout simple: grid 16×16 a 32px por celda → 256 iconos por atlas.
  • 1.3 Subir como GL texture RGBA8 con linear filtering.
  • 1.4 Tests: build de 10 iconos conocidos; verificar que la textura tiene contenido en las regiones esperadas.

Fase 2 — Shaders SDF

  • 2.1 Implementar las 6 funciones SDF en GLSL.
  • 2.2 pick_sdf con switch por shape_id.
  • 2.3 Pasar shape, icon_id, icon_u0/v0/u1/v1 por instance. Layout actualizado.
  • 2.4 Compose icon overlay en fragment.

Fase 3 — Aristas direccionales + estilos

  • 3.1 Cambiar glDrawArrays(GL_LINES, ...) por geometry expansion en CPU/shader: 4 vertices por arista, los 2 ultimos solo se usan si EF_DIRECTED.
  • 3.2 Vertex shader calcula posicion de la flecha (10 px constante en pantalla).
  • 3.3 Fragment shader recibe arc_length y descarta segun style.

Fase 4 — Demo

  • 4.1 Crear cpp/apps/primitives_gallery/demos_graph_styles.cpp: grafo pequeño (~30 nodos) con 6 EntityTypes (uno por shape), 3 RelationTypes (solid/dashed/dotted), aristas direccionales mezcladas. Iconos Tabler representativos: TI_USER, TI_MAIL, TI_GLOBE, TI_PHONE, TI_BUILDING, TI_DATABASE.
  • 4.2 Anadirlo a demos.h y al menu de la galeria.
  • 4.3 Visual golden generado.

Fase 5 — Cleanup

  • Bump version graph_renderer 1.2.0 → 1.3.0; graph_icons 1.0.0.
  • fn index.
  • Commit feat(viz): renderer shapes/iconos/flechas/edge-styles.

Criterio de done

  • demos_graph_styles muestra todas las shapes + iconos + flechas + estilos visualmente correctos.
  • Sigue siendo 1 draw call por nodos y 1 por aristas.
  • Test golden estable.
  • Tests test_graph_icons verdes.

Riesgos

Riesgo Mitigacion
switch en GLSL ramifica → menos eficiente Acceptable a estas escalas; se puede unfold luego con #define por tipo si hace falta
Atlas baker mete artifacts en bordes Padding 2px entre celdas
Flechas ocupan area visible del nodo target Acortar el segmento de linea por el radio del nodo target en vertex shader
Codepoints Tabler con caracteres compuestos Usar solo los basicos del header icons_tabler.h (ya validados)