#include "common_uniforms" #include "math/common_utils" @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; // Transform normal from local to world space out.normal = transform_normal(obj.inv_model, 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); }