ac11300335
graph_renderer 1.5.0: - 6 shapes SDF (circle, square, diamond, hex, triangle, rounded square) con dispatch en fragment shader y AA via fwidth. - Atlas opcional de iconos Tabler bakeado por graph_icons; el shader compone overlay desde un uniform vec4 u_icon_uvs[256]. Setter publico graph_renderer_set_icon_atlas(r, tex, uv_table, count). - Aristas direccionales: 6 vertices por arista (line + chevron de la flecha) en una sola draw call; segmento principal acortado por el radio del nodo target. - Edge styles solid/dashed/dotted via descarte por arc_length en el fragment shader; las lineas del chevron son siempre solidas. graph_icons 1.0.0 (nuevo): - Atlas RGBA8 512x512 = grid 16x16 (256 iconos max) bakeado con stb_truetype desde tabler-icons.ttf. - API: graph_icons_build/texture/region/uv_table/destroy. icon_id es 1-based; 0 reservado para "sin icono". - Hook FN_GRAPH_ICONS_SKIP_GL=1 para tests sin contexto GL. Demo demos_graph_styles en primitives_gallery: 6 EntityTypes (uno por shape) con icono Tabler representativo + 3 RelationTypes (knows/uses/ owns) con flechas direccionales y los 3 estilos. test_graph_icons: 6 casos cubriendo bake, regiones 1-indexed, uv_table consistente, layout en grid 16x16, validacion de count fuera de rango, y verificacion de alpha != 0 en las celdas tras bake. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
152 lines
6.3 KiB
Markdown
152 lines
6.3 KiB
Markdown
# 0049f — Renderer extendido: shapes SDF, icon atlas, flechas, edge styles
|
||
|
||
## Metadata
|
||
|
||
| Campo | Valor |
|
||
|-------|-------|
|
||
| **ID** | 0049f |
|
||
| **Estado** | pendiente |
|
||
| **Prioridad** | alta |
|
||
| **Tipo** | feature — parte de [#0049](0049-osint-graph-viewer.md) |
|
||
|
||
## Dependencias
|
||
|
||
**Bloqueada por:** [0049e](0049e-graph-types-extended.md) (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`
|
||
|
||
```cpp
|
||
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:
|
||
|
||
```glsl
|
||
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) |
|