# 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 ```cpp 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]`). ### Fase 3 — Gallery demo - 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 ```cpp 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).