Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.5 KiB
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_buildusandostb_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_sdfcon switch porshape_id. - 2.3 Pasar
shape,icon_id,icon_u0/v0/u1/v1por 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 siEF_DIRECTED. - 3.2 Vertex shader calcula posicion de la flecha (10 px constante en pantalla).
- 3.3 Fragment shader recibe
arc_lengthy descarta segunstyle.
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.hy al menu de la galeria. - 4.3 Visual golden generado.
Fase 5 — Cleanup
- Bump version
graph_renderer1.2.0 → 1.3.0;graph_icons1.0.0. fn index.- Commit
feat(viz): renderer shapes/iconos/flechas/edge-styles.
Criterio de done
demos_graph_stylesmuestra 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_iconsverdes.
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) |