summaryrefslogtreecommitdiff
path: root/src/3d/renderer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3d/renderer.cc')
-rw-r--r--src/3d/renderer.cc250
1 files changed, 249 insertions, 1 deletions
diff --git a/src/3d/renderer.cc b/src/3d/renderer.cc
index e08a0d0..0bc8812 100644
--- a/src/3d/renderer.cc
+++ b/src/3d/renderer.cc
@@ -5,6 +5,7 @@
#include "generated/assets.h"
#include "gpu/effects/shader_composer.h"
#include "util/asset_manager.h"
+#include "util/mesh_utils.h"
#include <algorithm>
#include <cassert>
#include <cstring>
@@ -124,7 +125,254 @@ void Renderer3D::create_default_resources() {
WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, nullptr)
.buffer;
}
+void Renderer3D::create_pipeline() {
+ // Shader Modules
+ std::string sdf_shader_source =
+ ShaderComposer::Get().Compose(std::vector<std::string>{}, AssetId::ASSET_SHADER_RENDER_SCENE_QUERY_BVH);
+ WGPUShaderModuleDescriptor sdf_shader_desc =
+ platform_create_shader_module_descriptor(sdf_shader_source.c_str());
+ WGPUShaderModule sdf_shader_module =
+ wgpuDeviceCreateShaderModule(device_, &sdf_shader_desc);
+ std::string sdf_no_bvh_shader_source =
+ ShaderComposer::Get().Compose(std::vector<std::string>{}, AssetId::ASSET_SHADER_RENDER_SCENE_QUERY_LINEAR);
+ WGPUShaderModuleDescriptor sdf_no_bvh_shader_desc =
+ platform_create_shader_module_descriptor(
+ sdf_no_bvh_shader_source.c_str());
+ WGPUShaderModule sdf_no_bvh_shader_module =
+ wgpuDeviceCreateShaderModule(device_, &sdf_no_bvh_shader_desc);
+
+ // Mesh Shader Module
+ std::string mesh_shader_source =
+ ShaderComposer::Get().Compose(std::vector<std::string>{}, AssetId::ASSET_SHADER_RENDER_SHADOWS); // Use SHADOWS shader
+ WGPUShaderModuleDescriptor mesh_shader_desc =
+ platform_create_shader_module_descriptor(mesh_shader_source.c_str());
+ WGPUShaderModule mesh_shader_module =
+ wgpuDeviceCreateShaderModule(device_, &mesh_shader_desc);
+
+ // Bind Group Layouts and Pipelines (SDF)
+ std::vector<WGPUBindGroupLayoutEntry> bgl_entries;
+ // Uniforms
+ bgl_entries.push_back({.binding = 0,
+ .visibility = WGPUShaderStage_Vertex |
+ WGPUShaderStage_Fragment,
+ .buffer = {.type = WGPUBufferBindingType_Uniform,
+ .hasDynamicOffset = false,
+ .minBindingSize = sizeof(GlobalUniforms)}});
+ // Object Storage
+ bgl_entries.push_back(
+ {.binding = 1,
+ .visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment,
+ .buffer = {.type = WGPUBufferBindingType_ReadOnlyStorage,
+ .hasDynamicOffset = false,
+ .minBindingSize = sizeof(ObjectData) * kMaxObjects}});
+
+ // BVH Storage (Conditional for BVH pipeline)
+ bgl_entries.push_back(
+ {.binding = 2,
+ .visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment,
+ .buffer = {.type = WGPUBufferBindingType_ReadOnlyStorage,
+ .hasDynamicOffset = false,
+ .minBindingSize = sizeof(BVHNode) * kMaxObjects * 2}});
+
+ // Noise Texture
+ bgl_entries.push_back({.binding = 3,
+ .visibility = WGPUShaderStage_Fragment,
+ .texture = {.sampleType = WGPUTextureSampleType_Float,
+ .viewDimension = WGPUTextureViewDimension_2D,
+ .multisampled = false}});
+ // Default Sampler
+ bgl_entries.push_back({.binding = 4,
+ .visibility = WGPUShaderStage_Fragment,
+ .sampler = {.type = WGPUSamplerBindingType_Filtering}});
+ // Skybox Texture
+ bgl_entries.push_back({.binding = 5,
+ .visibility = WGPUShaderStage_Fragment,
+ .texture = {.sampleType = WGPUTextureSampleType_Float,
+ .viewDimension = WGPUTextureViewDimension_2D,
+ .multisampled = false}});
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = (uint32_t)bgl_entries.size();
+ bgl_desc.entries = bgl_entries.data();
+
+ 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);
+
+ // Depth Stencil State
+ WGPUDepthStencilState depth_stencil = {};
+ depth_stencil.format = WGPUTextureFormat_Depth24Plus;
+ depth_stencil.depthWriteEnabled = WGPUOptionalBool_True;
+ depth_stencil.depthCompare = WGPUCompareFunction_Less;
+
+ // Configure common color target state
+ WGPUColorTargetState color_target = {};
+ color_target.format = format_;
+ color_target.writeMask = WGPUColorWriteMask_All;
+ // Alpha blending for meshes/particles, but not SDFs
+ color_target.blend = nullptr; // Explicitly set to nullptr
+
+ WGPUFragmentState fragment_state = {};
+ fragment_state.module = sdf_shader_module;
+ fragment_state.entryPoint = str_view("fs_main");
+ fragment_state.targetCount = 1;
+ fragment_state.targets = &color_target;
+
+ // Create SDF pipeline (with BVH)
+ WGPURenderPipelineDescriptor pipeline_desc = {};
+ pipeline_desc.layout = pipeline_layout;
+ pipeline_desc.vertex.module = sdf_shader_module;
+ pipeline_desc.vertex.entryPoint = str_view("vs_main");
+ pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ pipeline_desc.multisample.count = 1;
+ pipeline_desc.multisample.mask = 0xFFFFFFFF;
+ pipeline_desc.fragment = &fragment_state;
+ PLATFORM_SET_PIPELINE_DEPTH_STENCIL(pipeline_desc, &depth_stencil);
+ pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc);
+
+ // Create SDF pipeline (without BVH)
+ fragment_state.module = sdf_no_bvh_shader_module; // Use linear shader
+ WGPURenderPipelineDescriptor pipeline_no_bvh_desc = pipeline_desc;
+ pipeline_no_bvh_desc.vertex.module = sdf_no_bvh_shader_module;
+ pipeline_no_bvh_desc.fragment = &fragment_state;
+ PLATFORM_SET_PIPELINE_DEPTH_STENCIL(pipeline_no_bvh_desc, &depth_stencil);
+ pipeline_no_bvh_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_no_bvh_desc);
+
+ // Configure blend state for mesh/particle pipeline
+ WGPUBlendState mesh_blend_state = {};
+ mesh_blend_state.color.srcFactor = WGPUBlendFactor_SrcAlpha;
+ mesh_blend_state.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
+ mesh_blend_state.color.operation = WGPUBlendOperation_Add;
+ mesh_blend_state.alpha.srcFactor = WGPUBlendFactor_One;
+ mesh_blend_state.alpha.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
+ mesh_blend_state.alpha.operation = WGPUBlendOperation_Add;
+ color_target.blend = &mesh_blend_state; // Enable blending for meshes
+
+ // Create Mesh pipeline
+ WGPURenderPipelineDescriptor mesh_pipeline_desc = {};
+ mesh_pipeline_desc.layout = pipeline_layout;
+ mesh_pipeline_desc.vertex.module = mesh_shader_module;
+ mesh_pipeline_desc.vertex.entryPoint = str_view("vs_main");
+ mesh_pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ mesh_pipeline_desc.multisample.count = 1;
+ mesh_pipeline_desc.multisample.mask = 0xFFFFFFFF;
+ mesh_pipeline_desc.fragment = &fragment_state; // Reuse fragment state
+ // Override fragment module to mesh_shader_module
+ fragment_state.module = mesh_shader_module;
+ mesh_pipeline_desc.fragment = &fragment_state;
+ PLATFORM_SET_PIPELINE_DEPTH_STENCIL(mesh_pipeline_desc, &depth_stencil);
+
+ // Vertex attributes for mesh
+ WGPUVertexAttribute vert_attrs[3] = {};
+ // Position
+ vert_attrs[0].shaderLocation = 0;
+ vert_attrs[0].offset = 0;
+ vert_attrs[0].format = WGPUVertexFormat_Float32x3;
+ // Normal
+ vert_attrs[1].shaderLocation = 1;
+ vert_attrs[1].offset = sizeof(vec3);
+ vert_attrs[1].format = WGPUVertexFormat_Float32x3;
+ // UV
+ vert_attrs[2].shaderLocation = 2;
+ vert_attrs[2].offset = sizeof(vec3) * 2;
+ vert_attrs[2].format = WGPUVertexFormat_Float32x2;
+
+ 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;
+
+ mesh_pipeline_desc.vertex.bufferCount = 1;
+ mesh_pipeline_desc.vertex.buffers = &vert_buffer_layout;
+
+ mesh_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &mesh_pipeline_desc);
+
+ // Release shader modules as they are now part of the pipelines
+ wgpuShaderModuleRelease(sdf_shader_module);
+ wgpuShaderModuleRelease(sdf_no_bvh_shader_module);
+ wgpuShaderModuleRelease(mesh_shader_module);
+ wgpuPipelineLayoutRelease(pipeline_layout);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+}
+
+void Renderer3D::create_skybox_pipeline() {
+ std::string skybox_shader_source =
+ ShaderComposer::Get().Compose(std::vector<std::string>{}, AssetId::ASSET_SHADER_RENDER_SHADOWS); // Use SHADOWS shader
+ WGPUShaderModuleDescriptor skybox_shader_desc =
+ platform_create_shader_module_descriptor(skybox_shader_source.c_str());
+ WGPUShaderModule skybox_shader_module =
+ wgpuDeviceCreateShaderModule(device_, &skybox_shader_desc);
+
+ WGPUBindGroupLayoutEntry bgl_entries[3] = {};
+ // Skybox Texture
+ bgl_entries[0].binding = 0;
+ bgl_entries[0].visibility = WGPUShaderStage_Fragment;
+ bgl_entries[0].texture = {.sampleType = WGPUTextureSampleType_Float,
+ .viewDimension = WGPUTextureViewDimension_2D,
+ .multisampled = false};
+ // Sampler
+ bgl_entries[1].binding = 1;
+ bgl_entries[1].visibility = WGPUShaderStage_Fragment;
+ bgl_entries[1].sampler = {.type = WGPUSamplerBindingType_Filtering};
+ // Global Uniforms
+ bgl_entries[2].binding = 2;
+ bgl_entries[2].visibility = WGPUShaderStage_Vertex;
+ bgl_entries[2].buffer = {.type = WGPUBufferBindingType_Uniform,
+ .hasDynamicOffset = false,
+ .minBindingSize = sizeof(GlobalUniforms)};
+
+ 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);
+
+ WGPUColorTargetState color_target = {};
+ color_target.format = format_;
+ color_target.writeMask = WGPUColorWriteMask_All;
+ color_target.blend = nullptr; // No blending for skybox
+
+ WGPUFragmentState fragment_state = {};
+ fragment_state.module = skybox_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 = skybox_shader_module;
+ pipeline_desc.vertex.entryPoint = str_view("vs_main");
+ pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ pipeline_desc.multisample.count = 1;
+ pipeline_desc.multisample.mask = 0xFFFFFFFF;
+ pipeline_desc.fragment = &fragment_state;
+
+ // Skybox depth state (clear and write depth for objects)
+ WGPUDepthStencilState depth_stencil = {};
+ depth_stencil.format = WGPUTextureFormat_Depth24Plus;
+ depth_stencil.depthWriteEnabled = WGPUOptionalBool_False;
+ depth_stencil.depthCompare = WGPUCompareFunction_Always;
+ PLATFORM_SET_PIPELINE_DEPTH_STENCIL(pipeline_desc, &depth_stencil);
+
+ skybox_pipeline_ = wgpuDeviceCreateRenderPipeline(device_, &pipeline_desc);
+
+ wgpuShaderModuleRelease(skybox_shader_module);
+ wgpuPipelineLayoutRelease(pipeline_layout);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+}
void Renderer3D::set_noise_texture(WGPUTextureView noise_view) {
noise_texture_view_ = noise_view;
}
@@ -450,4 +698,4 @@ void Renderer3D::render(const Scene& scene, const Camera& camera, float time,
wgpuCommandBufferRelease(commands);
wgpuCommandEncoderRelease(encoder);
-} \ No newline at end of file
+}