summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt6
-rw-r--r--src/3d/renderer.cc235
-rw-r--r--src/3d/renderer_draw.cc215
-rw-r--r--src/3d/renderer_mesh.cc204
-rw-r--r--src/3d/renderer_pipelines.cc255
-rw-r--r--src/3d/renderer_resources.cc54
-rw-r--r--src/3d/renderer_sdf.cc158
-rw-r--r--src/3d/renderer_skybox.cc94
9 files changed, 529 insertions, 693 deletions
diff --git a/.gitignore b/.gitignore
index bf013fe..b0b2d89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,7 @@ compile_commands.json
*.sublime-workspace
*.gemini
/assets/originals
+/assets/final
/third_party/windows
/archive
.DS_Store
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a02f256..052be7c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,9 +119,9 @@ set(GPU_SOURCES
)
set(3D_SOURCES
src/3d/renderer.cc
- src/3d/renderer_sdf.cc
- src/3d/renderer_mesh.cc
- src/3d/renderer_skybox.cc
+ src/3d/renderer_draw.cc
+ src/3d/renderer_pipelines.cc
+ src/3d/renderer_resources.cc
src/3d/visual_debug.cc
src/3d/bvh.cc
src/3d/physics.cc
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc
index e08a0d0..d846895 100644
--- a/src/3d/renderer.cc
+++ b/src/3d/renderer.cc
@@ -106,25 +106,6 @@ void Renderer3D::resize(int width, int height) {
depth_view_ = wgpuTextureCreateView(depth_texture_, &view_desc);
}
-void Renderer3D::create_default_resources() {
- global_uniform_buffer_ =
- gpu_create_buffer(device_, sizeof(GlobalUniforms),
- WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst,
- nullptr)
- .buffer;
- object_storage_buffer_ =
- gpu_create_buffer(device_, sizeof(ObjectData) * kMaxObjects,
- WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst,
- nullptr)
- .buffer;
- bvh_storage_buffer_ =
- gpu_create_buffer(
- device_,
- sizeof(BVHNode) * kMaxObjects * 2, // Capacity for a full tree
- WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr)
- .buffer;
-}
-
void Renderer3D::set_noise_texture(WGPUTextureView noise_view) {
noise_texture_view_ = noise_view;
}
@@ -140,223 +121,12 @@ void Renderer3D::add_debug_aabb(const vec3& min, const vec3& max,
#endif
}
-void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera,
- float time) {
- GlobalUniforms globals;
- globals.view_proj = camera.get_projection_matrix() * camera.get_view_matrix();
- globals.inv_view_proj = globals.view_proj.inverse();
- globals.camera_pos_time =
- vec4(camera.position.x, camera.position.y, camera.position.z, time);
- globals.params =
- vec4((float)std::min((size_t)kMaxObjects, scene.objects.size()), 0.0f,
- 0.0f, 0.0f);
- globals.resolution = vec2((float)width_, (float)height_);
- globals.padding = vec2(0.0f, 0.0f);
-
- wgpuQueueWriteBuffer(queue_, global_uniform_buffer_, 0, &globals,
- sizeof(GlobalUniforms));
-
- std::vector<ObjectData> obj_data;
- for (const auto& obj : scene.objects) {
- ObjectData data;
- data.model = obj.get_model_matrix();
-
- // Calculate Inverse for point transformation
- data.inv_model = data.model.inverse();
-
- data.color = obj.color;
- float type_id = 0.0f;
- switch (obj.type) {
- case ObjectType::SPHERE:
- type_id = 1.0f;
- break;
- case ObjectType::BOX:
- type_id = 2.0f;
- break;
- case ObjectType::CUBE:
- type_id = 2.0f;
- break; // CUBE is same as BOX for shader
- case ObjectType::TORUS:
- type_id = 3.0f;
- break;
- case ObjectType::PLANE:
- type_id = 4.0f;
- break;
- case ObjectType::MESH:
- type_id = 5.0f;
- break;
- default:
- type_id = 0.0f;
- break;
- }
- data.params = vec4(type_id, obj.local_extent.x, obj.local_extent.y,
- obj.local_extent.z);
- obj_data.push_back(data);
- if (obj_data.size() >= kMaxObjects)
- break;
- }
- if (!obj_data.empty()) {
- wgpuQueueWriteBuffer(queue_, object_storage_buffer_, 0, obj_data.data(),
- obj_data.size() * sizeof(ObjectData));
- }
-
- // Build and upload BVH (always uploaded, used by BVH pipeline)
- BVHBuilder::build(cpu_bvh_, scene.objects);
- if (!cpu_bvh_.nodes.empty()) {
- wgpuQueueWriteBuffer(queue_, bvh_storage_buffer_, 0, cpu_bvh_.nodes.data(),
- cpu_bvh_.nodes.size() * sizeof(BVHNode));
- }
-}
-
-void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene,
- const Camera& camera, float time) {
- update_uniforms(scene, camera, time);
-
- // Lazy Bind Group creation
-
- if (bind_group_)
- wgpuBindGroupRelease(bind_group_);
-
- std::vector<WGPUBindGroupEntry> bg_entries;
-
- {
- WGPUBindGroupEntry e = {};
- e.binding = 0;
- e.buffer = global_uniform_buffer_;
- e.size = sizeof(GlobalUniforms);
- bg_entries.push_back(e);
- }
-
- {
- WGPUBindGroupEntry e = {};
- e.binding = 1;
- e.buffer = object_storage_buffer_;
- e.size = sizeof(ObjectData) * kMaxObjects;
- bg_entries.push_back(e);
- }
-
- if (bvh_enabled_) {
- WGPUBindGroupEntry e = {};
- e.binding = 2;
- e.buffer = bvh_storage_buffer_;
- e.size = sizeof(BVHNode) * kMaxObjects * 2;
- bg_entries.push_back(e);
- }
-
- {
- WGPUBindGroupEntry e = {};
- e.binding = 3;
- e.textureView = noise_texture_view_;
- bg_entries.push_back(e);
- }
-
- {
- WGPUBindGroupEntry e = {};
- e.binding = 4;
- e.sampler = default_sampler_;
- bg_entries.push_back(e);
- }
-
- {
- WGPUBindGroupEntry e = {};
- e.binding = 5;
- e.textureView = sky_texture_view_ ? sky_texture_view_ : noise_texture_view_;
- bg_entries.push_back(e);
- }
-
- // Select the correct pipeline and bind group layout
- WGPURenderPipeline current_pipeline =
- bvh_enabled_ ? pipeline_ : pipeline_no_bvh_;
- WGPUBindGroupLayout current_layout =
- wgpuRenderPipelineGetBindGroupLayout(current_pipeline, 0);
-
- WGPUBindGroupDescriptor bg_desc = {};
- bg_desc.layout = current_layout;
- bg_desc.entryCount = (uint32_t)bg_entries.size();
- bg_desc.entries = bg_entries.data();
-
- bind_group_ = wgpuDeviceCreateBindGroup(device_, &bg_desc);
-
- wgpuBindGroupLayoutRelease(current_layout);
-
- wgpuRenderPassEncoderSetPipeline(pass, current_pipeline);
-
- wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
-
- uint32_t instance_count =
- (uint32_t)std::min((size_t)kMaxObjects, scene.objects.size());
-
- if (instance_count > 0) {
- wgpuRenderPassEncoderSetPipeline(pass, current_pipeline);
- wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
- wgpuRenderPassEncoderDraw(pass, 36, instance_count, 0, 0);
-
- // Mesh pass
- if (mesh_pipeline_) {
- wgpuRenderPassEncoderSetPipeline(pass, mesh_pipeline_);
- // Bind group is the same layout
- wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
-
- for (uint32_t i = 0; i < instance_count; ++i) {
- const auto& obj = scene.objects[i];
- if (obj.type == ObjectType::MESH) {
- const MeshGpuData* mesh = temp_mesh_override_
- ? temp_mesh_override_
- : get_or_create_mesh(obj.mesh_asset_id);
- if (mesh) {
- wgpuRenderPassEncoderSetVertexBuffer(pass, 0, mesh->vertex_buffer,
- 0, WGPU_WHOLE_SIZE);
- wgpuRenderPassEncoderSetIndexBuffer(pass, mesh->index_buffer,
- WGPUIndexFormat_Uint32, 0,
- WGPU_WHOLE_SIZE);
- wgpuRenderPassEncoderDrawIndexed(pass, mesh->num_indices, 1, 0, 0,
- i);
- }
- }
- }
- }
- }
-
-#if !defined(STRIP_ALL)
- if (s_debug_enabled_) {
- for (const auto& obj : scene.objects) {
- vec3 extent = obj.local_extent;
- if (obj.type == ObjectType::TORUS) {
- extent = vec3(1.5f, 0.5f, 1.5f);
- } else if (obj.type == ObjectType::MESH) {
- MeshAsset mesh = GetMeshAsset(obj.mesh_asset_id);
- if (mesh.num_indices > 0) {
- visual_debug_.add_mesh_wireframe(
- obj.get_model_matrix(), mesh.num_vertices, mesh.vertices,
- mesh.num_indices, mesh.indices,
- vec3(0.0f, 1.0f, 1.0f)); // Cyan wireframe
- }
- } else {
- extent = vec3(1.0f, 1.0f, 1.0f);
- }
-
- if (obj.type != ObjectType::MESH) {
- visual_debug_.add_box(obj.get_model_matrix(), extent,
- vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes
- }
- }
-
- // Calculate ViewProj matrix for the debug renderer
- mat4 view_proj = camera.get_projection_matrix() * camera.get_view_matrix();
- visual_debug_.render(pass, view_proj);
- }
-#endif
-}
-
void Renderer3D::render(const Scene& scene, const Camera& camera, float time,
-
WGPUTextureView target_view,
-
WGPUTextureView depth_view_opt) {
WGPUTextureView depth_view = depth_view_opt ? depth_view_opt : depth_view_;
if (!depth_view)
-
return;
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, nullptr);
@@ -444,10 +214,7 @@ void Renderer3D::render(const Scene& scene, const Camera& camera, float time,
wgpuRenderPassEncoderRelease(obj_pass);
WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, nullptr);
-
wgpuQueueSubmit(queue_, 1, &commands);
-
wgpuCommandBufferRelease(commands);
-
wgpuCommandEncoderRelease(encoder);
-} \ No newline at end of file
+}
diff --git a/src/3d/renderer_draw.cc b/src/3d/renderer_draw.cc
new file mode 100644
index 0000000..b50229f
--- /dev/null
+++ b/src/3d/renderer_draw.cc
@@ -0,0 +1,215 @@
+// This file is part of the 64k demo project.
+// It implements the drawing logic for Renderer3D.
+
+#include "3d/renderer.h"
+#include "util/asset_manager_utils.h"
+#include <algorithm>
+#include <vector>
+
+void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera,
+ float time) {
+ GlobalUniforms globals;
+ globals.view_proj = camera.get_projection_matrix() * camera.get_view_matrix();
+ globals.inv_view_proj = globals.view_proj.inverse();
+ globals.camera_pos_time =
+ vec4(camera.position.x, camera.position.y, camera.position.z, time);
+ globals.params =
+ vec4((float)std::min((size_t)kMaxObjects, scene.objects.size()), 0.0f,
+ 0.0f, 0.0f);
+ globals.resolution = vec2((float)width_, (float)height_);
+ globals.padding = vec2(0.0f, 0.0f);
+
+ wgpuQueueWriteBuffer(queue_, global_uniform_buffer_, 0, &globals,
+ sizeof(GlobalUniforms));
+
+ std::vector<ObjectData> obj_data;
+ for (const auto& obj : scene.objects) {
+ ObjectData data;
+ data.model = obj.get_model_matrix();
+
+ // Calculate Inverse for point transformation
+ data.inv_model = data.model.inverse();
+
+ data.color = obj.color;
+ float type_id = 0.0f;
+ switch (obj.type) {
+ case ObjectType::SPHERE:
+ type_id = 1.0f;
+ break;
+ case ObjectType::BOX:
+ type_id = 2.0f;
+ break;
+ case ObjectType::CUBE:
+ type_id = 2.0f;
+ break; // CUBE is same as BOX for shader
+ case ObjectType::TORUS:
+ type_id = 3.0f;
+ break;
+ case ObjectType::PLANE:
+ type_id = 4.0f;
+ break;
+ case ObjectType::MESH:
+ type_id = 5.0f;
+ break;
+ default:
+ type_id = 0.0f;
+ break;
+ }
+ data.params = vec4(type_id, obj.local_extent.x, obj.local_extent.y,
+ obj.local_extent.z);
+ obj_data.push_back(data);
+ if (obj_data.size() >= kMaxObjects)
+ break;
+ }
+ if (!obj_data.empty()) {
+ wgpuQueueWriteBuffer(queue_, object_storage_buffer_, 0, obj_data.data(),
+ obj_data.size() * sizeof(ObjectData));
+ }
+
+ // Build and upload BVH (always uploaded, used by BVH pipeline)
+ BVHBuilder::build(cpu_bvh_, scene.objects);
+ if (!cpu_bvh_.nodes.empty()) {
+ wgpuQueueWriteBuffer(queue_, bvh_storage_buffer_, 0, cpu_bvh_.nodes.data(),
+ cpu_bvh_.nodes.size() * sizeof(BVHNode));
+ }
+}
+
+void Renderer3D::draw(WGPURenderPassEncoder pass, const Scene& scene,
+ const Camera& camera, float time) {
+ update_uniforms(scene, camera, time);
+
+ // Lazy Bind Group creation
+
+ if (bind_group_)
+ wgpuBindGroupRelease(bind_group_);
+
+ std::vector<WGPUBindGroupEntry> bg_entries;
+
+ {
+ WGPUBindGroupEntry e = {};
+ e.binding = 0;
+ e.buffer = global_uniform_buffer_;
+ e.size = sizeof(GlobalUniforms);
+ bg_entries.push_back(e);
+ }
+
+ {
+ WGPUBindGroupEntry e = {};
+ e.binding = 1;
+ e.buffer = object_storage_buffer_;
+ e.size = sizeof(ObjectData) * kMaxObjects;
+ bg_entries.push_back(e);
+ }
+
+ if (bvh_enabled_) {
+ WGPUBindGroupEntry e = {};
+ e.binding = 2;
+ e.buffer = bvh_storage_buffer_;
+ e.size = sizeof(BVHNode) * kMaxObjects * 2;
+ bg_entries.push_back(e);
+ }
+
+ {
+ WGPUBindGroupEntry e = {};
+ e.binding = 3;
+ e.textureView = noise_texture_view_;
+ bg_entries.push_back(e);
+ }
+
+ {
+ WGPUBindGroupEntry e = {};
+ e.binding = 4;
+ e.sampler = default_sampler_;
+ bg_entries.push_back(e);
+ }
+
+ {
+ WGPUBindGroupEntry e = {};
+ e.binding = 5;
+ e.textureView = sky_texture_view_ ? sky_texture_view_ : noise_texture_view_;
+ bg_entries.push_back(e);
+ }
+
+ // Select the correct pipeline and bind group layout
+ WGPURenderPipeline current_pipeline =
+ bvh_enabled_ ? pipeline_ : pipeline_no_bvh_;
+ WGPUBindGroupLayout current_layout =
+ wgpuRenderPipelineGetBindGroupLayout(current_pipeline, 0);
+
+ WGPUBindGroupDescriptor bg_desc = {};
+ bg_desc.layout = current_layout;
+ bg_desc.entryCount = (uint32_t)bg_entries.size();
+ bg_desc.entries = bg_entries.data();
+
+ bind_group_ = wgpuDeviceCreateBindGroup(device_, &bg_desc);
+
+ wgpuBindGroupLayoutRelease(current_layout);
+
+ wgpuRenderPassEncoderSetPipeline(pass, current_pipeline);
+
+ wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
+
+ uint32_t instance_count =
+ (uint32_t)std::min((size_t)kMaxObjects, scene.objects.size());
+
+ if (instance_count > 0) {
+ wgpuRenderPassEncoderSetPipeline(pass, current_pipeline);
+ wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
+ wgpuRenderPassEncoderDraw(pass, 36, instance_count, 0, 0);
+
+ // Mesh pass
+ if (mesh_pipeline_) {
+ wgpuRenderPassEncoderSetPipeline(pass, mesh_pipeline_);
+ // Bind group is the same layout
+ wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
+
+ for (uint32_t i = 0; i < instance_count; ++i) {
+ const auto& obj = scene.objects[i];
+ if (obj.type == ObjectType::MESH) {
+ const MeshGpuData* mesh = temp_mesh_override_
+ ? temp_mesh_override_
+ : get_or_create_mesh(obj.mesh_asset_id);
+ if (mesh) {
+ wgpuRenderPassEncoderSetVertexBuffer(pass, 0, mesh->vertex_buffer,
+ 0, WGPU_WHOLE_SIZE);
+ wgpuRenderPassEncoderSetIndexBuffer(pass, mesh->index_buffer,
+ WGPUIndexFormat_Uint32, 0,
+ WGPU_WHOLE_SIZE);
+ wgpuRenderPassEncoderDrawIndexed(pass, mesh->num_indices, 1, 0, 0,
+ i);
+ }
+ }
+ }
+ }
+ }
+
+#if !defined(STRIP_ALL)
+ if (s_debug_enabled_) {
+ for (const auto& obj : scene.objects) {
+ vec3 extent = obj.local_extent;
+ if (obj.type == ObjectType::TORUS) {
+ extent = vec3(1.5f, 0.5f, 1.5f);
+ } else if (obj.type == ObjectType::MESH) {
+ MeshAsset mesh = GetMeshAsset(obj.mesh_asset_id);
+ if (mesh.num_indices > 0) {
+ visual_debug_.add_mesh_wireframe(
+ obj.get_model_matrix(), mesh.num_vertices, mesh.vertices,
+ mesh.num_indices, mesh.indices,
+ vec3(0.0f, 1.0f, 1.0f)); // Cyan wireframe
+ }
+ } else {
+ extent = vec3(1.0f, 1.0f, 1.0f);
+ }
+
+ if (obj.type != ObjectType::MESH) {
+ visual_debug_.add_box(obj.get_model_matrix(), extent,
+ vec3(1.0f, 1.0f, 0.0f)); // Yellow boxes
+ }
+ }
+
+ // Calculate ViewProj matrix for the debug renderer
+ mat4 view_proj = camera.get_projection_matrix() * camera.get_view_matrix();
+ visual_debug_.render(pass, view_proj);
+ }
+#endif
+}
diff --git a/src/3d/renderer_mesh.cc b/src/3d/renderer_mesh.cc
deleted file mode 100644
index 7ef2b42..0000000
--- a/src/3d/renderer_mesh.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// This file is part of the 64k demo project.
-// It implements mesh-related logic for Renderer3D.
-
-#include "3d/renderer.h"
-#include "generated/assets.h"
-#include "gpu/effects/shader_composer.h"
-#include "util/asset_manager_utils.h"
-#include <cstring>
-#include <vector>
-
-void Renderer3D::create_mesh_pipeline() {
- std::vector<WGPUBindGroupLayoutEntry> entries;
-
- // Binding 0: Global Uniforms
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 0;
- e.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
- e.buffer.type = WGPUBufferBindingType_Uniform;
- e.buffer.minBindingSize = sizeof(GlobalUniforms);
- entries.push_back(e);
- }
-
- // Binding 1: Object Data
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 1;
- e.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
- e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage;
- e.buffer.minBindingSize = sizeof(ObjectData) * kMaxObjects;
- entries.push_back(e);
- }
-
- // Binding 2: BVH Nodes (Optional)
- if (bvh_enabled_) {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 2;
- e.visibility = WGPUShaderStage_Fragment;
- e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage;
- e.buffer.minBindingSize = sizeof(BVHNode) * kMaxObjects * 2;
- entries.push_back(e);
- }
-
- // Binding 3: Noise Texture
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 3;
- e.visibility = WGPUShaderStage_Fragment;
- e.texture.sampleType = WGPUTextureSampleType_Float;
- e.texture.viewDimension = WGPUTextureViewDimension_2D;
- entries.push_back(e);
- }
-
- // Binding 4: Default Sampler
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 4;
- e.visibility = WGPUShaderStage_Fragment;
- e.sampler.type = WGPUSamplerBindingType_Filtering;
- entries.push_back(e);
- }
-
- // Binding 5: Sky Texture
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 5;
- e.visibility = WGPUShaderStage_Fragment;
- e.texture.sampleType = WGPUTextureSampleType_Float;
- e.texture.viewDimension = WGPUTextureViewDimension_2D;
- entries.push_back(e);
- }
-
- WGPUBindGroupLayoutDescriptor bgl_desc = {};
- bgl_desc.entryCount = (uint32_t)entries.size();
- bgl_desc.entries = entries.data();
- WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
-
- WGPUPipelineLayoutDescriptor pl_desc = {};
- pl_desc.bindGroupLayoutCount = 1;
- pl_desc.bindGroupLayouts = &bgl;
- WGPUPipelineLayout pipeline_layout =
- wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
-
- const char* shader_code_asset =
- (const char*)GetAsset(AssetId::ASSET_SHADER_MESH);
-
- ShaderComposer::CompositionMap composition_map;
- if (bvh_enabled_) {
- composition_map["render/scene_query_mode"] = "render/scene_query_bvh";
- } else {
- composition_map["render/scene_query_mode"] = "render/scene_query_linear";
- }
- std::string shader_source =
- ShaderComposer::Get().Compose({}, shader_code_asset, composition_map);
-
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
- wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
- wgsl_desc.code = shader_source.c_str();
- WGPUShaderModuleDescriptor shader_desc = {};
- shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain;
-#else
- WGPUShaderSourceWGSL wgsl_desc = {};
- wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
- wgsl_desc.code = str_view(shader_source.c_str());
- WGPUShaderModuleDescriptor shader_desc = {};
- shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain;
-#endif
- WGPUShaderModule shader_module =
- wgpuDeviceCreateShaderModule(device_, &shader_desc);
-
- WGPUVertexAttribute vert_attrs[3] = {};
- // pos
- vert_attrs[0].format = WGPUVertexFormat_Float32x3;
- vert_attrs[0].offset = offsetof(MeshVertex, p);
- vert_attrs[0].shaderLocation = 0;
- // norm
- vert_attrs[1].format = WGPUVertexFormat_Float32x3;
- vert_attrs[1].offset = offsetof(MeshVertex, n);
- vert_attrs[1].shaderLocation = 1;
- // uv
- vert_attrs[2].format = WGPUVertexFormat_Float32x2;
- vert_attrs[2].offset = offsetof(MeshVertex, u);
- vert_attrs[2].shaderLocation = 2;
-
- WGPUVertexBufferLayout vert_layout = {};
- vert_layout.arrayStride = sizeof(MeshVertex);
- vert_layout.stepMode = WGPUVertexStepMode_Vertex;
- vert_layout.attributeCount = 3;
- vert_layout.attributes = vert_attrs;
-
- WGPURenderPipelineDescriptor desc = {};
- desc.layout = pipeline_layout;
- desc.vertex.module = shader_module;
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- desc.vertex.entryPoint = "vs_main";
-#else
- desc.vertex.entryPoint = {"vs_main", 7};
-#endif
- desc.vertex.bufferCount = 1;
- desc.vertex.buffers = &vert_layout;
-
- WGPUColorTargetState color_target = {};
- color_target.format = format_;
- color_target.writeMask = WGPUColorWriteMask_All;
- WGPUFragmentState fragment = {};
- fragment.module = shader_module;
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- fragment.entryPoint = "fs_main";
-#else
- fragment.entryPoint = {"fs_main", 7};
-#endif
- fragment.targetCount = 1;
- fragment.targets = &color_target;
- desc.fragment = &fragment;
-
- desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
- desc.primitive.cullMode = WGPUCullMode_Back;
- desc.primitive.frontFace = WGPUFrontFace_CCW;
-
- WGPUDepthStencilState depth_stencil = {};
- depth_stencil.format = WGPUTextureFormat_Depth24Plus;
- depth_stencil.depthWriteEnabled = WGPUOptionalBool_True;
- depth_stencil.depthCompare = WGPUCompareFunction_Less;
- desc.depthStencil = &depth_stencil;
-
- desc.multisample.count = 1;
- desc.multisample.mask = 0xFFFFFFFF;
-
- mesh_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &desc);
- wgpuBindGroupLayoutRelease(bgl);
- wgpuPipelineLayoutRelease(pipeline_layout);
- wgpuShaderModuleRelease(shader_module);
-}
-
-const Renderer3D::MeshGpuData*
-Renderer3D::get_or_create_mesh(AssetId asset_id) {
- auto it = mesh_cache_.find(asset_id);
- if (it != mesh_cache_.end()) {
- return &it->second;
- }
-
- MeshAsset asset = GetMeshAsset(asset_id);
- if (!asset.vertices || asset.num_vertices == 0) {
- return nullptr;
- }
-
- MeshGpuData data;
- data.num_indices = asset.num_indices;
-
- data.vertex_buffer =
- gpu_create_buffer(device_, asset.num_vertices * sizeof(MeshVertex),
- WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst,
- asset.vertices)
- .buffer;
- data.index_buffer =
- gpu_create_buffer(device_, asset.num_indices * sizeof(uint32_t),
- WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst,
- asset.indices)
- .buffer;
-
- mesh_cache_[asset_id] = data;
- return &mesh_cache_[asset_id];
-}
diff --git a/src/3d/renderer_pipelines.cc b/src/3d/renderer_pipelines.cc
new file mode 100644
index 0000000..d0f1a7b
--- /dev/null
+++ b/src/3d/renderer_pipelines.cc
@@ -0,0 +1,255 @@
+// This file is part of the 64k demo project.
+// It implements the pipeline creation logic for Renderer3D.
+
+#include "3d/renderer.h"
+#include "generated/assets.h"
+#include "gpu/effects/shader_composer.h"
+#include "util/asset_manager.h"
+#include "util/asset_manager_utils.h"
+#include <vector>
+
+void Renderer3D::create_pipeline() {
+ pipeline_ = create_pipeline_impl(true);
+ pipeline_no_bvh_ = create_pipeline_impl(false);
+ create_mesh_pipeline();
+}
+
+WGPURenderPipeline Renderer3D::create_pipeline_impl(bool use_bvh) {
+ // Main SDF shader
+ size_t size;
+ const char* shader_code = reinterpret_cast<const char*>(
+ GetAsset(AssetId::ASSET_SHADER_RENDERER_3D, &size));
+
+ // Compose the final shader by substituting the scene query implementation
+ ShaderComposer::CompositionMap composition_map;
+ if (use_bvh) {
+ composition_map["render/scene_query_mode"] = "render/scene_query_bvh";
+ } else {
+ composition_map["render/scene_query_mode"] = "render/scene_query_linear";
+ }
+ std::string composed_shader = ShaderComposer::Get().Compose(
+ {}, std::string(shader_code, size), composition_map);
+
+ WGPUShaderSourceWGSL wgsl_src = {};
+ wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
+ wgsl_src.code = str_view(composed_shader.c_str());
+
+ WGPUShaderModuleDescriptor shader_desc = {};
+ shader_desc.nextInChain = &wgsl_src.chain;
+ WGPUShaderModule shader_module =
+ wgpuDeviceCreateShaderModule(device_, &shader_desc);
+
+ // BIND GROUP LAYOUT
+ std::vector<WGPUBindGroupLayoutEntry> bgl_entries;
+ bgl_entries.push_back({.binding = 0, // B0: uniforms
+ .visibility = WGPUShaderStage_Vertex |
+ WGPUShaderStage_Fragment,
+ .buffer = {.type = WGPUBufferBindingType_Uniform}});
+ bgl_entries.push_back(
+ {.binding = 1, // B1: object storage
+ .visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment,
+ .buffer = {.type = WGPUBufferBindingType_ReadOnlyStorage}});
+ if (use_bvh) {
+ bgl_entries.push_back(
+ {.binding = 2, // B2: bvh storage
+ .visibility = WGPUShaderStage_Fragment,
+ .buffer = {.type = WGPUBufferBindingType_ReadOnlyStorage}});
+ }
+ bgl_entries.push_back({.binding = 3, // B3: noise texture
+ .visibility = WGPUShaderStage_Fragment,
+ .texture = {.sampleType = WGPUTextureSampleType_Float,
+ .viewDimension =
+ WGPUTextureViewDimension_2D}});
+ bgl_entries.push_back({.binding = 4, // B4: default sampler
+ .visibility = WGPUShaderStage_Fragment,
+ .sampler = {.type = WGPUSamplerBindingType_Filtering}});
+ bgl_entries.push_back({.binding = 5, // B5: sky texture
+ .visibility = WGPUShaderStage_Fragment,
+ .texture = {.sampleType = WGPUTextureSampleType_Float,
+ .viewDimension =
+ WGPUTextureViewDimension_2D}});
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = bgl_entries.size();
+ bgl_desc.entries = bgl_entries.data();
+ WGPUBindGroupLayout bind_group_layout =
+ wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
+
+ // PIPELINE LAYOUT
+ WGPUPipelineLayoutDescriptor pl_desc = {};
+ pl_desc.bindGroupLayoutCount = 1;
+ pl_desc.bindGroupLayouts = &bind_group_layout;
+ WGPUPipelineLayout pipeline_layout =
+ wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
+
+ // PIPELINE
+ WGPUDepthStencilState depth_stencil = {};
+ depth_stencil.format = WGPUTextureFormat_Depth24Plus;
+ depth_stencil.depthWriteEnabled = WGPUOptionalBool_True;
+ depth_stencil.depthCompare = WGPUCompareFunction_Less;
+
+ WGPUColorTargetState color_target = {};
+ color_target.format = format_;
+ color_target.writeMask = WGPUColorWriteMask_All;
+
+ WGPUFragmentState fragment_state = {};
+ fragment_state.module = shader_module;
+ fragment_state.entryPoint = str_view("fs_main");
+ fragment_state.targetCount = 1;
+ fragment_state.targets = &color_target;
+
+ WGPURenderPipelineDescriptor pipeline_desc = {};
+ pipeline_desc.layout = pipeline_layout;
+ pipeline_desc.vertex.module = shader_module;
+ pipeline_desc.vertex.entryPoint = str_view("vs_main");
+ pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ pipeline_desc.multisample.count = 1;
+ pipeline_desc.fragment = &fragment_state;
+ pipeline_desc.depthStencil = &depth_stencil;
+
+ WGPURenderPipeline pipeline =
+ wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc);
+
+ wgpuShaderModuleRelease(shader_module);
+ wgpuPipelineLayoutRelease(pipeline_layout);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+
+ return pipeline;
+}
+
+void Renderer3D::create_mesh_pipeline() {
+ size_t size;
+ const char* shader_code = reinterpret_cast<const char*>(
+ GetAsset(AssetId::ASSET_SHADER_MESH, &size));
+
+ ShaderComposer::CompositionMap composition_map;
+ if (bvh_enabled_) {
+ composition_map["render/scene_query_mode"] = "render/scene_query_bvh";
+ } else {
+ composition_map["render/scene_query_mode"] = "render/scene_query_linear";
+ }
+ std::string composed_shader = ShaderComposer::Get().Compose(
+ {}, std::string(shader_code, size), composition_map);
+
+ WGPUShaderSourceWGSL wgsl_src = {};
+ wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
+ wgsl_src.code = str_view(composed_shader.c_str());
+ WGPUShaderModuleDescriptor shader_desc = {};
+ shader_desc.nextInChain = &wgsl_src.chain;
+ WGPUShaderModule shader_module =
+ wgpuDeviceCreateShaderModule(device_, &shader_desc);
+
+ WGPUBindGroupLayout bgl =
+ wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0);
+ WGPUPipelineLayoutDescriptor pl_desc = {};
+ pl_desc.bindGroupLayoutCount = 1;
+ pl_desc.bindGroupLayouts = &bgl;
+ WGPUPipelineLayout pipeline_layout =
+ wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
+ wgpuBindGroupLayoutRelease(bgl);
+
+ WGPUDepthStencilState depth_stencil = {};
+ depth_stencil.format = WGPUTextureFormat_Depth24Plus;
+ depth_stencil.depthWriteEnabled = WGPUOptionalBool_True;
+ depth_stencil.depthCompare = WGPUCompareFunction_Less;
+
+ WGPUColorTargetState color_target = {};
+ color_target.format = format_;
+ color_target.writeMask = WGPUColorWriteMask_All;
+ WGPUFragmentState fragment_state = {};
+ fragment_state.module = shader_module;
+ fragment_state.entryPoint = str_view("fs_main");
+ fragment_state.targetCount = 1;
+ fragment_state.targets = &color_target;
+
+ WGPUVertexAttribute vert_attrs[3] = {};
+ vert_attrs[0] = {.format = WGPUVertexFormat_Float32x3, .offset = offsetof(MeshVertex, p), .shaderLocation = 0};
+ vert_attrs[1] = {.format = WGPUVertexFormat_Float32x3, .offset = offsetof(MeshVertex, n), .shaderLocation = 1};
+ vert_attrs[2] = {.format = WGPUVertexFormat_Float32x2, .offset = offsetof(MeshVertex, u), .shaderLocation = 2};
+
+ WGPUVertexBufferLayout vert_buffer_layout = {};
+ vert_buffer_layout.arrayStride = sizeof(MeshVertex);
+ vert_buffer_layout.stepMode = WGPUVertexStepMode_Vertex;
+ vert_buffer_layout.attributeCount = 3;
+ vert_buffer_layout.attributes = vert_attrs;
+
+ WGPURenderPipelineDescriptor pipeline_desc = {};
+ pipeline_desc.layout = pipeline_layout;
+ pipeline_desc.vertex.module = shader_module;
+ pipeline_desc.vertex.entryPoint = str_view("vs_main");
+ pipeline_desc.vertex.bufferCount = 1;
+ pipeline_desc.vertex.buffers = &vert_buffer_layout;
+ pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ pipeline_desc.primitive.cullMode = WGPUCullMode_Back;
+ pipeline_desc.multisample.count = 1;
+ pipeline_desc.fragment = &fragment_state;
+ pipeline_desc.depthStencil = &depth_stencil;
+
+ mesh_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc);
+
+ wgpuShaderModuleRelease(shader_module);
+ wgpuPipelineLayoutRelease(pipeline_layout);
+}
+
+void Renderer3D::create_skybox_pipeline() {
+ size_t size;
+ const char* shader_code = reinterpret_cast<const char*>(
+ GetAsset(AssetId::ASSET_SHADER_SKYBOX, &size));
+
+ std::string composed_shader = ShaderComposer::Get().Compose(
+ {}, std::string(shader_code, size));
+
+ WGPUShaderSourceWGSL wgsl_src = {};
+ wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
+ wgsl_src.code = str_view(composed_shader.c_str());
+ WGPUShaderModuleDescriptor shader_desc = {};
+ shader_desc.nextInChain = &wgsl_src.chain;
+ WGPUShaderModule shader_module =
+ wgpuDeviceCreateShaderModule(device_, &shader_desc);
+
+ WGPUBindGroupLayoutEntry bgl_entries[3] = {};
+ bgl_entries[0] = {.binding=0, .visibility=WGPUShaderStage_Fragment, .texture={.sampleType=WGPUTextureSampleType_Float, .viewDimension=WGPUTextureViewDimension_2D}};
+ bgl_entries[1] = {.binding=1, .visibility=WGPUShaderStage_Fragment, .sampler={.type=WGPUSamplerBindingType_Filtering}};
+ bgl_entries[2] = {.binding=2, .visibility=WGPUShaderStage_Fragment, .buffer={.type=WGPUBufferBindingType_Uniform}};
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = 3;
+ bgl_desc.entries = bgl_entries;
+ WGPUBindGroupLayout bind_group_layout =
+ wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
+
+ WGPUPipelineLayoutDescriptor pl_desc = {};
+ pl_desc.bindGroupLayoutCount = 1;
+ pl_desc.bindGroupLayouts = &bind_group_layout;
+ WGPUPipelineLayout pipeline_layout =
+ wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
+
+ WGPUDepthStencilState depth_stencil = {};
+ depth_stencil.format = WGPUTextureFormat_Depth24Plus;
+ depth_stencil.depthWriteEnabled = WGPUOptionalBool_False;
+ depth_stencil.depthCompare = WGPUCompareFunction_Always;
+
+ WGPUColorTargetState color_target = {};
+ color_target.format = format_;
+ color_target.writeMask = WGPUColorWriteMask_All;
+ WGPUFragmentState fragment_state = {};
+ fragment_state.module = shader_module;
+ fragment_state.entryPoint = str_view("fs_main");
+ fragment_state.targetCount = 1;
+ fragment_state.targets = &color_target;
+
+ WGPURenderPipelineDescriptor pipeline_desc = {};
+ pipeline_desc.layout = pipeline_layout;
+ pipeline_desc.vertex.module = shader_module;
+ pipeline_desc.vertex.entryPoint = str_view("vs_main");
+ pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ pipeline_desc.multisample.count = 1;
+ pipeline_desc.fragment = &fragment_state;
+ pipeline_desc.depthStencil = &depth_stencil;
+
+ skybox_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc);
+
+ wgpuShaderModuleRelease(shader_module);
+ wgpuPipelineLayoutRelease(pipeline_layout);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+} \ No newline at end of file
diff --git a/src/3d/renderer_resources.cc b/src/3d/renderer_resources.cc
new file mode 100644
index 0000000..2b001aa
--- /dev/null
+++ b/src/3d/renderer_resources.cc
@@ -0,0 +1,54 @@
+// This file is part of the 64k demo project.
+// It implements the resource management logic for Renderer3D.
+
+#include "3d/renderer.h"
+#include "util/asset_manager_utils.h"
+
+void Renderer3D::create_default_resources() {
+ global_uniform_buffer_ =
+ gpu_create_buffer(device_, sizeof(GlobalUniforms),
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst,
+ nullptr)
+ .buffer;
+ object_storage_buffer_ =
+ gpu_create_buffer(device_, sizeof(ObjectData) * kMaxObjects,
+ WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst,
+ nullptr)
+ .buffer;
+ bvh_storage_buffer_ =
+ gpu_create_buffer(
+ device_,
+ sizeof(BVHNode) * kMaxObjects * 2, // Capacity for a full tree
+ WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr)
+ .buffer;
+}
+
+const Renderer3D::MeshGpuData*
+Renderer3D::get_or_create_mesh(AssetId asset_id) {
+ auto it = mesh_cache_.find(asset_id);
+ if (it != mesh_cache_.end()) {
+ return &it->second;
+ }
+
+ MeshAsset asset = GetMeshAsset(asset_id);
+ if (!asset.vertices || asset.num_vertices == 0) {
+ return nullptr;
+ }
+
+ MeshGpuData data;
+ data.num_indices = asset.num_indices;
+
+ data.vertex_buffer =
+ gpu_create_buffer(device_, asset.num_vertices * sizeof(MeshVertex),
+ WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst,
+ asset.vertices)
+ .buffer;
+ data.index_buffer =
+ gpu_create_buffer(device_, asset.num_indices * sizeof(uint32_t),
+ WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst,
+ asset.indices)
+ .buffer;
+
+ mesh_cache_[asset_id] = data;
+ return &mesh_cache_[asset_id];
+}
diff --git a/src/3d/renderer_sdf.cc b/src/3d/renderer_sdf.cc
deleted file mode 100644
index d94df11..0000000
--- a/src/3d/renderer_sdf.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// This file is part of the 64k demo project.
-// It implements SDF-related pipeline logic for Renderer3D.
-
-#include "3d/renderer.h"
-#include "generated/assets.h"
-#include "gpu/effects/shader_composer.h"
-#include "util/asset_manager.h"
-#include <vector>
-
-void Renderer3D::create_pipeline() {
- pipeline_ = create_pipeline_impl(true); // BVH enabled
- pipeline_no_bvh_ = create_pipeline_impl(false); // BVH disabled
- create_mesh_pipeline();
-}
-
-WGPURenderPipeline Renderer3D::create_pipeline_impl(bool use_bvh) {
- std::vector<WGPUBindGroupLayoutEntry> entries;
-
- // Binding 0: Global Uniforms
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 0;
- e.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
- e.buffer.type = WGPUBufferBindingType_Uniform;
- e.buffer.minBindingSize = sizeof(GlobalUniforms);
- entries.push_back(e);
- }
-
- // Binding 1: Object Data
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 1;
- e.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
- e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage;
- e.buffer.minBindingSize = sizeof(ObjectData) * kMaxObjects;
- entries.push_back(e);
- }
-
- // Binding 2: BVH Nodes (only if BVH is used)
- if (use_bvh) {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 2;
- e.visibility = WGPUShaderStage_Fragment;
- e.buffer.type = WGPUBufferBindingType_ReadOnlyStorage;
- e.buffer.minBindingSize = sizeof(BVHNode) * kMaxObjects * 2;
- entries.push_back(e);
- }
-
- // Binding 3: Noise Texture
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 3;
- e.visibility = WGPUShaderStage_Fragment;
- e.texture.sampleType = WGPUTextureSampleType_Float;
- e.texture.viewDimension = WGPUTextureViewDimension_2D;
- entries.push_back(e);
- }
-
- // Binding 4: Default Sampler
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 4;
- e.visibility = WGPUShaderStage_Fragment;
- e.sampler.type = WGPUSamplerBindingType_Filtering;
- entries.push_back(e);
- }
-
- // Binding 5: Sky Texture
- {
- WGPUBindGroupLayoutEntry e = {};
- e.binding = 5;
- e.visibility = WGPUShaderStage_Fragment;
- e.texture.sampleType = WGPUTextureSampleType_Float;
- e.texture.viewDimension = WGPUTextureViewDimension_2D;
- entries.push_back(e);
- }
-
- WGPUBindGroupLayoutDescriptor bgl_desc = {};
- bgl_desc.entryCount = (uint32_t)entries.size();
- bgl_desc.entries = entries.data();
- WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
-
- WGPUPipelineLayoutDescriptor pl_desc = {};
- pl_desc.bindGroupLayoutCount = 1;
- pl_desc.bindGroupLayouts = &bgl;
- WGPUPipelineLayout pipeline_layout =
- wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
-
- const char* asset_data =
- (const char*)GetAsset(AssetId::ASSET_SHADER_RENDERER_3D);
- std::string main_code = asset_data;
-
- // Use ShaderComposer to dynamically include the correct scene_query snippet
- ShaderComposer::CompositionMap composition_map;
- if (use_bvh) {
- composition_map["render/scene_query_mode"] = "render/scene_query_bvh";
- } else {
- composition_map["render/scene_query_mode"] = "render/scene_query_linear";
- }
- std::string shader_source =
- ShaderComposer::Get().Compose({}, main_code, composition_map);
-
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
- wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
- wgsl_desc.code = shader_source.c_str();
- WGPUShaderModuleDescriptor shader_desc = {};
- shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain;
-#else
- WGPUShaderSourceWGSL wgsl_desc = {};
- wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
- wgsl_desc.code = str_view(shader_source.c_str());
- WGPUShaderModuleDescriptor shader_desc = {};
- shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain;
-#endif
- WGPUShaderModule shader_module =
- wgpuDeviceCreateShaderModule(device_, &shader_desc);
-
- WGPUDepthStencilState depth_stencil = {};
- depth_stencil.format = WGPUTextureFormat_Depth24Plus;
- depth_stencil.depthWriteEnabled = WGPUOptionalBool_True;
- depth_stencil.depthCompare = WGPUCompareFunction_Less;
-
- WGPURenderPipelineDescriptor desc = {};
- desc.layout = pipeline_layout;
- desc.vertex.module = shader_module;
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- desc.vertex.entryPoint = "vs_main";
-#else
- desc.vertex.entryPoint = {"vs_main", 7};
-#endif
- WGPUColorTargetState color_target = {};
- color_target.format = format_;
- color_target.writeMask = WGPUColorWriteMask_All;
- WGPUFragmentState fragment = {};
- fragment.module = shader_module;
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- fragment.entryPoint = "fs_main";
-#else
- fragment.entryPoint = {"fs_main", 7};
-#endif
- fragment.targetCount = 1;
- fragment.targets = &color_target;
- desc.fragment = &fragment;
- desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
- desc.primitive.cullMode = WGPUCullMode_Back;
- desc.primitive.frontFace = WGPUFrontFace_CCW;
- desc.depthStencil = &depth_stencil;
- desc.multisample.count = 1;
- desc.multisample.mask = 0xFFFFFFFF;
-
- WGPURenderPipeline pipeline = wgpuDeviceCreateRenderPipeline(device_, &desc);
- wgpuBindGroupLayoutRelease(bgl);
- wgpuPipelineLayoutRelease(pipeline_layout);
- wgpuShaderModuleRelease(shader_module);
-
- return pipeline;
-}
diff --git a/src/3d/renderer_skybox.cc b/src/3d/renderer_skybox.cc
deleted file mode 100644
index 203cc07..0000000
--- a/src/3d/renderer_skybox.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// This file is part of the 64k demo project.
-// It implements the skybox pipeline for Renderer3D.
-
-#include "3d/renderer.h"
-#include "generated/assets.h"
-#include "gpu/effects/shader_composer.h"
-#include "util/asset_manager.h"
-
-void Renderer3D::create_skybox_pipeline() {
- WGPUBindGroupLayoutEntry entries[3] = {};
- entries[0].binding = 0;
- entries[0].visibility = WGPUShaderStage_Fragment;
- entries[0].texture.sampleType = WGPUTextureSampleType_Float;
- entries[0].texture.viewDimension = WGPUTextureViewDimension_2D;
-
- entries[1].binding = 1;
- entries[1].visibility = WGPUShaderStage_Fragment;
- entries[1].sampler.type = WGPUSamplerBindingType_Filtering;
-
- entries[2].binding = 2;
- entries[2].visibility = WGPUShaderStage_Fragment;
- entries[2].buffer.type = WGPUBufferBindingType_Uniform;
- entries[2].buffer.minBindingSize = sizeof(GlobalUniforms);
-
- WGPUBindGroupLayoutDescriptor bgl_desc = {};
- bgl_desc.entryCount = 3;
- bgl_desc.entries = entries;
- WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
-
- WGPUPipelineLayoutDescriptor pl_desc = {};
- pl_desc.bindGroupLayoutCount = 1;
- pl_desc.bindGroupLayouts = &bgl;
- WGPUPipelineLayout pipeline_layout =
- wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
-
- const uint8_t* shader_code_asset =
- GetAsset(AssetId::ASSET_SHADER_SKYBOX, nullptr);
- std::string shader_source =
- ShaderComposer::Get().Compose({}, (const char*)shader_code_asset);
-
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
- wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
- wgsl_desc.code = shader_source.c_str();
- WGPUShaderModuleDescriptor shader_desc = {};
- shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain;
-#else
- WGPUShaderSourceWGSL wgsl_desc = {};
- wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
- wgsl_desc.code = str_view(shader_source.c_str());
- WGPUShaderModuleDescriptor shader_desc = {};
- shader_desc.nextInChain = (const WGPUChainedStruct*)&wgsl_desc.chain;
-#endif
- WGPUShaderModule shader_module =
- wgpuDeviceCreateShaderModule(device_, &shader_desc);
-
- WGPURenderPipelineDescriptor desc = {};
- desc.layout = pipeline_layout;
- desc.vertex.module = shader_module;
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- desc.vertex.entryPoint = "vs_main";
-#else
- desc.vertex.entryPoint = {"vs_main", 7};
-#endif
- WGPUColorTargetState color_target = {};
- color_target.format = format_;
- color_target.writeMask = WGPUColorWriteMask_All;
- WGPUFragmentState fragment = {};
- fragment.module = shader_module;
-#if defined(DEMO_CROSS_COMPILE_WIN32)
- fragment.entryPoint = "fs_main";
-#else
- fragment.entryPoint = {"fs_main", 7};
-#endif
- fragment.targetCount = 1;
- fragment.targets = &color_target;
- desc.fragment = &fragment;
- desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
- desc.primitive.cullMode = WGPUCullMode_Back;
- desc.primitive.frontFace = WGPUFrontFace_CCW;
- desc.multisample.count = 1;
- desc.multisample.mask = 0xFFFFFFFF;
-
- WGPUDepthStencilState depth_stencil = {};
- depth_stencil.format = WGPUTextureFormat_Depth24Plus;
- depth_stencil.depthWriteEnabled = WGPUOptionalBool_False;
- depth_stencil.depthCompare = WGPUCompareFunction_Always;
- desc.depthStencil = &depth_stencil;
-
- skybox_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &desc);
- wgpuBindGroupLayoutRelease(bgl);
- wgpuPipelineLayoutRelease(pipeline_layout);
- wgpuShaderModuleRelease(shader_module);
-}