gl_texture_load_cpp_gfx implementado, vendoreado stb_image v2.30, gl_loader extendido con glActiveTexture y glGenerateMipmap. Demo demos_gl_texture.cpp + asset PNG damero 256x256 listos para la primitives_gallery cuando se integre en master. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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) acpp/vendor/stb/. Crearcpp/vendor/stb/stb_image_impl.cppcon#define STB_IMAGE_IMPLEMENTATIONantes del include, para evitar emitir el cuerpo en multiples TUs. - 1.2 Añadirlo a
cpp/CMakeLists.txtglobal.
Fase 2 — gl_texture_load
- 2.1 Implementar
gl_texture_load.h/.cpp. UsarglGenTextures+glTexImage2D. Filtros LINEAR_MIPMAP_LINEAR + LINEAR. Generar mipmaps conglGenerateMipmap. - 2.2 Soporte para
srgb=true(GL_SRGB8_ALPHA8como internal format). - 2.3 Soporte HDR: si extension es
.hdr, usarstbi_loadfyGL_RGBA16F. - 2.4
gl_texture_load.mdcon frontmatter (kind: function,purity: impure,error_type,uses_functions: [gl_loader_cpp_gfx]).
Fase 3 — Gallery demo
- 3.1
demos_gl_texture.cppcondemo_gl_texture_load(): cargaassets/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 indexy verificar viafn 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=truepor defecto porque la convencion en GLSL es V hacia arriba.srgbopcional — para texturas LDR de color,GL_SRGB8_ALPHA8da un gamma correcto sin tener quepow(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).