summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-01 16:18:19 +0100
committerskal <pascal.massimino@gmail.com>2026-02-01 16:18:19 +0100
commit1522b95c838fc3e567066fd96dede3dca25cbc95 (patch)
tree24dd8d2bc586f8b9f8f3518b4fe68907e8eeb1d4
parent1481b0a6313b725eec3e3ebeea085e98703df00f (diff)
feat(gpu): Integrate bumpy 3D renderer into main demo
- Added depth buffer support to MainSequence. - Implemented Hybrid3DEffect for the main timeline. - Fixed effect initialization order in MainSequence. - Ensured depth-stencil compatibility for all scene effects. - Updated demo sequence with 3D elements and post-processing.
-rw-r--r--CMakeLists.txt3
-rw-r--r--assets/demo.seq19
-rw-r--r--assets/final/demo_assets.txt4
-rw-r--r--src/3d/renderer.cc1
-rw-r--r--src/gpu/demo_effects.h19
-rw-r--r--src/gpu/effect.cc47
-rw-r--r--src/gpu/effect.h9
-rw-r--r--src/gpu/effects/hybrid_3d_effect.cc80
-rw-r--r--src/gpu/effects/hybrid_3d_effect.h14
-rw-r--r--src/gpu/gpu.cc7
-rw-r--r--src/gpu/texture_manager.cc33
-rw-r--r--src/gpu/texture_manager.h3
-rw-r--r--tools/asset_packer.cc108
13 files changed, 244 insertions, 103 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 984bb8d..d88db94 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,7 +85,9 @@ set(GPU_SOURCES
src/gpu/effects/chroma_aberration_effect.cc
src/gpu/effects/post_process_helper.cc
src/gpu/effects/shaders.cc
+ src/gpu/effects/hybrid_3d_effect.cc
src/gpu/texture_manager.cc
+ src/3d/renderer.cc
)
set(UTIL_SOURCES src/util/asset_manager.cc ${GEN_DEMO_CC})
set(PLATFORM_SOURCES src/platform.cc third_party/glfw3webgpu/glfw3webgpu.c)
@@ -133,6 +135,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/src/generated
COMMAND ${SEQ_COMPILER_CMD} ${DEMO_SEQ_PATH} ${GENERATED_TIMELINE_CC}
DEPENDS ${SEQ_COMPILER_DEPENDS} ${DEMO_SEQ_PATH}
+ src/gpu/demo_effects.h
COMMENT \"Compiling demo sequence...\"
)
add_custom_target(generate_timeline ALL DEPENDS ${GENERATED_TIMELINE_CC})
diff --git a/assets/demo.seq b/assets/demo.seq
index 5cae67a..6b0db85 100644
--- a/assets/demo.seq
+++ b/assets/demo.seq
@@ -1,14 +1,9 @@
-# Main demo timeline
-
SEQUENCE 0.0 0
- EFFECT HeptagonEffect 0.0 1000.0 0
- EFFECT MovingEllipseEffect 0.0 1000.0 1
- EFFECT ParticlesEffect 0.0 1000.0 2
- EFFECT ParticleSprayEffect 0.0 1000.0 3
+ EFFECT HeptagonEffect 0.0 60.0 0
+ EFFECT ParticlesEffect 0.0 60.0 1
+ EFFECT Hybrid3DEffect 0.0 60.0 2
-# Post-processing layer
-SEQUENCE 0.0 1
- EFFECT SolarizeEffect 5.0 10.0 0
- EFFECT GaussianBlurEffect 10.0 15.0 0
- EFFECT DistortEffect 15.0 20.0 0
- EFFECT ChromaAberrationEffect 20.0 25.0 0 \ No newline at end of file
+# Post-processing chain
+SEQUENCE 0.0 10
+ EFFECT GaussianBlurEffect 0.0 60.0 0
+ EFFECT ChromaAberrationEffect 0.0 60.0 1
diff --git a/assets/final/demo_assets.txt b/assets/final/demo_assets.txt
index 52dd77e..a425e38 100644
--- a/assets/final/demo_assets.txt
+++ b/assets/final/demo_assets.txt
@@ -1,3 +1,5 @@
# Asset Name, Compression Type, Filename/Placeholder, Description
KICK_1, NONE, kick1.spec, "A drum kick sample"
-NOISE_TEX, PROC(gen_noise, 1234, 16), _, "Procedural noise texture for bump mapping" \ No newline at end of file
+SNARE_1, NONE, snare1.spec, "A snare drum sample"
+HIHAT_1, NONE, hihat1.spec, "A hi-hat sample"
+NOISE_TEX, PROC(gen_noise, 1234, 16), _, "Procedural noise texture for bump mapping"
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc
index 0d0b2d8..0a2ae9a 100644
--- a/src/3d/renderer.cc
+++ b/src/3d/renderer.cc
@@ -4,6 +4,7 @@
#include "3d/renderer.h"
#include <algorithm>
#include <cstring>
+#include <cassert>
#include <iostream>
static const char* kShaderCode = R"(
diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h
index fb8d531..0ff75b9 100644
--- a/src/gpu/demo_effects.h
+++ b/src/gpu/demo_effects.h
@@ -6,6 +6,10 @@
#include "gpu/effects/post_process_helper.h"
#include "gpu/effects/shaders.h"
#include "gpu/gpu.h"
+#include "3d/renderer.h"
+#include "3d/scene.h"
+#include "3d/camera.h"
+#include "gpu/texture_manager.h"
#include <memory>
static const int NUM_PARTICLES = 10000;
@@ -108,6 +112,21 @@ class ChromaAberrationEffect : public PostProcessEffect {
void update_bind_group(WGPUTextureView input_view) override;
};
+class Hybrid3DEffect : public Effect {
+ public:
+ Hybrid3DEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format);
+ void init(MainSequence* demo) override;
+ void render(WGPURenderPassEncoder pass, float time, float beat,
+ float intensity, float aspect_ratio) override;
+ private:
+ Renderer3D renderer_;
+ TextureManager texture_manager_;
+ Scene scene_;
+ Camera camera_;
+ int width_ = 1280;
+ int height_ = 720;
+};
+
// Auto-generated function to populate the timeline
void LoadTimeline(MainSequence& main_seq, WGPUDevice device, WGPUQueue queue,
WGPUTextureFormat format); \ No newline at end of file
diff --git a/src/gpu/effect.cc b/src/gpu/effect.cc
index 81d5952..fdc604c 100644
--- a/src/gpu/effect.cc
+++ b/src/gpu/effect.cc
@@ -111,14 +111,24 @@ void MainSequence::create_framebuffers(int width, int height) {
framebuffer_view_a_ = wgpuTextureCreateView(framebuffer_a_, &view_desc);
framebuffer_view_b_ = wgpuTextureCreateView(framebuffer_b_, &view_desc);
-}
-void MainSequence::init_test(WGPUDevice d, WGPUQueue q, WGPUTextureFormat f) {
- device = d;
- queue = q;
- format = f;
- // No framebuffers or passthrough effect created in test mode.
- // Test effects should not rely on these being real.
+ // Depth Buffer
+ WGPUTextureDescriptor depth_desc = {};
+ depth_desc.usage = WGPUTextureUsage_RenderAttachment;
+ depth_desc.dimension = WGPUTextureDimension_2D;
+ depth_desc.size = {(uint32_t)width, (uint32_t)height, 1};
+ depth_desc.format = WGPUTextureFormat_Depth24Plus;
+ depth_desc.mipLevelCount = 1;
+ depth_desc.sampleCount = 1;
+ depth_texture_ = wgpuDeviceCreateTexture(device, &depth_desc);
+
+ WGPUTextureViewDescriptor depth_view_desc = {};
+ depth_view_desc.format = WGPUTextureFormat_Depth24Plus;
+ depth_view_desc.dimension = WGPUTextureViewDimension_2D;
+ depth_view_desc.aspect = WGPUTextureAspect_DepthOnly;
+ depth_view_desc.mipLevelCount = 1;
+ depth_view_desc.arrayLayerCount = 1;
+ depth_view_ = wgpuTextureCreateView(depth_texture_, &depth_view_desc);
}
void MainSequence::init(WGPUDevice d, WGPUQueue q, WGPUTextureFormat f,
@@ -139,6 +149,10 @@ void MainSequence::init(WGPUDevice d, WGPUQueue q, WGPUTextureFormat f,
void MainSequence::add_sequence(std::shared_ptr<Sequence> seq, float start_time,
int priority) {
sequences_.push_back({seq, start_time, priority});
+ // If MainSequence is already initialized, init the new sequence immediately
+ if (device) {
+ seq->init(this);
+ }
std::sort(sequences_.begin(), sequences_.end(),
[](const ActiveSequence& a, const ActiveSequence& b) {
return a.priority < b.priority;
@@ -183,8 +197,16 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
#if !defined(DEMO_CROSS_COMPILE_WIN32)
scene_attachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
#endif /* !defined(DEMO_CROSS_COMPILE_WIN32) */
+
+ WGPURenderPassDepthStencilAttachment depth_attachment = {};
+ depth_attachment.view = depth_view_;
+ depth_attachment.depthLoadOp = WGPULoadOp_Clear;
+ depth_attachment.depthStoreOp = WGPUStoreOp_Store;
+ depth_attachment.depthClearValue = 1.0f;
+
WGPURenderPassDescriptor scene_desc = {.colorAttachmentCount = 1,
- .colorAttachments = &scene_attachment};
+ .colorAttachments = &scene_attachment,
+ .depthStencilAttachment = &depth_attachment};
WGPURenderPassEncoder scene_pass =
wgpuCommandEncoderBeginRenderPass(encoder, &scene_desc);
for (const SequenceItem* item : scene_effects) {
@@ -200,7 +222,10 @@ void MainSequence::render_frame(float global_time, float beat, float peak,
if (post_effects.empty()) {
wgpuSurfaceGetCurrentTexture(surface, &st);
final_view = wgpuTextureCreateView(st.texture, nullptr);
- passthrough_effect_->update_bind_group(framebuffer_view_a_);
+
+ // Safely cast to PostProcessEffect to call update_bind_group
+ PostProcessEffect* pp_effect = (PostProcessEffect*)passthrough_effect_.get();
+ pp_effect->update_bind_group(framebuffer_view_a_);
WGPURenderPassColorAttachment final_attachment = {};
final_attachment.view = final_view;
@@ -274,6 +299,10 @@ void MainSequence::shutdown() {
wgpuTextureViewRelease(framebuffer_view_b_);
if (framebuffer_b_)
wgpuTextureRelease(framebuffer_b_);
+ if (depth_view_)
+ wgpuTextureViewRelease(depth_view_);
+ if (depth_texture_)
+ wgpuTextureRelease(depth_texture_);
for (ActiveSequence& entry : sequences_) {
entry.seq->reset();
}
diff --git a/src/gpu/effect.h b/src/gpu/effect.h
index 51b3883..5d6b666 100644
--- a/src/gpu/effect.h
+++ b/src/gpu/effect.h
@@ -122,12 +122,11 @@ class MainSequence {
WGPUTextureView framebuffer_view_a_ = nullptr;
WGPUTexture framebuffer_b_ = nullptr;
WGPUTextureView framebuffer_view_b_ = nullptr;
+
+ WGPUTexture depth_texture_ = nullptr;
+ WGPUTextureView depth_view_ = nullptr;
- public: // Made public for testing
- void init_test(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format);
-
- private: // Restore private access for other members
- std::unique_ptr<PostProcessEffect> passthrough_effect_;
+ std::unique_ptr<Effect> passthrough_effect_;
void create_framebuffers(int width, int height);
};
diff --git a/src/gpu/effects/hybrid_3d_effect.cc b/src/gpu/effects/hybrid_3d_effect.cc
new file mode 100644
index 0000000..41ede0b
--- /dev/null
+++ b/src/gpu/effects/hybrid_3d_effect.cc
@@ -0,0 +1,80 @@
+// This file is part of the 64k demo project.
+// It implements the Hybrid3DEffect.
+
+#include "gpu/effects/hybrid_3d_effect.h"
+#include "util/asset_manager.h"
+#include "generated/assets.h"
+#include <cmath>
+#include <cassert>
+#include <iostream>
+
+Hybrid3DEffect::Hybrid3DEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : Effect(device, queue), width_(1280), height_(720) {
+ (void)format; // Passed to base, not directly used here.
+}
+
+void Hybrid3DEffect::init(MainSequence* demo) {
+ (void)demo;
+ WGPUTextureFormat format = demo->format; // Get current format from MainSequence (might be different than constructor if resized)
+
+ renderer_.init(device_, queue_, format);
+ renderer_.resize(width_, height_);
+
+ // Texture Manager
+ texture_manager_.init(device_, queue_);
+
+ // Load Noise Asset
+ size_t size = 0;
+ const uint8_t* noise_data = GetAsset(AssetId::ASSET_NOISE_TEX, &size);
+ if (noise_data && size == 256 * 256 * 4) {
+ texture_manager_.create_texture("noise", 256, 256, noise_data);
+ renderer_.set_noise_texture(texture_manager_.get_texture_view("noise"));
+ } else {
+ std::cerr << "Failed to load NOISE_TEX asset." << std::endl;
+ }
+
+ // Setup Scene
+ scene_.clear();
+ Object3D center(ObjectType::BOX); // Use BOX for bumps
+ center.position = vec3(0, 0, 0);
+ center.color = vec4(1, 0, 0, 1);
+ scene_.add_object(center);
+
+ for (int i = 0; i < 8; ++i) {
+ ObjectType type = ObjectType::SPHERE;
+ if (i % 3 == 1) type = ObjectType::TORUS;
+ if (i % 3 == 2) type = ObjectType::BOX;
+
+ Object3D obj(type);
+ float angle = (i / 8.0f) * 6.28318f;
+ obj.position = vec3(std::cos(angle) * 4.0f, 0, std::sin(angle) * 4.0f);
+ obj.scale = vec3(0.5f, 0.5f, 0.5f);
+
+ if (type == ObjectType::SPHERE) obj.color = vec4(0, 1, 0, 1);
+ else if (type == ObjectType::TORUS) obj.color = vec4(0, 0.5, 1, 1);
+ else obj.color = vec4(1, 1, 0, 1);
+
+ scene_.add_object(obj);
+ }
+}
+
+void Hybrid3DEffect::render(WGPURenderPassEncoder pass, float time, float beat, float intensity, float aspect_ratio) {
+ // Animate Objects
+ for (size_t i = 1; i < scene_.objects.size(); ++i) {
+ scene_.objects[i].rotation = quat::from_axis(vec3(0, 1, 0), time * 2.0f + i);
+ scene_.objects[i].position.y = std::sin(time * 3.0f + i) * 1.5f;
+ }
+
+ // Animate Camera
+ float cam_radius = 10.0f + std::sin(time * 0.3f) * 4.0f;
+ float cam_height = 5.0f + std::cos(time * 0.4f) * 3.0f;
+ camera_.set_look_at(
+ vec3(std::sin(time * 0.5f) * cam_radius, cam_height, std::cos(time * 0.5f) * cam_radius),
+ vec3(0, 0, 0),
+ vec3(0, 1, 0)
+ );
+
+ camera_.aspect_ratio = aspect_ratio;
+
+ // Draw
+ renderer_.draw(pass, scene_, camera_, time);
+}
diff --git a/src/gpu/effects/hybrid_3d_effect.h b/src/gpu/effects/hybrid_3d_effect.h
index a0a82b5..1b0eab7 100644
--- a/src/gpu/effects/hybrid_3d_effect.h
+++ b/src/gpu/effects/hybrid_3d_effect.h
@@ -7,21 +7,21 @@
#include "3d/renderer.h"
#include "3d/scene.h"
#include "3d/camera.h"
+#include "gpu/texture_manager.h"
class Hybrid3DEffect : public Effect {
public:
- Hybrid3DEffect();
+ Hybrid3DEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format);
virtual ~Hybrid3DEffect() override = default;
- void init(WGPUDevice device, WGPUQueue queue, int width, int height) override;
- void render(WGPURenderPassEncoder pass, float time, float beat, float alpha) override;
+ void init(MainSequence* demo) override;
+ void render(WGPURenderPassEncoder pass, float time, float beat, float intensity, float aspect_ratio) override;
private:
Renderer3D renderer_;
+ TextureManager texture_manager_;
Scene scene_;
Camera camera_;
- WGPUDevice device_ = nullptr;
- WGPUQueue queue_ = nullptr;
- int width_ = 0;
- int height_ = 0;
+ int width_ = 1280;
+ int height_ = 720;
};
diff --git a/src/gpu/gpu.cc b/src/gpu/gpu.cc
index 3cdf9aa..17d32ee 100644
--- a/src/gpu/gpu.cc
+++ b/src/gpu/gpu.cc
@@ -147,6 +147,13 @@ RenderPass gpu_create_render_pass(WGPUDevice device, WGPUTextureFormat format,
pipeline_desc.multisample.mask = 0xFFFFFFFF;
pipeline_desc.fragment = &fragment_state;
+ // Depth Stencil State (Required for compatibility with MainSequence pass)
+ WGPUDepthStencilState depth_stencil = {};
+ depth_stencil.format = WGPUTextureFormat_Depth24Plus;
+ depth_stencil.depthWriteEnabled = WGPUOptionalBool_False;
+ depth_stencil.depthCompare = WGPUCompareFunction_Always;
+ pipeline_desc.depthStencil = &depth_stencil;
+
pass.pipeline = wgpuDeviceCreateRenderPipeline(device, &pipeline_desc);
return pass;
diff --git a/src/gpu/texture_manager.cc b/src/gpu/texture_manager.cc
index 4240245..f2d93ad 100644
--- a/src/gpu/texture_manager.cc
+++ b/src/gpu/texture_manager.cc
@@ -36,11 +36,21 @@ void TextureManager::create_procedural_texture(
def.gen_func(pixel_data.data(), def.width, def.height, def.params.data(),
(int)def.params.size());
- WGPUExtent3D tex_size = {(uint32_t)def.width, (uint32_t)def.height, 1};
+ create_texture(name, def.width, def.height, pixel_data.data());
+
+#if !defined(STRIP_ALL)
+ std::cout << "Generated procedural texture: " << name << " (" << def.width
+ << "x" << def.height << ")" << std::endl;
+#endif
+}
+
+void TextureManager::create_texture(const std::string& name, int width, int height, const uint8_t* data) {
+ WGPUExtent3D tex_size = {(uint32_t)width, (uint32_t)height, 1};
// 2. Create GPU Texture
WGPUTextureDescriptor tex_desc = {};
- tex_desc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst;
+ tex_desc.usage =
+ WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst;
tex_desc.dimension = WGPUTextureDimension_2D;
tex_desc.size = tex_size;
tex_desc.format = WGPUTextureFormat_RGBA8Unorm;
@@ -63,11 +73,11 @@ void TextureManager::create_procedural_texture(
WGPU_TEX_DATA_LAYOUT source_layout = {};
source_layout.offset = 0;
- source_layout.bytesPerRow = def.width * 4;
- source_layout.rowsPerImage = def.height;
+ source_layout.bytesPerRow = width * 4;
+ source_layout.rowsPerImage = height;
- wgpuQueueWriteTexture(queue_, &destination, pixel_data.data(),
- pixel_data.size(), &source_layout, &tex_size);
+ wgpuQueueWriteTexture(queue_, &destination, data,
+ width * height * 4, &source_layout, &tex_size);
// 4. Create View
WGPUTextureViewDescriptor view_desc = {};
@@ -85,15 +95,10 @@ void TextureManager::create_procedural_texture(
GpuTexture gpu_tex;
gpu_tex.texture = texture;
gpu_tex.view = view;
- gpu_tex.width = def.width;
- gpu_tex.height = def.height;
-
+ gpu_tex.width = width;
+ gpu_tex.height = height;
+
textures_[name] = gpu_tex;
-
-#if !defined(STRIP_ALL)
- std::cout << "Generated procedural texture: " << name << " (" << def.width
- << "x" << def.height << ")" << std::endl;
-#endif
}
WGPUTextureView TextureManager::get_texture_view(const std::string& name) {
diff --git a/src/gpu/texture_manager.h b/src/gpu/texture_manager.h
index 3faf74c..54dcfeb 100644
--- a/src/gpu/texture_manager.h
+++ b/src/gpu/texture_manager.h
@@ -37,6 +37,9 @@ class TextureManager {
// Registers and generates a texture immediately
void create_procedural_texture(const std::string& name,
const ProceduralTextureDef& def);
+
+ // Creates a texture from existing data (RGBA8)
+ void create_texture(const std::string& name, int width, int height, const uint8_t* data);
// Retrieves a texture view by name (returns nullptr if not found)
WGPUTextureView get_texture_view(const std::string& name);
diff --git a/tools/asset_packer.cc b/tools/asset_packer.cc
index 8ae4742..a91552a 100644
--- a/tools/asset_packer.cc
+++ b/tools/asset_packer.cc
@@ -2,8 +2,8 @@
// It implements the asset packer tool for demoscene resource management.
// Converts external files into embedded C++ byte arrays and look-up records.
+#include <cstdio> // for simplicity, use fprintf() for output generation
#include <fstream>
-#include <iostream>
#include <map>
#include <string>
#include <vector>
@@ -36,9 +36,7 @@ struct AssetBuildInfo {
int main(int argc, char* argv[]) {
if (argc != 4) {
- std::cerr << "Usage: " << argv[0]
- << " <assets.txt_path> <output_assets_h_path> "
- "<output_assets_data_cc_path>\n";
+ fprintf(stderr, "Usage: %s <assets.txt_path> <output_assets_h_path> <output_assets_data_cc_path>\n", argv[0]);
return 1;
}
@@ -48,44 +46,39 @@ int main(int argc, char* argv[]) {
std::ifstream assets_txt_file(assets_txt_path);
if (!assets_txt_file.is_open()) {
- std::cerr << "Error: Could not open assets.txt at " << assets_txt_path
- << "\n";
+ fprintf(stderr, "Error: Could not open assets.txt at %s\n", assets_txt_path.c_str());
return 1;
}
- std::ofstream assets_h_file(output_assets_h_path);
- if (!assets_h_file.is_open()) {
- std::cerr << "Error: Could not open output assets.h at "
- << output_assets_h_path << "\n";
+ FILE* assets_h_file = std::fopen(output_assets_h_path.c_str(), "w");
+ if (!assets_h_file) {
+ fprintf(stderr, "Error: Could not open output assets.h at %s\n", output_assets_h_path.c_str());
return 1;
}
- std::ofstream assets_data_cc_file(output_assets_data_cc_path);
- if (!assets_data_cc_file.is_open()) {
- std::cerr << "Error: Could not open output assets_data.cc at "
- << output_assets_data_cc_path << "\n";
+ FILE* assets_data_cc_file = std::fopen(output_assets_data_cc_path.c_str(), "w");
+ if (!assets_data_cc_file) {
+ fprintf(stderr, "Error: Could not open output assets_data.cc at %s\n", output_assets_data_cc_path.c_str());
return 1;
}
// Generate assets.h header
- assets_h_file
- << "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n"
- << "#pragma once\n"
- << "#include <cstdint>\n\n"
- << "enum class AssetId : uint16_t {\n";
+ fprintf(assets_h_file, "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n");
+ fprintf(assets_h_file, "#pragma once\n");
+ fprintf(assets_h_file, "#include <cstdint>\n\n");
+ fprintf(assets_h_file, "enum class AssetId : uint16_t {\n");
std::string generated_header_name = output_assets_h_path.substr(output_assets_h_path.find_last_of("/\\") + 1);
// Generate assets_data.cc header
- assets_data_cc_file
- << "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n"
- << "#include \"util/asset_manager.h\"\n"
- << "#include \"generated/" << generated_header_name << "\"\n\n";
+ fprintf(assets_data_cc_file, "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n");
+ fprintf(assets_data_cc_file, "#include \"util/asset_manager.h\"\n");
+ fprintf(assets_data_cc_file, "#include \"generated/%s\"\n\n", generated_header_name.c_str());
// Forward declare procedural functions for AssetRecord initialization
- assets_data_cc_file << "namespace procedural { void gen_noise(uint8_t*, int, int, const float*, int); }\n"
- << "namespace procedural { void gen_grid(uint8_t*, int, int, const float*, int); }\n"
- << "namespace procedural { void make_periodic(uint8_t*, int, int, const float*, int); }\n\n";
+ fprintf(assets_data_cc_file, "namespace procedural { void gen_noise(uint8_t*, int, int, const float*, int); }\n");
+ fprintf(assets_data_cc_file, "namespace procedural { void gen_grid(uint8_t*, int, int, const float*, int); }\n");
+ fprintf(assets_data_cc_file, "namespace procedural { void make_periodic(uint8_t*, int, int, const float*, int); }\n\n");
std::vector<AssetBuildInfo> asset_build_infos;
int asset_id_counter = 0;
@@ -115,7 +108,7 @@ int main(int argc, char* argv[]) {
size_t open_paren = compression_type_str.find('(');
size_t close_paren = compression_type_str.rfind(')');
if (open_paren == std::string::npos || close_paren == std::string::npos) {
- std::cerr << "Error: Invalid PROC() syntax for asset: " << info.name << ", string: [" << compression_type_str << "]\n";
+ fprintf(stderr, "Error: Invalid PROC() syntax for asset: %s, string: [%s]\n", info.name.c_str(), compression_type_str.c_str());
return 1;
}
std::string func_and_params_str = compression_type_str.substr(open_paren + 1, close_paren - open_paren - 1);
@@ -134,7 +127,7 @@ int main(int argc, char* argv[]) {
try {
info.proc_params.push_back(std::stof(param_val_str));
} catch (...) {
- std::cerr << "Error: Invalid proc param for " << info.name << ": " << param_val_str << "\n";
+ fprintf(stderr, "Error: Invalid proc param for %s: %s\n", info.name.c_str(), param_val_str.c_str());
return 1;
}
if (comma_pos == std::string::npos) break;
@@ -147,67 +140,72 @@ int main(int argc, char* argv[]) {
// Validate procedural function name
// kAssetPackerProcGenFuncMap is defined globally for validation
if (kAssetPackerProcGenFuncMap.find(info.proc_func_name) == kAssetPackerProcGenFuncMap.end()) {
- std::cerr << "Error: Unknown procedural function: " << info.proc_func_name << " for asset: " << info.name << "\n";
+ fprintf(stderr, "Error: Unknown procedural function: %s for asset: %s\n", info.proc_func_name.c_str(), info.name.c_str());
return 1;
}
}
asset_build_infos.push_back(info);
- assets_h_file << " ASSET_" << info.name << " = " << asset_id_counter++ << ",\n";
+ fprintf(assets_h_file, " ASSET_%s = %d,\n", info.name.c_str(), asset_id_counter++);
} else {
- std::cerr << "Warning: Skipping malformed line in assets.txt: " << line << "\n";
+ fprintf(stderr, "Warning: Skipping malformed line in assets.txt: %s\n", line.c_str());
}
}
- assets_h_file << " ASSET_LAST_ID = " << asset_id_counter << ",\n";
- assets_h_file << "};\n";
+ fprintf(assets_h_file, " ASSET_LAST_ID = %d,\n", asset_id_counter);
+ fprintf(assets_h_file, "};\n");
- assets_h_file << "#include \"util/asset_manager.h\"\n"; // Include here AFTER enum definition
- assets_h_file.close();
+ fprintf(assets_h_file, "#include \"util/asset_manager.h\"\n"); // Include here AFTER enum definition
+ std::fclose(assets_h_file);
for (const auto& info : asset_build_infos) {
if (!info.is_procedural) {
std::string base_dir = assets_txt_path.substr(0, assets_txt_path.find_last_of("/\\") + 1);
std::ifstream asset_file(base_dir + info.filename, std::ios::binary);
if (!asset_file.is_open()) {
- std::cerr << "Error: Could not open asset file: " << base_dir + info.filename << "\n";
+ fprintf(stderr, "Error: Could not open asset file: %s\n", (base_dir + info.filename).c_str());
return 1;
}
std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(asset_file)), std::istreambuf_iterator<char>());
- assets_data_cc_file << "static const uint8_t " << info.data_array_name << "[] = {\n ";
+ fprintf(assets_data_cc_file, "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) assets_data_cc_file << "\n ";
- assets_data_cc_file << "0x" << std::hex << (int)buffer[i] << std::dec << (i == buffer.size() - 1 ? "" : ", ");
+ 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 ? "" : ", "));
}
- assets_data_cc_file << "\n};\n";
+ fprintf(assets_data_cc_file, "\n};\n");
} else {
- assets_data_cc_file << "static const float " << info.params_array_name << "[] = {";
+ fprintf(assets_data_cc_file, "static const float %s[] = {", info.params_array_name.c_str());
for (size_t i = 0; i < info.proc_params.size(); ++i) {
- if (i > 0) assets_data_cc_file << ", ";
- assets_data_cc_file << info.proc_params[i];
+ if (i > 0) fprintf(assets_data_cc_file, ", ");
+ fprintf(assets_data_cc_file, "%f", info.proc_params[i]);
}
- assets_data_cc_file << "};\n\n";
- assets_data_cc_file << "static const char* " << info.func_name_str_name << " = \"" << info.proc_func_name << "\";\n\n";
+ fprintf(assets_data_cc_file, "};\n\n");
+ fprintf(assets_data_cc_file, "static const char* %s = \"%s\";\n\n", info.func_name_str_name.c_str(), info.proc_func_name.c_str());
}
}
- assets_data_cc_file << "extern const AssetRecord g_assets[] = {\n";
+ fprintf(assets_data_cc_file, "extern const AssetRecord g_assets[] = {\n");
for (const auto& info : asset_build_infos) {
- assets_data_cc_file << " {";
+ fprintf(assets_data_cc_file, " { ");
if (info.is_procedural) {
- assets_data_cc_file << " nullptr, 0, true, " << info.func_name_str_name << ", " << info.params_array_name << ", " << info.proc_params.size();
+ fprintf(assets_data_cc_file, "nullptr, 0, true, %s, %s, %zu",
+ info.func_name_str_name.c_str(),
+ info.params_array_name.c_str(),
+ info.proc_params.size());
} else {
- assets_data_cc_file << " " << info.data_array_name << ", sizeof(" << info.data_array_name << "), false, nullptr, nullptr, 0";
+ fprintf(assets_data_cc_file, "%s, sizeof(%s), false, nullptr, nullptr, 0",
+ info.data_array_name.c_str(),
+ info.data_array_name.c_str());
}
- assets_data_cc_file << " },\n";
+ fprintf(assets_data_cc_file, " },\n");
}
- assets_data_cc_file << "};\n";
- assets_data_cc_file << "extern const size_t g_assets_count = sizeof(g_assets) / sizeof(g_assets[0]);\n";
+ fprintf(assets_data_cc_file, "};\n");
+ fprintf(assets_data_cc_file, "extern const size_t g_assets_count = sizeof(g_assets) / sizeof(g_assets[0]);\n");
- assets_data_cc_file.close();
+ std::fclose(assets_data_cc_file);
- std::cout << "Asset packer successfully generated records for "
- << asset_build_infos.size() << " assets.\n";
+ printf("Asset packer successfully generated records for %zu assets.\n",
+ asset_build_infos.size());
return 0;
}