From c3d3fe94f59a9929387ea1f47ad1b56792411ff9 Mon Sep 17 00:00:00 2001 From: skal Date: Fri, 6 Feb 2026 06:57:04 +0100 Subject: refactor(3d): Split Renderer3D into sub-functionalities Moved SDF, Mesh, and Skybox logic into separate files to adhere to the 500-line file limit rule. - src/3d/renderer_sdf.cc - src/3d/renderer_mesh.cc - src/3d/renderer_skybox.cc --- src/3d/renderer.cc | 444 ++--------------------------------------------------- 1 file changed, 13 insertions(+), 431 deletions(-) (limited to 'src/3d/renderer.cc') diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc index c3083fc..513b6f6 100644 --- a/src/3d/renderer.cc +++ b/src/3d/renderer.cc @@ -1,5 +1,5 @@ // This file is part of the 64k demo project. -// It implements the Renderer3D class. +// It implements the core Renderer3D class logic. #include "3d/renderer.h" #include "generated/assets.h" @@ -37,93 +37,6 @@ void Renderer3D::init(WGPUDevice device, WGPUQueue queue, #endif } -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); -} - void Renderer3D::shutdown() { #if !defined(STRIP_ALL) visual_debug_.shutdown(); @@ -137,6 +50,8 @@ void Renderer3D::shutdown() { wgpuRenderPipelineRelease(pipeline_no_bvh_); if (bind_group_) wgpuBindGroupRelease(bind_group_); + if (mesh_pipeline_) + wgpuRenderPipelineRelease(mesh_pipeline_); if (skybox_pipeline_) wgpuRenderPipelineRelease(skybox_pipeline_); if (skybox_bind_group_) @@ -151,6 +66,15 @@ void Renderer3D::shutdown() { wgpuTextureViewRelease(depth_view_); if (depth_texture_) wgpuTextureRelease(depth_texture_); + + // Clear mesh cache + for (auto& pair : mesh_cache_) { + if (pair.second.vertex_buffer) + wgpuBufferRelease(pair.second.vertex_buffer); + if (pair.second.index_buffer) + wgpuBufferRelease(pair.second.index_buffer); + } + mesh_cache_.clear(); } void Renderer3D::resize(int width, int height) { @@ -214,348 +138,6 @@ void Renderer3D::add_debug_aabb(const vec3& min, const vec3& max, #endif } -void Renderer3D::create_pipeline() { - pipeline_ = create_pipeline_impl(true); // BVH enabled - pipeline_no_bvh_ = create_pipeline_impl(false); // BVH disabled - create_mesh_pipeline(); -} - -void Renderer3D::create_mesh_pipeline() { - std::vector 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); -} - -WGPURenderPipeline Renderer3D::create_pipeline_impl(bool use_bvh) { - std::vector 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; -} - -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]; -} - void Renderer3D::update_uniforms(const Scene& scene, const Camera& camera, float time) { GlobalUniforms globals; @@ -838,4 +420,4 @@ void Renderer3D::render(const Scene& scene, const Camera& camera, float time, wgpuCommandBufferRelease(commands); wgpuCommandEncoderRelease(encoder); -} +} \ No newline at end of file -- cgit v1.2.3