From a2f0f7c7a45ba8b30984fb135b8b54f11fb119f8 Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Mar 2026 09:33:17 +0100 Subject: feat: Implement dual-mode asset loading and update documentation This commit introduces a dual-mode asset loading system to enhance developer workflow and optimize release builds. Key changes include: - **Dual-Mode Asset Loading:** Assets are now loaded from disk during development (when is OFF) for faster iteration, particularly for heavy assets like and files. For release builds ( ON), all assets are embedded directly into the binary, ensuring a single, self-contained executable. - **Explicit Asset Typing:** Replaced generic asset type with specific types (, , , , ) in and the enum in for clearer categorization and more robust processing. - **Build System Integration:** Modified to pass a flag to in development builds. - **Asset Packer Updates:** now generates file paths for disk-loaded assets and embeds data for others based on the build mode. - **Asset Manager Enhancements:** includes new logic in for loading and caching disk-based assets and updates to for proper memory deallocation. - **Documentation:** Updated to reflect the new asset nomenclature and dual-mode loading strategy. - **Project Rules:** Added a concise rule to mandating top-level documentation updates for medium/large sub-system changes. handoff(Gemini): Implemented dual-mode asset loading and updated documentation. --- cmake/DemoCodegen.cmake | 7 +- doc/AI_RULES.md | 1 + doc/ASSET_SYSTEM.md | 88 ++++++++++++++++-------- src/effects/ntsc.wgsl | 22 +++--- src/util/asset_manager.cc | 41 +++++++++++ src/util/asset_manager.h | 8 ++- tools/asset_packer.cc | 106 +++++++++++++++-------------- workspaces/main/assets.txt | 166 ++++++++++++++++++++++----------------------- 8 files changed, 261 insertions(+), 178 deletions(-) diff --git a/cmake/DemoCodegen.cmake b/cmake/DemoCodegen.cmake index 32cb06c..4d0d271 100644 --- a/cmake/DemoCodegen.cmake +++ b/cmake/DemoCodegen.cmake @@ -239,11 +239,16 @@ add_custom_target(generate_demo_data DEPENDS ${GEN_DEMO_H}.data_stamp) # assets.h is written via copy_if_different so its mtime only changes when the # enum content changes (e.g. new asset added). This prevents unrelated # translation units (audio, 3d, …) from recompiling on every shader edit. +set(ASSET_PACKER_FLAGS "") +if(NOT DEMO_STRIP_ALL) + set(ASSET_PACKER_FLAGS "--disk_load") +endif() + set(GEN_DEMO_H_STAMP ${GEN_DEMO_H}.gen_stamp) add_custom_command( OUTPUT ${GEN_DEMO_H_STAMP} ${GEN_DEMO_CC} COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/src/generated - COMMAND ${ASSET_PACKER_CMD} ${WORKSPACE_ASSETS} ${GEN_DEMO_H}.new ${GEN_DEMO_CC} + COMMAND ${ASSET_PACKER_CMD} ${WORKSPACE_ASSETS} ${GEN_DEMO_H}.new ${GEN_DEMO_CC} ${ASSET_PACKER_FLAGS} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GEN_DEMO_H}.new ${GEN_DEMO_H} COMMAND ${CMAKE_COMMAND} -E touch ${GEN_DEMO_H_STAMP} DEPENDS ${ASSET_PACKER_DEPENDS} ${WORKSPACE_ASSETS} diff --git a/doc/AI_RULES.md b/doc/AI_RULES.md index 5500a9a..27d2d47 100644 --- a/doc/AI_RULES.md +++ b/doc/AI_RULES.md @@ -4,6 +4,7 @@ - All changes must keep tests passing - Prefer small, reviewable commits - All `cmake --build` commands must use the `-j4` option for parallel building. +- Medium/large sub-system changes require top-level doc update (summarize, streamline, archive). - after a task, a 'big' final commit should contain a short handoff tag like "handoff(Gemini):..." if you're gemini-cli, or "handoff(Claude): ..." if you're claude-code. ## Adding Visual Effects diff --git a/doc/ASSET_SYSTEM.md b/doc/ASSET_SYSTEM.md index 6104353..87d2a9a 100644 --- a/doc/ASSET_SYSTEM.md +++ b/doc/ASSET_SYSTEM.md @@ -1,6 +1,6 @@ # Compact Asset System for the 64k Demo -All assets are const byte arrays embedded in the binary. Runtime retrieval via `GetAsset(AssetId)` returns direct pointers with O(1) lookup. +This document outlines the architecture for managing assets, which are compiled into the binary for release builds but loaded from disk during development to speed up iteration. ## Asset Manifest Format @@ -8,24 +8,56 @@ Files: `workspaces/main/assets.txt`, `workspaces/test/assets.txt` Format (CSV): ``` -ASSET_NAME, COMPRESSION, path/to/file.ext, "Description" +ASSET_NAME, ASSET_TYPE, path/to/file.ext, "Description" ``` -### Compression Types +### Asset Types -| Type | Behavior | -|------|----------| -| `NONE` | Raw binary embed (shaders, meshes, `.spec` files) | -| `MP3` | MP3 audio; decoded to spectrogram at init | -| `PROC(func, ...)` | CPU procedural generation at init | -| `PROC_GPU(func, ...)` | GPU compute procedural generation at init | +The `ASSET_TYPE` field explicitly defines how the asset is processed and used at runtime. + +| Type | Description | +|------|-------------| +| `WGSL` | WGSL shader source code. | +| `SPEC` | Spectrogram data for audio synthesis. | +| `TEXTURE` | Image file (PNG, JPG, etc.), converted to a raw RGBA8 buffer with a width/height header. | +| `MESH` | 3D model file (.obj), converted to an interleaved vertex/index buffer. | +| `BINARY`| Generic raw binary data. | +| `MP3` | MP3 audio; decoded to a spectrogram at runtime. | +| `PROC(func, ...)` | CPU-based procedural generation at init time. | +| `PROC_GPU(func, ...)`| GPU-based compute shader for procedural generation at init time. | + +## Dual-Mode Loading Strategy + +The asset system operates in two modes, controlled by the `DEMO_STRIP_ALL` CMake flag: + +1. **Development Mode (`DEMO_STRIP_ALL=OFF`)**: + * Heavy assets (`SPEC`, `MP3`) are **loaded from disk** at runtime. + * The `asset_packer` generates a C-string containing the file path for these assets. + * The `AssetManager` reads the file on first access, caches it, and returns the content. + * This mode allows for rapid iteration on audio assets without requiring a full recompile. + +2. **Release Mode (`DEMO_STRIP_ALL=ON`)**: + * All assets are **embedded directly into the binary** as `const` byte arrays. + * This creates a single, self-contained executable suitable for distribution. + * The `asset_packer` generates C++ byte arrays from the asset files. + +This dual-mode system provides both developer convenience and release-ready packaging. ## AssetType Enum -Each `AssetRecord` carries an `AssetType` field (replaces the former `is_procedural`/`is_gpu_procedural` bools): +The C++ `AssetType` enum mirrors the types defined in the asset manifest: ```cpp -enum class AssetType : uint8_t { STATIC, PROC, PROC_GPU, MP3 }; +enum class AssetType : uint8_t { + WGSL, + SPEC, + TEXTURE, + MESH, + BINARY, + MP3, + PROC, + PROC_GPU, +}; ``` Query at runtime: @@ -41,7 +73,7 @@ if (GetAssetType(AssetId::NEVER_MP3) == AssetType::MP3) { ... } // Retrieve asset data size_t size; const uint8_t* data = GetAsset(AssetId::MY_ASSET, &size); -DropAsset(AssetId::MY_ASSET, data); // Release procedural/cached data +DropAsset(AssetId::MY_ASSET, data); // Release procedural or disk-loaded data // Query type AssetType t = GetAssetType(AssetId::MY_ASSET); @@ -51,33 +83,29 @@ AssetType t = GetAssetType(AssetId::MY_ASSET); Tool: `tools/asset_packer.cc` -1. Parse workspace `assets.txt` -2. Read/process files (images → RGBA8 header, meshes → vertex/index binary, others → raw) -3. Generate `src/generated/assets.h` (enum + declarations) -4. Generate `src/generated/assets_data.cc` (byte arrays + `AssetRecord` table) -5. Auto-triggered by CMake on manifest changes +1. Parse workspace `assets.txt`. +2. If in **Development Mode**, for `SPEC` and `MP3` assets, it generates a C-string with the file path. +3. If in **Release Mode**, it reads and processes all files into byte arrays (images → RGBA8, meshes → vertex/index, etc.). +4. Generate `src/generated/assets.h` (enum + declarations). +5. Generate `src/generated/assets_data.cc` (byte arrays/paths + `AssetRecord` table). +6. Auto-triggered by CMake on manifest changes. ## Technical Guarantees -- **Alignment**: All arrays declared `alignas(16)` for safe `reinterpret_cast` -- **String Safety**: Null-terminator appended (safe as C-string) -- **Size**: `size` reflects original file size (buffer is `size + 1`) +- **Alignment**: All embedded data arrays are declared `alignas(16)` for safe `reinterpret_cast`. +- **String Safety**: Embedded assets are null-terminated (safe as C-strings). In disk-load mode, the path itself is a null-terminated C-string. +- **Size**: For embedded assets, `size` reflects the original file size (the buffer is `size + 1`). For disk-loaded assets, it reflects the file path's string length. ## Developer Workflow -**Add a static asset:** -``` -MY_ASSET, NONE, path/to/file.ext, "Description" -``` - -**Add an MP3 sample:** +**Add a spectrogram:** ``` -MY_SAMPLE, MP3, music/sample.mp3, "Description" +MY_KICK, SPEC, music/my_kick.spec, "Description" ``` -**Add a procedural texture:** +**Add a shader:** ``` -MY_TEX, PROC(gen_noise, 1234, 16), _, "Description" +MY_SHADER, WGSL, shaders/my_shader.wgsl, "Description" ``` -Rebuild: `cmake --build build -j4` — CMake detects manifest changes automatically. +Rebuild: `cmake --build build -j4` — CMake detects manifest changes automatically. In development mode, changes to `.spec` or `.mp3` files do not require a rebuild. diff --git a/src/effects/ntsc.wgsl b/src/effects/ntsc.wgsl index 31d4e0d..6c9fa37 100644 --- a/src/effects/ntsc.wgsl +++ b/src/effects/ntsc.wgsl @@ -3,9 +3,8 @@ #include "render/fullscreen_uv_vs" #include "math/noise" -const f32 vignetteRounding = 160.0f; -const f32 vignetteSmoothness = 0.7f; - +const vignetteRounding = 160.0f; +const vignetteSmoothness = 0.7f; @group(0) @binding(0) var input_sampler: sampler; @group(0) @binding(1) var input_texture: texture_2d; @@ -13,15 +12,14 @@ const f32 vignetteSmoothness = 0.7f; // Barrel (fisheye) distortion: strength > 0 = barrel, < 0 = pincushion fn fisheye(uv: vec2f, strength: f32) -> vec2f { - let c = uv * 2.0 - 1.0; - let r2 = c * c; - return uv * 1.03 * (1.0 + vec2f(.1, .24) * strength * r2); + let r2 = uv * uv; + return uv * 1.05 * (1.0 + vec2f(.1, .24) * strength * r2); } -fn vignette(vec2f uv) -> f32 { - uv *= 1.99; - f32 amount = 1.0 - sqrt(pow(abs(uv.x), vignetteRounding) + pow(abs(uv.y), vignetteRounding)); - f32 vhard = smoothstep(0., vignetteSmoothness, amount); +fn vignette(uv: vec2f) -> f32 { + let uv2 = uv * 1.99; + let amount = 1.0 - sqrt(pow(abs(uv2.x), vignetteRounding) + pow(abs(uv2.y), vignetteRounding)); + let vhard = smoothstep(0., vignetteSmoothness, amount); return vhard; } @@ -29,8 +27,8 @@ fn vignette(vec2f uv) -> f32 { let t = uniforms.time; // Fisheye/barrel distortion - let uv = fisheye(in.uv, 0.18); - uv = vignette(uv); + let uv = (fisheye(in.st, 0.18) + 1.) * .5; +// uv = vignette(uv); // Black outside screen edges if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { diff --git a/src/util/asset_manager.cc b/src/util/asset_manager.cc index 2285f3a..52a60ee 100644 --- a/src/util/asset_manager.cc +++ b/src/util/asset_manager.cc @@ -76,6 +76,39 @@ const uint8_t* GetAsset(AssetId asset_id, size_t* out_size) { AssetRecord source_record = assets[index]; +#if !defined(DEMO_STRIP_ALL) + if (source_record.type == AssetType::SPEC || + source_record.type == AssetType::MP3) { + const char* path = (const char*)source_record.data; + FILE* f = fopen(path, "rb"); + if (!f) { + if (out_size) + *out_size = 0; + return nullptr; + } + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + uint8_t* buffer = new (std::nothrow) uint8_t[size + 1]; + if (!buffer) { + fclose(f); + if (out_size) + *out_size = 0; + return nullptr; + } + fread(buffer, 1, size, f); + fclose(f); + buffer[size] = 0; // Null-terminate + + g_asset_cache[index].data = buffer; + g_asset_cache[index].size = size; + g_asset_cache[index].type = source_record.type; + if (out_size) + *out_size = size; + return buffer; + } +#endif + AssetRecord cached_record = source_record; if (source_record.type == AssetType::PROC || @@ -188,6 +221,14 @@ void DropAsset(AssetId asset_id, const uint8_t* asset) { delete[] g_asset_cache[index].data; g_asset_cache[index] = {}; // Zero out the struct to force re-generation } +#if !defined(DEMO_STRIP_ALL) + if (g_asset_cache[index].data == asset && + (g_asset_cache[index].type == AssetType::SPEC || + g_asset_cache[index].type == AssetType::MP3)) { + delete[] g_asset_cache[index].data; + g_asset_cache[index] = {}; + } +#endif // For static assets, no dynamic memory to free. } diff --git a/src/util/asset_manager.h b/src/util/asset_manager.h index 5380257..786a8db 100644 --- a/src/util/asset_manager.h +++ b/src/util/asset_manager.h @@ -6,10 +6,14 @@ #include "asset_manager_dcl.h" enum class AssetType : uint8_t { - STATIC, + WGSL, + SPEC, + TEXTURE, + MESH, + BINARY, + MP3, PROC, PROC_GPU, - MP3 }; struct AssetRecord { diff --git a/tools/asset_packer.cc b/tools/asset_packer.cc index c982a39..e28d71f 100644 --- a/tools/asset_packer.cc +++ b/tools/asset_packer.cc @@ -37,17 +37,6 @@ static const std::map kAssetPackerProcGenFuncMap = { #endif }; -static bool HasImageExtension(const std::string& filename) { - std::string ext = filename.substr(filename.find_last_of(".") + 1); - return ext == "png" || ext == "jpg" || ext == "jpeg" || ext == "tga" || - ext == "bmp"; -} - -static bool HasMeshExtension(const std::string& filename) { - std::string ext = filename.substr(filename.find_last_of(".") + 1); - return ext == "obj"; -} - // Forward declaration struct AssetBuildInfo; @@ -348,14 +337,20 @@ static bool ProcessImageFile(const std::string& full_path, } int main(int argc, char* argv[]) { - if (argc != 4) { + if (argc < 4) { fprintf(stderr, "Usage: %s " - "\n", + " [--disk_load]\n", argv[0]); return 1; } + bool disk_load_mode = false; + if (argc > 4 && std::strcmp(argv[4], "--disk_load") == 0) { + disk_load_mode = true; + printf("Asset packer running in disk-load mode.\n"); + } + std::string assets_txt_path = argv[1]; std::string output_assets_h_path = argv[2]; std::string output_assets_data_cc_path = argv[3]; @@ -438,7 +433,7 @@ int main(int argc, char* argv[]) { info.data_array_name = "ASSET_DATA_" + info.name; info.params_array_name = "ASSET_PROC_PARAMS_" + info.name; info.func_name_str_name = "ASSET_PROC_FUNC_STR_" + info.name; - info.asset_type = "STATIC"; + info.asset_type = compression_type_str; if (compression_type_str.rfind("PROC_GPU(", 0) == 0) { info.asset_type = "PROC_GPU"; @@ -452,7 +447,11 @@ int main(int argc, char* argv[]) { } } else if (compression_type_str == "MP3") { info.asset_type = "MP3"; - } else if (compression_type_str != "NONE") { + } else if (compression_type_str != "WGSL" && + compression_type_str != "SPEC" && + compression_type_str != "TEXTURE" && + compression_type_str != "MESH" && + compression_type_str != "BINARY") { fprintf(stderr, "Warning: Unknown compression type '%s' for asset: %s\n", compression_type_str.c_str(), info.name.c_str()); @@ -488,44 +487,50 @@ int main(int argc, char* argv[]) { std::filesystem::path combined_path = base_path / info.filename; std::string full_path = combined_path.lexically_normal().string(); - std::vector buffer; - bool is_image = HasImageExtension(info.filename); - bool is_mesh = HasMeshExtension(info.filename); - - if (is_image) { - if (!ProcessImageFile(full_path, &buffer, info.name)) { - return 1; - } - } else if (is_mesh) { - if (!ProcessMeshFile(full_path, &buffer, info.name)) { - return 1; - } + if (disk_load_mode && + (info.asset_type == "SPEC" || info.asset_type == "MP3")) { + fprintf(assets_data_cc_file, + "alignas(16) static const char %s[] = \"%s\";\n", + info.data_array_name.c_str(), full_path.c_str()); + fprintf(assets_data_cc_file, "const size_t ASSET_SIZE_%s = %zu;\n", + info.name.c_str(), full_path.length() + 1); } else { - std::ifstream asset_file(full_path, std::ios::binary); - if (!asset_file.is_open()) { - fprintf(stderr, "Error: Could not open asset file: %s\n", - full_path.c_str()); - return 1; + std::vector buffer; + if (info.asset_type == "TEXTURE") { + if (!ProcessImageFile(full_path, &buffer, info.name)) { + return 1; + } + } else if (info.asset_type == "MESH") { + if (!ProcessMeshFile(full_path, &buffer, info.name)) { + return 1; + } + } else { + std::ifstream asset_file(full_path, std::ios::binary); + if (!asset_file.is_open()) { + fprintf(stderr, "Error: Could not open asset file: %s\n", + full_path.c_str()); + return 1; + } + buffer.assign((std::istreambuf_iterator(asset_file)), + std::istreambuf_iterator()); } - buffer.assign((std::istreambuf_iterator(asset_file)), - std::istreambuf_iterator()); - } - - size_t original_size = buffer.size(); - buffer.push_back(0); // Null terminator for safety - fprintf(assets_data_cc_file, "const size_t ASSET_SIZE_%s = %zu;\n", - info.name.c_str(), original_size); - fprintf(assets_data_cc_file, - "alignas(16) static const uint8_t %s[] = {\n ", - info.data_array_name.c_str()); - for (size_t i = 0; i < buffer.size(); ++i) { - if (i > 0 && i % 12 == 0) - fprintf(assets_data_cc_file, "\n "); - fprintf(assets_data_cc_file, "0x%02x%s", buffer[i], - (i == buffer.size() - 1 ? "" : ", ")); + size_t original_size = buffer.size(); + buffer.push_back(0); // Null terminator for safety + + fprintf(assets_data_cc_file, "const size_t ASSET_SIZE_%s = %zu;\n", + info.name.c_str(), original_size); + fprintf(assets_data_cc_file, + "alignas(16) static const uint8_t %s[] = {\n ", + info.data_array_name.c_str()); + for (size_t i = 0; i < buffer.size(); ++i) { + if (i > 0 && i % 12 == 0) + fprintf(assets_data_cc_file, "\n "); + fprintf(assets_data_cc_file, "0x%02x%s", buffer[i], + (i == buffer.size() - 1 ? "" : ", ")); + } + fprintf(assets_data_cc_file, "\n};\n"); } - fprintf(assets_data_cc_file, "\n};\n"); } else { fprintf(assets_data_cc_file, "static const float %s[] = {", info.params_array_name.c_str()); @@ -550,7 +555,8 @@ int main(int argc, char* argv[]) { info.params_array_name.c_str(), info.proc_params.size()); } else { fprintf(assets_data_cc_file, - "%s, ASSET_SIZE_%s, AssetType::%s, nullptr, nullptr, 0", + "(const uint8_t*)%s, ASSET_SIZE_%s, AssetType::%s, nullptr, " + "nullptr, 0", info.data_array_name.c_str(), info.name.c_str(), info.asset_type.c_str()); } diff --git a/workspaces/main/assets.txt b/workspaces/main/assets.txt index 7ce8bdd..5f5bad7 100644 --- a/workspaces/main/assets.txt +++ b/workspaces/main/assets.txt @@ -8,22 +8,22 @@ # PROC_GPU(func,..) - GPU compute procedural generation at init # --- Drum & Percussion Samples --- -KICK_1, NONE, music/KICK_606.spec, "606 Kick" -KICK_2, NONE, music/KICK_90S_2.spec, "90s Kick" -SNARE_1, NONE, music/SNARE_808.spec, "808 Snare" -SNARE_2, NONE, music/SNARE_909_TUNE_8.spec, "909 Snare" -SNARE_3, NONE, music/SNARE_BLUE_ROOM.spec, "Snare Blue Room" -HIHAT_1, NONE, music/HIHAT_CLOSED_DMX.spec, "DMX Closed Hi-hat" -HIHAT_2, NONE, music/HIHAT_CLOSED_DUFF.spec, "Duff Closed Hi-hat" -HIHAT_3, NONE, music/HIHAT_CLOSED_ER_1.spec, "ER-1 Closed Hi-hat" -CRASH_1, NONE, music/CRASH_DMX.spec, "DMX Crash" -RIDE_1, NONE, music/RIDE_CUP_1.spec, "Ride Cymbal" -SPLASH_1, NONE, music/SPLASH_GROUNDED.spec, "Splash Cymbal" +KICK_1, SPEC, music/KICK_606.spec, "606 Kick" +KICK_2, SPEC, music/KICK_90S_2.spec, "90s Kick" +SNARE_1, SPEC, music/SNARE_808.spec, "808 Snare" +SNARE_2, SPEC, music/SNARE_909_TUNE_8.spec, "909 Snare" +SNARE_3, SPEC, music/SNARE_BLUE_ROOM.spec, "Snare Blue Room" +HIHAT_1, SPEC, music/HIHAT_CLOSED_DMX.spec, "DMX Closed Hi-hat" +HIHAT_2, SPEC, music/HIHAT_CLOSED_DUFF.spec, "Duff Closed Hi-hat" +HIHAT_3, SPEC, music/HIHAT_CLOSED_ER_1.spec, "ER-1 Closed Hi-hat" +CRASH_1, SPEC, music/CRASH_DMX.spec, "DMX Crash" +RIDE_1, SPEC, music/RIDE_CUP_1.spec, "Ride Cymbal" +SPLASH_1, SPEC, music/SPLASH_GROUNDED.spec, "Splash Cymbal" # --- Melodic Samples --- -BASS_1, NONE, music/BASS_GUITAR_FEEL.spec, "Bass Guitar" -BASS_2, NONE, music/BASS_SYNTH_1.spec, "Synth Bass 1" -BASS_3, NONE, music/SYNTH_BASS_DISTORT.spec, "Distorted Synth Bass" +BASS_1, SPEC, music/BASS_GUITAR_FEEL.spec, "Bass Guitar" +BASS_2, SPEC, music/BASS_SYNTH_1.spec, "Synth Bass 1" +BASS_3, SPEC, music/SYNTH_BASS_DISTORT.spec, "Distorted Synth Bass" NEVER_MP3, MP3, music/never.mp3, "MP3 Sample" DRUM_MP3, MP3, music/drum.mp3, "Drum Sample" @@ -31,74 +31,74 @@ DRUM_MP3, MP3, music/drum.mp3, "Drum Sample" NOISE_TEX, PROC(gen_noise, 1234, 16), _, "Procedural noise texture for bump mapping" # --- WGSL Shaders & Snippets --- -SHADER_RENDERER_3D, NONE, shaders/renderer_3d.wgsl, "Hybrid 3D Renderer Shader" -SHADER_COMMON_UNIFORMS, NONE, ../../src/shaders/common_uniforms.wgsl, "Common Uniforms Snippet" -SHADER_CAMERA_COMMON, NONE, ../../src/shaders/camera_common.wgsl, "Camera parameters and raymarching helpers" -SHADER_SDF_SHAPES, NONE, ../../src/shaders/math/sdf_shapes.wgsl, "SDF Shapes (2D/3D primitives)" -SHADER_LIGHTING, NONE, ../../src/shaders/lighting.wgsl, "Lighting Snippet" -SHADER_RAY_BOX, NONE, ../../src/shaders/ray_box.wgsl, "Ray-Box Intersection Snippet" -SHADER_RAY_TRIANGLE, NONE, ../../src/shaders/ray_triangle.wgsl, "Ray-Triangle Intersection Snippet (Möller-Trumbore)" -SHADER_MAIN, NONE, shaders/main_shader.wgsl, "Main Heptagon Shader" -SHADER_PARTICLE_COMPUTE, NONE, ../../src/effects/particle_compute.wgsl, "Particle Compute Shader" -SHADER_PARTICLE_RENDER, NONE, ../../src/effects/particle_render.wgsl, "Particle Render Shader" -SHADER_PARTICLE_COMPUTE_V2, NONE, ../../src/effects/particle_compute.wgsl, "Particle Compute Shader" -SHADER_PARTICLE_RENDER_V2, NONE, ../../src/effects/particle_render.wgsl, "Particle Render Shader" -SHADER_ROTATING_CUBE_V2, NONE, ../../src/effects/rotating_cube.wgsl, "Rotating Cube Shader" -SHADER_PASSTHROUGH, NONE, ../../src/shaders/passthrough.wgsl, "Passthrough Shader" -SHADER_ELLIPSE, NONE, ../../src/effects/ellipse.wgsl, "Ellipse Shader" -SHADER_PARTICLE_SPRAY_COMPUTE, NONE, ../../src/effects/particle_spray_compute.wgsl, "Particle Spray Compute" -SHADER_GAUSSIAN_BLUR, NONE, ../../src/effects/gaussian_blur.wgsl, "Gaussian Blur Shader" -SHADER_CNN_ACTIVATION, NONE, ../../cnn_v1/shaders/cnn_activation.wgsl, "CNN Activation Functions" -SHADER_CNN_CONV1X1, NONE, ../../cnn_v1/shaders/cnn_conv1x1.wgsl, "CNN 1x1 Convolution" -SHADER_CNN_CONV3X3, NONE, ../../cnn_v1/shaders/cnn_conv3x3.wgsl, "CNN 3x3 Convolution" -SHADER_CNN_CONV5X5, NONE, ../../cnn_v1/shaders/cnn_conv5x5.wgsl, "CNN 5x5 Convolution" -SHADER_CNN_CONV7X7, NONE, ../../cnn_v1/shaders/cnn_conv7x7.wgsl, "CNN 7x7 Convolution" -SHADER_CNN_WEIGHTS, NONE, ../../cnn_v1/shaders/cnn_weights_generated.wgsl, "CNN Weights (Generated)" -SHADER_CNN_LAYER, NONE, ../../cnn_v1/shaders/cnn_layer.wgsl, "CNN Layer Shader" -SHADER_CNN_V2_STATIC, NONE, ../../cnn_v2/shaders/cnn_v2_static.wgsl, "CNN v2 Static Features" -SHADER_CNN_V2_COMPUTE, NONE, ../../cnn_v2/shaders/cnn_v2_compute.wgsl, "CNN v2 Compute (Storage Buffer)" -WEIGHTS_CNN_V2, NONE, ../../cnn_v2/weights/cnn_v2_weights.bin, "CNN v2 Binary Weights" -SHADER_SOLARIZE, NONE, ../../src/effects/solarize.wgsl, "Solarize Shader" -SHADER_DISTORT, NONE, ../../src/effects/distort.wgsl, "Distort Shader" -SHADER_CHROMA_ABERRATION, NONE, ../../src/effects/chroma_aberration.wgsl, "Chroma Aberration Shader" -SHADER_VISUAL_DEBUG, NONE, shaders/visual_debug.wgsl, "Visual Debug Shader" -SHADER_SKYBOX, NONE, ../../src/shaders/skybox.wgsl, "Skybox background shader" -SHADER_MATH_SDF_SHAPES, NONE, ../../src/shaders/math/sdf_shapes.wgsl, "SDF Shapes Snippet" -SHADER_MATH_SDF_UTILS, NONE, ../../src/shaders/math/sdf_utils.wgsl, "SDF Utils Snippet" -SHADER_MATH_COMMON_UTILS, NONE, ../../src/shaders/math/common_utils.wgsl, "Common Math Utils" -SHADER_MATH_NOISE, NONE, ../../src/shaders/math/noise.wgsl, "RNG and Noise Functions" -SHADER_RENDER_SHADOWS, NONE, ../../src/shaders/render/shadows.wgsl, "Shadows Snippet" -SHADER_RENDER_SCENE_QUERY_BVH, NONE, ../../src/shaders/render/scene_query_bvh.wgsl, "Scene Query Snippet (BVH)" -SHADER_RENDER_SCENE_QUERY_LINEAR, NONE, ../../src/shaders/render/scene_query_linear.wgsl, "Scene Query Snippet (Linear)" -SHADER_RENDER_LIGHTING_UTILS, NONE, ../../src/shaders/render/lighting_utils.wgsl, "Lighting Utils Snippet" -SHADER_MESH, NONE, shaders/mesh_render.wgsl, "Mesh Rasterization Shader" -MESH_CUBE, NONE, obj/test_mesh.obj, "A simple cube mesh" -DODECAHEDRON, NONE, obj/dodecahedron.obj, "A dodecahedron mesh" -SHADER_RENDER_FULLSCREEN_VS, NONE, ../../src/shaders/render/fullscreen_vs.wgsl, "Fullscreen Vertex Shader" -SHADER_RENDER_FULLSCREEN_UV_VS, NONE, ../../src/shaders/render/fullscreen_uv_vs.wgsl, "Fullscreen Vertex Shader + UV" -SHADER_MATH_COLOR, NONE, ../../src/shaders/math/color.wgsl, "Color Functions" -SHADER_MATH_UTILS, NONE, ../../src/shaders/math/utils.wgsl, "Math Utilities" -SHADER_RENDER_RAYMARCHING, NONE, ../../src/shaders/render/raymarching.wgsl, "Raymarching Functions" -SHADER_RENDER_RAYMARCHING_ID, NONE, ../../src/shaders/render/raymarching_id.wgsl, "Raymarching-ID Functions" -SHADER_VIGNETTE, NONE, ../../src/effects/vignette.wgsl, "Vignette Shader" -SHADER_COMPUTE_GEN_NOISE, NONE, ../../src/shaders/compute/gen_noise.wgsl, "GPU Noise Compute Shader" -SHADER_COMPUTE_GEN_PERLIN, NONE, ../../src/shaders/compute/gen_perlin.wgsl, "GPU Perlin Noise Compute Shader" -SHADER_COMPUTE_GEN_GRID, NONE, ../../src/shaders/compute/gen_grid.wgsl, "GPU Grid Compute Shader" -SHADER_COMPUTE_GEN_BLEND, NONE, ../../src/shaders/compute/gen_blend.wgsl, "GPU Blend Composite Shader" -SHADER_COMPUTE_GEN_MASK, NONE, ../../src/shaders/compute/gen_mask.wgsl, "GPU Mask Composite Shader" -CIRCLE_MASK_COMPUTE_SHADER, NONE, shaders/circle_mask_compute.wgsl, "Circle mask compute shader" -CIRCLE_MASK_RENDER_SHADER, NONE, shaders/circle_mask_render.wgsl, "Circle mask render shader" -MASKED_CUBE_SHADER, NONE, shaders/masked_cube.wgsl, "Masked cube shader" -SHADER_SCENE1, NONE, ../../src/effects/scene1.wgsl, "Scene1 effect shader" -SHADER_SCENE2, NONE, ../../src/effects/scene2.wgsl, "Scene2 effect shader" -SHADER_RENDER_SCRATCH_LINES, NONE, ../../src/shaders/render/scratch_lines.wgsl, "Film scratch lines snippet" -SHADER_SCRATCH, NONE, ../../src/effects/scratch.wgsl, "Scratch effect shader" -SHADER_NTSC, NONE, ../../src/effects/ntsc.wgsl, "NTSC effect shader" +SHADER_RENDERER_3D, WGSL, shaders/renderer_3d.wgsl, "Hybrid 3D Renderer Shader" +SHADER_COMMON_UNIFORMS, WGSL, ../../src/shaders/common_uniforms.wgsl, "Common Uniforms Snippet" +SHADER_CAMERA_COMMON, WGSL, ../../src/shaders/camera_common.wgsl, "Camera parameters and raymarching helpers" +SHADER_SDF_SHAPES, WGSL, ../../src/shaders/math/sdf_shapes.wgsl, "SDF Shapes (2D/3D primitives)" +SHADER_LIGHTING, WGSL, ../../src/shaders/lighting.wgsl, "Lighting Snippet" +SHADER_RAY_BOX, WGSL, ../../src/shaders/ray_box.wgsl, "Ray-Box Intersection Snippet" +SHADER_RAY_TRIANGLE, WGSL, ../../src/shaders/ray_triangle.wgsl, "Ray-Triangle Intersection Snippet (Möller-Trumbore)" +SHADER_MAIN, WGSL, shaders/main_shader.wgsl, "Main Heptagon Shader" +SHADER_PARTICLE_COMPUTE, WGSL, ../../src/effects/particle_compute.wgsl, "Particle Compute Shader" +SHADER_PARTICLE_RENDER, WGSL, ../../src/effects/particle_render.wgsl, "Particle Render Shader" +SHADER_PARTICLE_COMPUTE_V2, WGSL, ../../src/effects/particle_compute.wgsl, "Particle Compute Shader" +SHADER_PARTICLE_RENDER_V2, WGSL, ../../src/effects/particle_render.wgsl, "Particle Render Shader" +SHADER_ROTATING_CUBE_V2, WGSL, ../../src/effects/rotating_cube.wgsl, "Rotating Cube Shader" +SHADER_PASSTHROUGH, WGSL, ../../src/shaders/passthrough.wgsl, "Passthrough Shader" +SHADER_ELLIPSE, WGSL, ../../src/effects/ellipse.wgsl, "Ellipse Shader" +SHADER_PARTICLE_SPRAY_COMPUTE, WGSL, ../../src/effects/particle_spray_compute.wgsl, "Particle Spray Compute" +SHADER_GAUSSIAN_BLUR, WGSL, ../../src/effects/gaussian_blur.wgsl, "Gaussian Blur Shader" +SHADER_CNN_ACTIVATION, WGSL, ../../cnn_v1/shaders/cnn_activation.wgsl, "CNN Activation Functions" +SHADER_CNN_CONV1X1, WGSL, ../../cnn_v1/shaders/cnn_conv1x1.wgsl, "CNN 1x1 Convolution" +SHADER_CNN_CONV3X3, WGSL, ../../cnn_v1/shaders/cnn_conv3x3.wgsl, "CNN 3x3 Convolution" +SHADER_CNN_CONV5X5, WGSL, ../../cnn_v1/shaders/cnn_conv5x5.wgsl, "CNN 5x5 Convolution" +SHADER_CNN_CONV7X7, WGSL, ../../cnn_v1/shaders/cnn_conv7x7.wgsl, "CNN 7x7 Convolution" +SHADER_CNN_WEIGHTS, WGSL, ../../cnn_v1/shaders/cnn_weights_generated.wgsl, "CNN Weights (Generated)" +SHADER_CNN_LAYER, WGSL, ../../cnn_v1/shaders/cnn_layer.wgsl, "CNN Layer Shader" +SHADER_CNN_V2_STATIC, WGSL, ../../cnn_v2/shaders/cnn_v2_static.wgsl, "CNN v2 Static Features" +SHADER_CNN_V2_COMPUTE, WGSL, ../../cnn_v2/shaders/cnn_v2_compute.wgsl, "CNN v2 Compute (Storage Buffer)" +WEIGHTS_CNN_V2, BINARY, ../../cnn_v2/weights/cnn_v2_weights.bin, "CNN v2 Binary Weights" +SHADER_SOLARIZE, WGSL, ../../src/effects/solarize.wgsl, "Solarize Shader" +SHADER_DISTORT, WGSL, ../../src/effects/distort.wgsl, "Distort Shader" +SHADER_CHROMA_ABERRATION, WGSL, ../../src/effects/chroma_aberration.wgsl, "Chroma Aberration Shader" +SHADER_VISUAL_DEBUG, WGSL, shaders/visual_debug.wgsl, "Visual Debug Shader" +SHADER_SKYBOX, WGSL, ../../src/shaders/skybox.wgsl, "Skybox background shader" +SHADER_MATH_SDF_SHAPES, WGSL, ../../src/shaders/math/sdf_shapes.wgsl, "SDF Shapes Snippet" +SHADER_MATH_SDF_UTILS, WGSL, ../../src/shaders/math/sdf_utils.wgsl, "SDF Utils Snippet" +SHADER_MATH_COMMON_UTILS, WGSL, ../../src/shaders/math/common_utils.wgsl, "Common Math Utils" +SHADER_MATH_NOISE, WGSL, ../../src/shaders/math/noise.wgsl, "RNG and Noise Functions" +SHADER_RENDER_SHADOWS, WGSL, ../../src/shaders/render/shadows.wgsl, "Shadows Snippet" +SHADER_RENDER_SCENE_QUERY_BVH, WGSL, ../../src/shaders/render/scene_query_bvh.wgsl, "Scene Query Snippet (BVH)" +SHADER_RENDER_SCENE_QUERY_LINEAR, WGSL, ../../src/shaders/render/scene_query_linear.wgsl, "Scene Query Snippet (Linear)" +SHADER_RENDER_LIGHTING_UTILS, WGSL, ../../src/shaders/render/lighting_utils.wgsl, "Lighting Utils Snippet" +SHADER_MESH, WGSL, shaders/mesh_render.wgsl, "Mesh Rasterization Shader" +MESH_CUBE, MESH, obj/test_mesh.obj, "A simple cube mesh" +DODECAHEDRON, MESH, obj/dodecahedron.obj, "A dodecahedron mesh" +SHADER_RENDER_FULLSCREEN_VS, WGSL, ../../src/shaders/render/fullscreen_vs.wgsl, "Fullscreen Vertex Shader" +SHADER_RENDER_FULLSCREEN_UV_VS, WGSL, ../../src/shaders/render/fullscreen_uv_vs.wgsl, "Fullscreen Vertex Shader + UV" +SHADER_MATH_COLOR, WGSL, ../../src/shaders/math/color.wgsl, "Color Functions" +SHADER_MATH_UTILS, WGSL, ../../src/shaders/math/utils.wgsl, "Math Utilities" +SHADER_RENDER_RAYMARCHING, WGSL, ../../src/shaders/render/raymarching.wgsl, "Raymarching Functions" +SHADER_RENDER_RAYMARCHING_ID, WGSL, ../../src/shaders/render/raymarching_id.wgsl, "Raymarching-ID Functions" +SHADER_VIGNETTE, WGSL, ../../src/effects/vignette.wgsl, "Vignette Shader" +SHADER_COMPUTE_GEN_NOISE, WGSL, ../../src/shaders/compute/gen_noise.wgsl, "GPU Noise Compute Shader" +SHADER_COMPUTE_GEN_PERLIN, WGSL, ../../src/shaders/compute/gen_perlin.wgsl, "GPU Perlin Noise Compute Shader" +SHADER_COMPUTE_GEN_GRID, WGSL, ../../src/shaders/compute/gen_grid.wgsl, "GPU Grid Compute Shader" +SHADER_COMPUTE_GEN_BLEND, WGSL, ../../src/shaders/compute/gen_blend.wgsl, "GPU Blend Composite Shader" +SHADER_COMPUTE_GEN_MASK, WGSL, ../../src/shaders/compute/gen_mask.wgsl, "GPU Mask Composite Shader" +CIRCLE_MASK_COMPUTE_SHADER, WGSL, shaders/circle_mask_compute.wgsl, "Circle mask compute shader" +CIRCLE_MASK_RENDER_SHADER, WGSL, shaders/circle_mask_render.wgsl, "Circle mask render shader" +MASKED_CUBE_SHADER, WGSL, shaders/masked_cube.wgsl, "Masked cube shader" +SHADER_SCENE1, WGSL, ../../src/effects/scene1.wgsl, "Scene1 effect shader" +SHADER_SCENE2, WGSL, ../../src/effects/scene2.wgsl, "Scene2 effect shader" +SHADER_RENDER_SCRATCH_LINES, WGSL, ../../src/shaders/render/scratch_lines.wgsl, "Film scratch lines snippet" +SHADER_SCRATCH, WGSL, ../../src/effects/scratch.wgsl, "Scratch effect shader" +SHADER_NTSC, WGSL, ../../src/effects/ntsc.wgsl, "NTSC effect shader" # --- Sequence Shaders --- -SHADER_SEQUENCE_V2_UNIFORMS, NONE, ../../src/shaders/sequence_uniforms.wgsl, "Sequence Uniforms Snippet" -SHADER_POSTPROCESS_INLINE, NONE, ../../src/shaders/postprocess_inline.wgsl, "Inline Post-Process Functions" -SHADER_PASSTHROUGH_V2, NONE, ../../src/shaders/passthrough.wgsl, "Passthrough Shader" -SHADER_GAUSSIAN_BLUR_V2, NONE, ../../src/shaders/gaussian_blur.wgsl, "Gaussian Blur Shader" -SHADER_HEPTAGON_V2, NONE, ../../src/shaders/heptagon.wgsl, "Heptagon Shader" -SHADER_FLASH, NONE, ../../src/effects/flash.wgsl, "Flash Shader" +SHADER_SEQUENCE_V2_UNIFORMS, WGSL, ../../src/shaders/sequence_uniforms.wgsl, "Sequence Uniforms Snippet" +SHADER_POSTPROCESS_INLINE, WGSL, ../../src/shaders/postprocess_inline.wgsl, "Inline Post-Process Functions" +SHADER_PASSTHROUGH_V2, WGSL, ../../src/shaders/passthrough.wgsl, "Passthrough Shader" +SHADER_GAUSSIAN_BLUR_V2, WGSL, ../../src/shaders/gaussian_blur.wgsl, "Gaussian Blur Shader" +SHADER_HEPTAGON_V2, WGSL, ../../src/shaders/heptagon.wgsl, "Heptagon Shader" +SHADER_FLASH, WGSL, ../../src/effects/flash.wgsl, "Flash Shader" -- cgit v1.2.3