From f33d55485e428bd3ef6b0ac07b07b1d5451ed38b Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Sat, 25 Apr 2026 20:58:50 +0200 Subject: [PATCH] feat(primitives_gallery): demo de gl_texture_load + asset PNG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Añade demos_gl_texture.cpp (carga assets/sample.png con la nueva funcion gl_texture_load_cpp_gfx, muestra w/h/channels y sliders de tint RGB + zoom UV via ImGui::ImageWithBg) y un PNG damero 256x256 generado para la demo. Tambien registra apps/primitives_gallery como subdirectorio en cpp/CMakeLists.txt (la app vive como WIP en master; aqui solo se añade el hook de build). Para integrarse, demos.h, main.cpp y CMakeLists.txt de la gallery deben anadir respectivamente la declaracion gallery::demo_gl_texture(), la entrada {"gl_texture", "gl_texture_load", "Gfx", &gallery::demo_gl_texture} en k_demos[], y demos_gl_texture.cpp + cpp/functions/gfx/gl_texture_load.cpp + cpp/vendor/stb/stb_image_impl.cpp + include de cpp/vendor/stb a sus sources. Co-Authored-By: Claude Opus 4.7 (1M context) --- cpp/CMakeLists.txt | 5 + cpp/apps/primitives_gallery/assets/sample.png | Bin 0 -> 966 bytes .../primitives_gallery/demos_gl_texture.cpp | 127 ++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 cpp/apps/primitives_gallery/assets/sample.png create mode 100644 cpp/apps/primitives_gallery/demos_gl_texture.cpp diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index a1a74a89..d625b05f 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -115,6 +115,11 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/apps/shaders_lab/CMakeLists.txt) add_subdirectory(apps/shaders_lab) endif() +# --- Primitives Gallery --- +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/apps/primitives_gallery/CMakeLists.txt) + add_subdirectory(apps/primitives_gallery) +endif() + # --- Registry Dashboard (lives in projects/fn_monitoring/apps/) --- set(_DASH_DIR ${CMAKE_SOURCE_DIR}/../projects/fn_monitoring/apps/registry_dashboard) if(EXISTS ${_DASH_DIR}/CMakeLists.txt) diff --git a/cpp/apps/primitives_gallery/assets/sample.png b/cpp/apps/primitives_gallery/assets/sample.png new file mode 100644 index 0000000000000000000000000000000000000000..5156f39c3e7739cb4561556a74d9788fbe28482b GIT binary patch literal 966 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFdUQZXtkcwMxuP?lM+kl}p zaJf2j3XgODhkk_&35kph5R#BsA;`qdYwNTiA#zt!x7>@p+%~d}?>&~U`~9=baqZqo zpJR9ST>N`W?&9CCMcwcGb35PVPq*ARi8{ zws8CY`nTZS_~X$f^;P;8|K`qF{QI!=?)R(=`zZ4c*sk`ux9;sb$;{*38F#?Ue(~?i zMZNFVf0nwt{f(}m zjhnUl3?En-SQrEt96$+#T!zJ)D|OrRKQSDRTO_{WD=?zA#4rAxy&o8kcCO#O>-*nr zx20b2?fQP+yt3ii-bLa8yMUhB?Osy(jQTKZD?>L4B++-(iXv*VYD7X>tw +#include +#include + +namespace gallery { + +namespace { + +struct TextureState { + fn::GlTexture tex{}; + bool tried_load = false; + std::string_view err; + char err_buf[256] = {0}; + float tint[3] = {1.0f, 1.0f, 1.0f}; + float zoom = 1.0f; // 1.0 = sin zoom; >1 hace UV mas pequeno +}; + +TextureState& state() { + static TextureState s; + return s; +} + +// Resuelve un path para el asset. Probamos varios candidatos relativos al cwd +// del binario (puede lanzarse desde build/ o desde la raiz del repo). +const char* resolve_sample_path() { + static const char* candidates[] = { + "assets/sample.png", + "apps/primitives_gallery/assets/sample.png", + "cpp/apps/primitives_gallery/assets/sample.png", + "../cpp/apps/primitives_gallery/assets/sample.png", + "../../cpp/apps/primitives_gallery/assets/sample.png", + "../../../cpp/apps/primitives_gallery/assets/sample.png", + nullptr, + }; + for (int i = 0; candidates[i]; i++) { + FILE* f = std::fopen(candidates[i], "rb"); + if (f) { std::fclose(f); return candidates[i]; } + } + return candidates[0]; // devolver el primer candidato para que el error sea mas descriptivo +} + +} // namespace + +void demo_gl_texture() { + demo_header("gl_texture_load", "v1.0.0", + "Carga PNG/JPG/HDR desde disco a una textura GL lista para sampler2D. " + "Vendorea stb_image (cpp/vendor/stb/). Demo: assets/sample.png " + "(damero 256x256), tint RGB modulando ImGui::Image, zoom UV."); + + auto& s = state(); + + if (!s.tried_load) { + // Asegurar simbolos GL resueltos (Linux no-op, Windows wglGetProcAddress). + fn::gfx::gl_loader_init(); + const char* path = resolve_sample_path(); + s.tex = fn::gl_texture_load(path, /*flip_y=*/true, /*srgb=*/false); + if (!s.tex.ok()) { + std::snprintf(s.err_buf, sizeof(s.err_buf), + "no se pudo cargar '%s': %s", + path, fn::gl_texture_last_error()); + } + s.tried_load = true; + } + + if (!s.tex.ok()) { + ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "%s", s.err_buf); + ImGui::TextWrapped( + "El binario busca el PNG en varios paths relativos al cwd. " + "Lanzar desde la raiz del repo o desde cpp/build/ deberia funcionar."); + return; + } + + section("Texture info"); + ImGui::Text("size: %d x %d px", s.tex.w, s.tex.h); + ImGui::Text("channels: %d (forzado a RGBA en upload)", s.tex.channels); + ImGui::Text("gl_id: %u", (unsigned)s.tex.id); + + section("Tint + zoom"); + ImGui::SliderFloat3("tint RGB", s.tint, 0.0f, 2.0f, "%.2f"); + ImGui::SliderFloat("zoom UV", &s.zoom, 0.25f, 4.0f, "%.2fx"); + + section("Preview"); + + // Calcular UVs centradas con zoom: 1.0 = (0,0)-(1,1), 2.0 = (0.25,0.25)-(0.75,0.75) + float u_half = 0.5f / (s.zoom > 0.001f ? s.zoom : 0.001f); + ImVec2 uv0(0.5f - u_half, 0.5f - u_half); + ImVec2 uv1(0.5f + u_half, 0.5f + u_half); + + ImVec4 tint(s.tint[0], s.tint[1], s.tint[2], 1.0f); + + // Conversion GLuint -> ImTextureID. ImGui::Image acepta cualquier id de + // textura del backend; en imgui_impl_opengl3 es directamente el GLuint. + ImTextureID tid = (ImTextureID)(intptr_t)s.tex.id; + + ImGui::ImageWithBg(tid, ImVec2(384.0f, 384.0f), uv0, uv1, + ImVec4(0, 0, 0, 0), tint); + + code_block( + "#include \"gfx/gl_texture_load.h\"\n\n" + "auto tex = fn::gl_texture_load(\"assets/sample.png\");\n" + "if (!tex.ok()) {\n" + " fprintf(stderr, \"%s\\n\", fn::gl_texture_last_error());\n" + " return 1;\n" + "}\n" + "// uso en shader:\n" + "glUseProgram(prog);\n" + "fn::gl_texture_bind_uniform(prog, \"u_tex\", tex, /*unit=*/0);\n" + "glDrawArrays(GL_TRIANGLES, 0, 6);\n\n" + "// o en ImGui directamente:\n" + "ImGui::Image((ImTextureID)(intptr_t)tex.id, ImVec2(w, h));" + ); +} + +} // namespace gallery