diff options
Diffstat (limited to 'assets/final/shaders/masked_cube.wgsl')
| -rw-r--r-- | assets/final/shaders/masked_cube.wgsl | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/assets/final/shaders/masked_cube.wgsl b/assets/final/shaders/masked_cube.wgsl new file mode 100644 index 0000000..77e2fb9 --- /dev/null +++ b/assets/final/shaders/masked_cube.wgsl @@ -0,0 +1,160 @@ +// Masked cube shader - based on renderer_3d.wgsl with mask sampling +#include "common_uniforms" +#include "math/common_utils" +#include "math/sdf_utils" + +@group(0) @binding(0) var<uniform> globals: GlobalUniforms; +@group(0) @binding(1) var<storage, read> object_data: ObjectsBuffer; +@group(0) @binding(3) var noise_tex: texture_2d<f32>; +@group(0) @binding(4) var noise_sampler: sampler; +@group(0) @binding(5) var sky_tex: texture_2d<f32>; + +@group(1) @binding(0) var mask_tex: texture_2d<f32>; +@group(1) @binding(1) var mask_sampler: sampler; + +struct VertexOutput { + @builtin(position) position: vec4<f32>, + @location(0) local_pos: vec3<f32>, + @location(1) color: vec4<f32>, + @location(2) @interpolate(flat) instance_index: u32, + @location(3) world_pos: vec3<f32>, + @location(4) transformed_normal: vec3<f32>, +}; + +@vertex +fn vs_main(@builtin(vertex_index) vertex_index: u32, + @builtin(instance_index) instance_index: u32) -> VertexOutput { + var pos = array<vec3<f32>, 36>( + vec3(-1.0, -1.0, 1.0), vec3( 1.0, -1.0, 1.0), vec3( 1.0, 1.0, 1.0), + vec3(-1.0, -1.0, 1.0), vec3( 1.0, 1.0, 1.0), vec3(-1.0, 1.0, 1.0), + vec3(-1.0, -1.0, -1.0), vec3(-1.0, 1.0, -1.0), vec3( 1.0, 1.0, -1.0), + vec3(-1.0, -1.0, -1.0), vec3( 1.0, 1.0, -1.0), vec3( 1.0, -1.0, -1.0), + vec3(-1.0, 1.0, -1.0), vec3(-1.0, 1.0, 1.0), vec3( 1.0, 1.0, 1.0), + vec3(-1.0, 1.0, -1.0), vec3( 1.0, 1.0, 1.0), vec3( 1.0, 1.0, -1.0), + vec3(-1.0, -1.0, -1.0), vec3( 1.0, -1.0, -1.0), vec3( 1.0, -1.0, 1.0), + vec3(-1.0, -1.0, -1.0), vec3( 1.0, -1.0, 1.0), vec3(-1.0, -1.0, 1.0), + vec3( 1.0, -1.0, -1.0), vec3( 1.0, 1.0, -1.0), vec3( 1.0, 1.0, 1.0), + vec3( 1.0, -1.0, -1.0), vec3( 1.0, 1.0, 1.0), vec3( 1.0, -1.0, 1.0), + vec3(-1.0, -1.0, -1.0), vec3(-1.0, -1.0, 1.0), vec3(-1.0, 1.0, 1.0), + vec3(-1.0, -1.0, -1.0), vec3(-1.0, 1.0, 1.0), vec3(-1.0, 1.0, -1.0) + ); + + var p = pos[vertex_index]; + let obj = object_data.objects[instance_index]; + let world_pos = obj.model * vec4<f32>(p, 1.0); + let clip_pos = globals.view_proj * world_pos; + + var out: VertexOutput; + out.position = clip_pos; + out.local_pos = p; + out.color = obj.color; + out.instance_index = instance_index; + out.world_pos = world_pos.xyz; + out.transformed_normal = normalize(vec3<f32>(0.0, 1.0, 0.0)); + + return out; +} + +#include "render/scene_query_mode" +#include "render/shadows" +#include "render/lighting_utils" +#include "ray_box" + +struct FragmentOutput { + @location(0) color: vec4<f32>, + @builtin(frag_depth) depth: f32, +}; + +@fragment +fn fs_main(in: VertexOutput) -> FragmentOutput { + let screen_uv = in.position.xy / globals.resolution; + let mask_value = textureSample(mask_tex, mask_sampler, screen_uv).r; + + if (mask_value < 0.5) { + discard; + } + + let obj = object_data.objects[in.instance_index]; + let obj_type = obj.params.x; + + var p: vec3<f32>; + var normal: vec3<f32>; + var base_color = in.color.rgb; + let light_dir = normalize(vec3<f32>(1.0, 1.0, 1.0)); + + let ray_origin = globals.camera_pos_time.xyz; + let ray_dir = normalize(in.world_pos - ray_origin); + let inv_model = obj.inv_model; + + let local_origin = (inv_model * vec4<f32>(ray_origin, 1.0)).xyz; + let local_dir = normalize((inv_model * vec4<f32>(ray_dir, 0.0)).xyz); + + let t = ray_box(local_origin, local_dir, vec3<f32>(-1.0), vec3<f32>(1.0)); + if (t.y < 0.0) { + discard; + } + + let t_start = max(t.x, 0.0); + let t_end = t.y; + + var t_march = t_start; + let max_steps = 128; + var hit = false; + var local_p = vec3<f32>(0.0); + + for (var step = 0; step < max_steps; step++) { + local_p = local_origin + t_march * local_dir; + let d = sdBox(local_p, vec3<f32>(1.0)); + + if (d < 0.001) { + hit = true; + break; + } + + t_march += max(d * 0.5, 0.001); + if (t_march > t_end) { + break; + } + } + + if (!hit) { + discard; + } + + p = local_p; + let eps = 0.001; + normal = normalize(vec3<f32>( + sdBox(p + vec3<f32>(eps, 0.0, 0.0), vec3<f32>(1.0)) - + sdBox(p - vec3<f32>(eps, 0.0, 0.0), vec3<f32>(1.0)), + sdBox(p + vec3<f32>(0.0, eps, 0.0), vec3<f32>(1.0)) - + sdBox(p - vec3<f32>(0.0, eps, 0.0), vec3<f32>(1.0)), + sdBox(p + vec3<f32>(0.0, 0.0, eps), vec3<f32>(1.0)) - + sdBox(p - vec3<f32>(0.0, 0.0, eps), vec3<f32>(1.0)) + )); + + let world_p = (obj.model * vec4<f32>(p, 1.0)).xyz; + let world_normal = normalize((obj.model * vec4<f32>(normal, 0.0)).xyz); + + let bump_strength = 0.3; + let bump_scale = 4.0; + let noise_uv = world_p.xy * bump_scale; + let noise_val = textureSample(noise_tex, noise_sampler, noise_uv).r; + let bump_offset = (noise_val - 0.5) * bump_strength; + + let bumped_normal = normalize(world_normal + vec3<f32>(bump_offset)); + + let diffuse = max(dot(bumped_normal, light_dir), 0.0); + let ambient = 0.3; + let lighting = ambient + diffuse * 0.7; + + let final_color = base_color * lighting; + + let clip_p = globals.view_proj * vec4<f32>(world_p, 1.0); + let depth = clip_p.z / clip_p.w; + + var out: FragmentOutput; + out.color = vec4<f32>(final_color, 1.0); + out.depth = depth; + + return out; +} |
