93 lines
3.4 KiB
WebGPU Shading Language
93 lines
3.4 KiB
WebGPU Shading Language
struct VertexOutput {
|
|
@location(0) world_space_position: vec4<f32>,
|
|
@builtin(position) position: vec4<f32>,
|
|
}
|
|
|
|
struct Uniforms {
|
|
camera_to_world_matrix: mat4x4<f32>,
|
|
world_to_ndc_matrix: mat4x4<f32>,
|
|
camera_position: vec4<f32>,
|
|
dem_min_corner: vec2<f32>,
|
|
dem_cell_size: vec2<f32>,
|
|
dem_z_range: vec2<f32>
|
|
}
|
|
|
|
@group(0) @binding(0)
|
|
var<uniform> uniforms: Uniforms;
|
|
|
|
@group(0) @binding(1)
|
|
var dem_texture: texture_2d<u32>;
|
|
|
|
@group(0) @binding(2)
|
|
var dembvh_texture: texture_2d<u32>;
|
|
|
|
//#include ray_intersection.wgsl
|
|
|
|
@vertex
|
|
fn vs_main(
|
|
@location(0) position: vec4<f32>,
|
|
) -> VertexOutput {
|
|
var result: VertexOutput;
|
|
result.position = uniforms.world_to_ndc_matrix * position;
|
|
result.world_space_position = position;
|
|
return result;
|
|
}
|
|
|
|
@fragment
|
|
fn fs_solid(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
|
var ray: Ray;
|
|
ray.origin = vertex.world_space_position.xyz;
|
|
ray.direction = normalize(vertex.world_space_position.xyz - uniforms.camera_position.xyz);
|
|
|
|
var root_node: BoundingNode;
|
|
root_node.index = vec2<u32>(0);
|
|
root_node.level = textureNumLevels(dembvh_texture) - 1;
|
|
|
|
var hit_index = vec2<u32>(0);
|
|
if intersect_ray_with_node(dembvh_texture,
|
|
uniforms.dem_min_corner,
|
|
uniforms.dem_cell_size,
|
|
uniforms.dem_z_range,
|
|
ray,
|
|
root_node,
|
|
&hit_index) {
|
|
//Calculate x-values of cell corners
|
|
let v00 = textureLoad(dem_texture, hit_index, 0).r;
|
|
let v01 = textureLoad(dem_texture, hit_index + vec2<u32>(0,1), 0).r;
|
|
let v10 = textureLoad(dem_texture, hit_index + vec2<u32>(1,0), 0).r;
|
|
let v11 = textureLoad(dem_texture, hit_index + vec2<u32>(1,1), 0).r;
|
|
let z00 = 12.0 * f32(v00) / 65535.0;
|
|
let z01 = 12.0 * f32(v01) / 65535.0;
|
|
let z10 = 12.0 * f32(v10) / 65535.0;
|
|
let z11 = 12.0 * f32(v11) / 65535.0;
|
|
// Calculate xyz of cell corners
|
|
let xy00 = uniforms.dem_min_corner.xy
|
|
+ uniforms.dem_cell_size * vec2<f32>(hit_index);
|
|
let p00 = vec3<f32>(xy00, z00);
|
|
let p01 = vec3<f32>(xy00 + vec2<f32>(0, 1), z01);
|
|
let p10 = vec3<f32>(xy00 + vec2<f32>(1, 0), z10);
|
|
let p11 = vec3<f32>(xy00 + vec2<f32>(1, 1), z11);
|
|
// Intersect ray with the plane of each triangle and then take the
|
|
// point that's inside it's triangle.
|
|
// p is the point and p0, p1 and p2 are the triangle corners.
|
|
let p_t0 = intersect_ray_with_triangle_plane(ray, p00, p01, p11);
|
|
let p_t1 = intersect_ray_with_triangle_plane(ray, p00, p10, p11);
|
|
let point_is_in_first_triangle = point_is_in_triangle(p_t0, p00, p01, p11);
|
|
let p = select(p_t1, p_t0, point_is_in_first_triangle);
|
|
let p0 = p00;
|
|
let p1 = select(p10, p01, point_is_in_first_triangle);
|
|
let p2 = p11;
|
|
// Estimate normal as cross product of triangle for now
|
|
var normal = normalize(cross(p1-p0, p2-p0));
|
|
normal *= sign(normal.z); //Ensure normal points up
|
|
// Calculate light
|
|
let sun_direction = (uniforms.camera_to_world_matrix
|
|
* vec4<f32>(normalize(vec3<f32>(1.0, 1.0, 1.0)), 0.0)).xyz;
|
|
let l = dot(normal, sun_direction);
|
|
return vec4<f32>(l, l, l, 1.0);
|
|
//return vec4<f32>(normal.xy, 0.0, 1.0);
|
|
} else {
|
|
discard;
|
|
}
|
|
}
|