WebGPU Voxel Game
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 133 lines 4.9 kB view raw
1// Vertex shader 2 3// struct InstanceInput { 4// @location(5) model_matrix_0: vec4<f32>, 5// @location(6) model_matrix_1: vec4<f32>, 6// @location(7) model_matrix_2: vec4<f32>, 7// @location(8) model_matrix_3: vec4<f32>, 8 9// @location(9) normal_matrix_0: vec3<f32>, 10// @location(10) normal_matrix_1: vec3<f32>, 11// @location(11) normal_matrix_2: vec3<f32>, 12// }; 13 14struct Camera { 15 view_pos: vec4<f32>, 16 view_proj: mat4x4<f32>, 17} 18@group(1) @binding(0) 19var<uniform> camera: Camera; 20 21@group(1) @binding(1) 22var<uniform> light: Camera; 23 24 25struct VertexInput { 26 @location(0) position: vec3<f32>, 27 @location(1) tex_coords: vec2<f32>, 28 @location(2) normal: vec3<f32>, 29} 30 31struct VertexOutput { 32 @builtin(position) clip_position: vec4<f32>, 33 @location(0) tex_coords: vec2<f32>, 34 @location(1) world_normal: vec3<f32>, 35 @location(2) world_position: vec3<f32>, 36}; 37 38@vertex 39fn vs_main( 40 model: VertexInput, 41) -> VertexOutput { 42 43 44 var out: VertexOutput; 45 out.tex_coords = model.tex_coords; 46 out.world_normal = model.normal; 47 48 var world_position: vec4<f32> = vec4<f32>(model.position, 1.0); 49 out.world_position = world_position.xyz; 50 out.clip_position = camera.view_proj * world_position; 51 return out; 52} 53 54 55// Fragment shader 56 57@group(0) @binding(0) 58var t_diffuse: texture_2d<f32>; 59@group(0) @binding(1) 60var s_diffuse: sampler; 61 62@group(1) @binding(2) 63var t_shadow: texture_depth_2d; 64@group(1) @binding(3) 65var s_shadow: sampler_comparison; 66 67// TODO CITE: wgpu/examples/shadow 68fn fetch_shadow(homogeneous_coords: vec4<f32>) -> f32 { 69 if (homogeneous_coords.w <= 0.0) { 70 return 1.0; 71 } 72 // compensate for the Y-flip difference between the NDC and texture coordinates 73 let flip_correction = vec2<f32>(0.5, -0.5); 74 // compute texture coordinates for shadow lookup 75 let proj_correction = 1.0 / homogeneous_coords.w; 76 let light_local = homogeneous_coords.xy * flip_correction * proj_correction + vec2<f32>(0.5, 0.5); 77 // do the lookup, using HW PCF and comparison 78 return textureSampleCompareLevel(t_shadow, s_shadow, light_local, homogeneous_coords.z * proj_correction); 79} 80 81@fragment 82fn fs_main(in: VertexOutput, @builtin(front_facing) face: bool) -> @location(0) vec4<f32> { 83 let light_color = vec3<f32>(1.0, 1.0, 1.0); 84 85 let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords); 86 87 let ambient_strength = 1.0; 88 let ambient_color = light_color * ambient_strength; 89 90 let light_dir = normalize(light.view_pos.xyz - in.world_position.xyz); 91 let diffuse_strength = max(dot(in.world_normal, light_dir), 0.0); 92 let diffuse_color = light_color * diffuse_strength; 93 94 let view_dir = normalize(camera.view_pos.xyz - in.world_position.xyz); 95 let half_dir = normalize(view_dir + light_dir); 96 97 // https://github.com/mcclure/webgpu-tutorial-rs/blob/webgpu-tutorial/src/shader.wgsl 98 // This one-dimensional separable blur filter samples five points and averages them by different amounts. 99 // If we do it on two separate axes, we get a 2d blur. 100 // Weights and offsets taken from http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ 101 102 // The weights for the center, one-point-out, and two-point-out samples 103 const WEIGHT0 = 0.2270270270; 104 const WEIGHT1 = 0.3162162162; 105 const WEIGHT2 = 0.0702702703; 106 107 // The distances-from-center for the samples 108 const OFFSET1 = 1.3846153846; 109 const OFFSET2 = 3.2307692308; 110 111 let blur_resolution = vec2<f32>(60.0, 60.0); 112 113 var shadow_guassian = 0.0; 114 shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position, 1.0)) * WEIGHT0; 115 shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy + blur_resolution * OFFSET1, in.world_position.z, 1.0)) * WEIGHT1; 116 shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy - blur_resolution * OFFSET1, in.world_position.z, 1.0)) * WEIGHT1; 117 shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy + blur_resolution * OFFSET2, in.world_position.z, 1.0)) * WEIGHT2; 118 shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy - blur_resolution * OFFSET2, in.world_position.z, 1.0)) * WEIGHT2; 119 120 let shadow_strength = 0.7; 121 let shadow = fetch_shadow(light.view_proj * vec4<f32>(in.world_position, 1.0)); 122 123 124 let specular_strength = pow(max(dot(in.world_normal, half_dir), 0.0), 32.0); 125 126 // Disable specular effects in shadow 127 let specular_color = specular_strength * light_color * shadow; 128 129 let result = (ambient_color + diffuse_color + specular_color) * (shadow_guassian * shadow_strength + (1.0 - shadow_strength)) * object_color.xyz; 130 // let result = (ambient_color + diffuse_color + specular_color) * (shadow_guassian * shadow_strength + (1.0 - shadow_strength)); 131 132 return vec4<f32>(result, object_color.a); 133}