Files
fn_registry/dev/issues/0026-cpp-gl-texture-load.md
T
egutierrez a11a58dab0 docs(issues): añadir 0025-0036 — features C++ para registry y primitives_gallery
12 issues nuevos para implementacion paralela: text_editor, file_watcher,
gl_texture_load, gl_compute+pingpong+DAG Compute, ImPlot3D, mesh_viewer,
audio reactivo, animation curves, sql_workbench, http+ws inspector,
scientific viz (5 charts), map_tiles, image_canvas + webcam_texture.

Cada issue añade funciones al registry y un demo propio en
primitives_gallery/demos_<feature>.cpp para minimizar conflictos en paralelo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:48:18 +02:00

5.0 KiB

0026 — C++ gl_texture_load

APP Metadata

Campo Valor
ID 0026
Estado pendiente
Prioridad alta
Tipo feature — C++ gfx (cpp/functions/gfx)

Dependencias

Ninguna. Se compone con gl_loader_cpp_gfx, gl_shader_cpp_gfx, shader_canvas_cpp_gfx.

Desbloquea: shaders que toman imagenes externas (textura de ruido, foto, lookup tables). Base para webcam_texture (0036) y para nodos DAG futuros que usen sampler2D.


Objetivo

Añadir una funcion impura al registry C++ que carga PNG/JPG/HDR desde disco y devuelve un GLuint listo para glBindTexture + glUniform1i. Vendorea stb_image (header-only, dominio publico) en cpp/vendor/stb/.

Mostrar el resultado en primitives_gallery como demo: un shader fullscreen que samplea una imagen cargada, con sliders para tint y zoom UV.

Contexto

Actualmente gl_shader_cpp_gfx solo expone uniforms u_resolution, u_time, u_mouse, y shaders_lab puede pasar u_params[16] via dag_uniforms. No hay forma de meter una imagen al pipeline. Esto bloquea casos comunes:

  • Texturas de ruido (perlin/bluenoise) precomputadas.
  • Lookup tables para color grading.
  • Imagenes de referencia para post-process.

Arquitectura

cpp/
├── vendor/stb/
│   └── stb_image.h              # NEW (~10k LOC, public domain)
├── functions/gfx/
│   ├── gl_texture_load.h        # NEW
│   ├── gl_texture_load.cpp      # NEW
│   └── gl_texture_load.md       # NEW
└── apps/primitives_gallery/
    ├── demos_gl_texture.cpp     # NEW
    ├── demos.h                  # MOD
    ├── main.cpp                 # MOD
    └── CMakeLists.txt           # MOD
cpp/CMakeLists.txt               # MOD

Pure core / impure shell

Funcion impura (purity: impure, kind: function): hace I/O de disco + crea recurso GPU.

API propuesta

namespace fn {

struct GlTexture {
    GLuint id = 0;
    int    w  = 0;
    int    h  = 0;
    int    channels = 0;
    bool   ok() const { return id != 0; }
};

// Carga desde disco (PNG/JPG/BMP/TGA via stb_image, HDR como float opcional).
// flip_y por defecto true para coincidir con UV de OpenGL.
// Devuelve GlTexture con id=0 si falla; usar gl_texture_last_error() para detalle.
GlTexture gl_texture_load(const char* path, bool flip_y = true, bool srgb = false);
GlTexture gl_texture_load_from_memory(const unsigned char* data, int size, bool flip_y = true, bool srgb = false);

void gl_texture_destroy(GlTexture& tex);
const char* gl_texture_last_error();

// Helper: bind a una texture unit y subir uniform sampler.
void gl_texture_bind_uniform(GLuint program, const char* name, const GlTexture& tex, int unit);
}

Tareas

Fase 1 — Vendor stb_image

  • 1.1 Descargar stb_image.h (commit estable) a cpp/vendor/stb/. Crear cpp/vendor/stb/stb_image_impl.cpp con #define STB_IMAGE_IMPLEMENTATION antes del include, para evitar emitir el cuerpo en multiples TUs.
  • 1.2 Añadirlo a cpp/CMakeLists.txt global.

Fase 2 — gl_texture_load

  • 2.1 Implementar gl_texture_load.h/.cpp. Usar glGenTextures + glTexImage2D. Filtros LINEAR_MIPMAP_LINEAR + LINEAR. Generar mipmaps con glGenerateMipmap.
  • 2.2 Soporte para srgb=true (GL_SRGB8_ALPHA8 como internal format).
  • 2.3 Soporte HDR: si extension es .hdr, usar stbi_loadf y GL_RGBA16F.
  • 2.4 gl_texture_load.md con frontmatter (kind: function, purity: impure, error_type, uses_functions: [gl_loader_cpp_gfx]).
  • 3.1 demos_gl_texture.cpp con demo_gl_texture_load(): carga assets/sample.png (un PNG de prueba, ej. patron damero). Renderiza un fullscreen quad con un shader que samplea la textura y aplica tint via uniforms. ImGui::Image con thumbnail al lado y info (w, h, channels).
  • 3.2 Añadir assets/sample.png (256x256, ~10KB).
  • 3.3 Registrar en demos.h, main.cpp, CMakeLists.txt.

Fase 4 — Tests + docs

  • 4.1 Test que carga un PNG embebido (in-memory) y verifica tex.ok() && tex.w == ....
  • 4.2 ./fn index y verificar via fn show gl_texture_load_cpp_gfx.

Ejemplo de uso

auto tex = fn::gl_texture_load("assets/noise.png");
if (!tex.ok()) {
    std::fprintf(stderr, "error: %s\n", fn::gl_texture_last_error());
    return 1;
}
glUseProgram(prog);
fn::gl_texture_bind_uniform(prog, "u_noise", tex, 0);  // unit 0
glDrawArrays(GL_TRIANGLES, 0, 6);

Decisiones de diseño

  • Vendoreado en cpp/vendor/stb/ sigue el patron actual de ImGui/ImPlot.
  • flip_y=true por defecto porque la convencion en GLSL es V hacia arriba.
  • srgb opcional — para texturas LDR de color, GL_SRGB8_ALPHA8 da un gamma correcto sin tener que pow(color, 2.2) en el shader.

Riesgos

  • Tamaño de imagenes: cargar PNGs de 4K consume RAM/VRAM. Documentar limite practico (<= 8192 lado).
  • Driver no soporta sRGB: documentar fallback a GL_RGBA8.
  • Codigo de stb_image lento: aceptable para uso interactivo (no es hot path de cada frame).