pteropus/src/app/dem_renderer/dem_renderer.wgsl

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;
}
}