From b68c8d8cbe9274e42a89888186152d4ded1a2962 Mon Sep 17 00:00:00 2001 From: skal Date: Fri, 6 Feb 2026 06:51:16 +0100 Subject: feat(3d): Implement basic OBJ mesh asset pipeline Added support for loading and rendering OBJ meshes. - Updated asset_packer to parse .obj files into a binary format. - Added MeshAsset and GetMeshAsset helper to asset_manager. - Extended Object3D with mesh_asset_id and ObjectType::MESH. - Implemented mesh rasterization pipeline in Renderer3D. - Added a sample cube mesh and verified in test_3d_render. --- assets/final/demo_assets.txt | 4 ++- assets/final/shaders/mesh_render.wgsl | 59 +++++++++++++++++++++++++++++++++++ assets/final/shaders/renderer_3d.wgsl | 6 ++++ assets/final/test_assets_list.txt | 14 +++++++++ assets/final/test_mesh.obj | 30 ++++++++++++++++++ 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 assets/final/shaders/mesh_render.wgsl create mode 100644 assets/final/test_mesh.obj (limited to 'assets/final') diff --git a/assets/final/demo_assets.txt b/assets/final/demo_assets.txt index c38da51..0febd75 100644 --- a/assets/final/demo_assets.txt +++ b/assets/final/demo_assets.txt @@ -46,4 +46,6 @@ SHADER_MATH_SDF_UTILS, NONE, shaders/math/sdf_utils.wgsl, "SDF Utils Snippet" SHADER_RENDER_SHADOWS, NONE, shaders/render/shadows.wgsl, "Shadows Snippet" SHADER_RENDER_SCENE_QUERY_BVH, NONE, shaders/render/scene_query_bvh.wgsl, "Scene Query Snippet (BVH)" SHADER_RENDER_SCENE_QUERY_LINEAR, NONE, shaders/render/scene_query_linear.wgsl, "Scene Query Snippet (Linear)" -SHADER_RENDER_LIGHTING_UTILS, NONE, shaders/render/lighting_utils.wgsl, "Lighting Utils Snippet" \ No newline at end of file +SHADER_RENDER_LIGHTING_UTILS, NONE, shaders/render/lighting_utils.wgsl, "Lighting Utils Snippet" +SHADER_MESH, NONE, shaders/mesh_render.wgsl, "Mesh Rasterization Shader" +MESH_CUBE, NONE, test_mesh.obj, "A simple cube mesh" \ No newline at end of file diff --git a/assets/final/shaders/mesh_render.wgsl b/assets/final/shaders/mesh_render.wgsl new file mode 100644 index 0000000..3759747 --- /dev/null +++ b/assets/final/shaders/mesh_render.wgsl @@ -0,0 +1,59 @@ +#include "common_uniforms" + +@group(0) @binding(0) var globals: GlobalUniforms; +@group(0) @binding(1) var object_data: ObjectsBuffer; + +// Binding 2 is reserved for BVH (not used here but matches layout for simplicity) + +@group(0) @binding(3) var noise_tex: texture_2d; +@group(0) @binding(4) var noise_sampler: sampler; +@group(0) @binding(5) var sky_tex: texture_2d; + +struct VertexInput { + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, +}; + +struct VertexOutput { + @builtin(position) clip_pos: vec4, + @location(0) world_pos: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) color: vec4, + @location(4) @interpolate(flat) instance_index: u32, +}; + +@vertex +fn vs_main(in: VertexInput, @builtin(instance_index) instance_index: u32) -> VertexOutput { + let obj = object_data.objects[instance_index]; + let world_pos = obj.model * vec4(in.position, 1.0); + + var out: VertexOutput; + out.clip_pos = globals.view_proj * world_pos; + out.world_pos = world_pos.xyz; + + // Normal transform (assuming uniform scale or using transpose(inverse(model))) + // For simplicity, we use the same mat3 logic as renderer_3d.wgsl + let normal_matrix = mat3x3(obj.model[0].xyz, obj.model[1].xyz, obj.model[2].xyz); + out.normal = normalize(normal_matrix * in.normal); + + out.uv = in.uv; + out.color = obj.color; + out.instance_index = instance_index; + return out; +} + +#include "render/scene_query_mode" +#include "render/shadows" +#include "render/lighting_utils" + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + let light_dir = normalize(vec3(1.0, 1.0, 1.0)); + + let shadow = calc_shadow(in.world_pos, light_dir, 0.05, 20.0, in.instance_index); + let lit_color = calculate_lighting(in.color.rgb, in.normal, in.world_pos, shadow); + + return vec4(lit_color, in.color.a); +} diff --git a/assets/final/shaders/renderer_3d.wgsl b/assets/final/shaders/renderer_3d.wgsl index f855052..e7cb810 100644 --- a/assets/final/shaders/renderer_3d.wgsl +++ b/assets/final/shaders/renderer_3d.wgsl @@ -40,6 +40,12 @@ fn vs_main(@builtin(vertex_index) vertex_index: u32, let obj = object_data.objects[instance_index]; let obj_type = obj.params.x; + if (obj_type == 5.0) { // MESH + var out: VertexOutput; + out.position = vec4(0.0, 0.0, 0.0, 0.0); + return out; + } + // Tight fit for Torus proxy hull (major radius 1.0, minor 0.4) if (obj_type == 3.0) { p.x = p.x * 1.5; diff --git a/assets/final/test_assets_list.txt b/assets/final/test_assets_list.txt index c9dd83b..7cded99 100644 --- a/assets/final/test_assets_list.txt +++ b/assets/final/test_assets_list.txt @@ -5,5 +5,19 @@ SHADER_SNIPPET_A, NONE, shaders/test_snippet_a.wgsl, "Test snippet A" SHADER_SNIPPET_B, NONE, shaders/test_snippet_b.wgsl, "Test snippet B" PROC_NOISE_256, PROC(gen_noise, 4321, 8), _, "Procedural noise for testing" TEST_IMAGE, NONE, test_image.tga, "A test TGA image" +TEST_MESH, NONE, test_mesh.obj, "A simple test cube mesh" PROC_UNKNOWN, PROC(gen_unknown_func, 0), _, "Unknown proc function" PROC_FAIL, PROC(gen_noise, -1337, 8), _, "Failing proc function" + +# --- Required Shaders for Renderer3D --- +SHADER_MESH, NONE, shaders/mesh_render.wgsl, "Mesh Rasterization Shader" +SHADER_RENDERER_3D, NONE, shaders/renderer_3d.wgsl, "Hybrid 3D Renderer Shader" +SHADER_SKYBOX, NONE, shaders/skybox.wgsl, "Skybox background shader" +SHADER_COMMON_UNIFORMS, NONE, shaders/common_uniforms.wgsl, "Common Uniforms Snippet" +SHADER_MATH_SDF_SHAPES, NONE, shaders/math/sdf_shapes.wgsl, "SDF Shapes Snippet" +SHADER_MATH_SDF_UTILS, NONE, shaders/math/sdf_utils.wgsl, "SDF Utils Snippet" +SHADER_RENDER_SHADOWS, NONE, shaders/render/shadows.wgsl, "Shadows Snippet" +SHADER_RENDER_SCENE_QUERY_BVH, NONE, shaders/render/scene_query_bvh.wgsl, "Scene Query Snippet (BVH)" +SHADER_RENDER_SCENE_QUERY_LINEAR, NONE, shaders/render/scene_query_linear.wgsl, "Scene Query Snippet (Linear)" +SHADER_RENDER_LIGHTING_UTILS, NONE, shaders/render/lighting_utils.wgsl, "Lighting Utils Snippet" +SHADER_RAY_BOX, NONE, shaders/ray_box.wgsl, "Ray-Box Intersection Snippet" \ No newline at end of file diff --git a/assets/final/test_mesh.obj b/assets/final/test_mesh.obj new file mode 100644 index 0000000..eb304d4 --- /dev/null +++ b/assets/final/test_mesh.obj @@ -0,0 +1,30 @@ +v -0.5 -0.5 0.5 +v 0.5 -0.5 0.5 +v 0.5 0.5 0.5 +v -0.5 0.5 0.5 +v -0.5 -0.5 -0.5 +v 0.5 -0.5 -0.5 +v 0.5 0.5 -0.5 +v -0.5 0.5 -0.5 +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 +vt 0.0 0.0 +vt 1.0 0.0 +vt 1.0 1.0 +vt 0.0 1.0 +f 1/1/1 2/2/1 3/3/1 +f 1/1/1 3/3/1 4/4/1 +f 5/1/2 8/4/2 7/3/2 +f 5/1/2 7/3/2 6/2/2 +f 1/1/6 4/4/6 8/3/6 +f 1/1/6 8/3/6 5/2/6 +f 2/1/5 6/4/5 7/3/5 +f 2/1/5 7/3/5 3/2/5 +f 4/1/3 3/4/3 7/3/3 +f 4/1/3 7/3/3 8/2/3 +f 1/1/4 5/4/4 6/3/4 +f 1/1/4 6/3/4 2/2/4 -- cgit v1.2.3