Calculate normals and apply lambertian lighting
This commit is contained in:
parent
c822264329
commit
9348c6021b
|
|
@ -4,7 +4,8 @@ struct VertexOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Uniforms {
|
struct Uniforms {
|
||||||
transform: mat4x4<f32>,
|
camera_to_world_matrix: mat4x4<f32>,
|
||||||
|
world_to_ndc_matrix: mat4x4<f32>,
|
||||||
camera_position: vec4<f32>,
|
camera_position: vec4<f32>,
|
||||||
dem_min_corner: vec2<f32>,
|
dem_min_corner: vec2<f32>,
|
||||||
dem_cell_size: vec2<f32>,
|
dem_cell_size: vec2<f32>,
|
||||||
|
|
@ -27,7 +28,7 @@ fn vs_main(
|
||||||
@location(0) position: vec4<f32>,
|
@location(0) position: vec4<f32>,
|
||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
var result: VertexOutput;
|
var result: VertexOutput;
|
||||||
result.position = uniforms.transform * position;
|
result.position = uniforms.world_to_ndc_matrix * position;
|
||||||
result.world_space_position = position;
|
result.world_space_position = position;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -50,8 +51,41 @@ fn fs_solid(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
ray,
|
ray,
|
||||||
root_node,
|
root_node,
|
||||||
&hit_index) {
|
&hit_index) {
|
||||||
let v_i = textureLoad(dem_texture, hit_index, 0).r;
|
//Calculate x-values of cell corners
|
||||||
return vec4<f32>(vec3<f32>(v_i) / 65535.0, 1.0);
|
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 {
|
} else {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,15 +62,20 @@ impl Camera {
|
||||||
glam::Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, ratio, 1.0, 10.0);
|
glam::Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, ratio, 1.0, 10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_matrix(&self) -> glam::Mat4 {
|
fn get_world_to_ndc_matrix(&self) -> glam::Mat4 {
|
||||||
self.projection_matrix * self.view_matrix
|
self.projection_matrix * self.view_matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_camera_to_world_matrix(&self) -> glam::Mat4 {
|
||||||
|
self.view_matrix.inverse()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Pod, Zeroable)]
|
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||||
struct UniformBufferContents {
|
struct UniformBufferContents {
|
||||||
camera_matrix: [f32; 16],
|
camera_to_world_matrix: [f32; 16],
|
||||||
|
world_to_ndc_matrix: [f32; 16],
|
||||||
camera_position: [f32; 4],
|
camera_position: [f32; 4],
|
||||||
dem_min_corner: [f32; 2],
|
dem_min_corner: [f32; 2],
|
||||||
dem_cell_size: [f32; 2],
|
dem_cell_size: [f32; 2],
|
||||||
|
|
@ -80,7 +85,7 @@ struct UniformBufferContents {
|
||||||
// member with the largest alignment. (The mat4x4<f32> type has a 16-byte
|
// member with the largest alignment. (The mat4x4<f32> type has a 16-byte
|
||||||
// alignment.) So this value may be rounded up from the actual size of
|
// alignment.) So this value may be rounded up from the actual size of
|
||||||
// UniformBufferContents.
|
// UniformBufferContents.
|
||||||
const UNIFORM_BUFFER_SIZE: u64 = 112;
|
const UNIFORM_BUFFER_SIZE: u64 = 176;
|
||||||
|
|
||||||
struct UniformBufferManager {
|
struct UniformBufferManager {
|
||||||
cpu_buffer: UniformBufferContents,
|
cpu_buffer: UniformBufferContents,
|
||||||
|
|
@ -101,10 +106,16 @@ impl UniformBufferManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_camera_matrix(&mut self, camera_matrix: glam::Mat4) {
|
fn set_camera_to_world_matrix(&mut self, camera_to_world_matrix: glam::Mat4) {
|
||||||
self.cpu_buffer
|
self.cpu_buffer
|
||||||
.camera_matrix
|
.camera_to_world_matrix
|
||||||
.clone_from_slice(&camera_matrix.to_cols_array())
|
.clone_from_slice(&camera_to_world_matrix.to_cols_array())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_world_to_ndc_matrix(&mut self, world_to_ndc_matrix: glam::Mat4) {
|
||||||
|
self.cpu_buffer
|
||||||
|
.world_to_ndc_matrix
|
||||||
|
.clone_from_slice(&world_to_ndc_matrix.to_cols_array())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_camera_position(&mut self, camera_position: glam::Vec4) {
|
fn set_camera_position(&mut self, camera_position: glam::Vec4) {
|
||||||
|
|
@ -301,7 +312,8 @@ impl DemRenderer {
|
||||||
);
|
);
|
||||||
self.camera
|
self.camera
|
||||||
.set_position(camera_position, self.get_dem_centre());
|
.set_position(camera_position, self.get_dem_centre());
|
||||||
self.uniforms.set_camera_matrix(self.camera.get_matrix());
|
self.uniforms.set_camera_to_world_matrix(self.camera.get_camera_to_world_matrix());
|
||||||
|
self.uniforms.set_world_to_ndc_matrix(self.camera.get_world_to_ndc_matrix());
|
||||||
self.uniforms
|
self.uniforms
|
||||||
.set_camera_position(camera_position.extend(1.0));
|
.set_camera_position(camera_position.extend(1.0));
|
||||||
self.uniforms.update_buffer(queue);
|
self.uniforms.update_buffer(queue);
|
||||||
|
|
@ -482,7 +494,7 @@ fn create_dembvh_texture(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_animated_camera_position(animation_time: std::time::Duration, dem_size: f32) -> glam::Vec3 {
|
fn get_animated_camera_position(animation_time: std::time::Duration, dem_size: f32) -> glam::Vec3 {
|
||||||
let animation_phase = 2.0 * std::f32::consts::PI * (animation_time.as_secs_f32() % 10.0) / 10.0;
|
let animation_phase = 2.0 * std::f32::consts::PI * (animation_time.as_secs_f32() % 25.0) / 25.0;
|
||||||
glam::Vec3::new(
|
glam::Vec3::new(
|
||||||
dem_size * f32::sin(animation_phase),
|
dem_size * f32::sin(animation_phase),
|
||||||
dem_size * f32::cos(animation_phase),
|
dem_size * f32::cos(animation_phase),
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,26 @@ fn intersect_ray_with_node(tree_texture: texture_2d<u32>,
|
||||||
}
|
}
|
||||||
return closest_hit_distance < 1.0e+20;
|
return closest_hit_distance < 1.0e+20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn intersect_ray_with_triangle_plane(ray: Ray,
|
||||||
|
p0: vec3<f32>,
|
||||||
|
p1: vec3<f32>,
|
||||||
|
p2: vec3<f32>) -> vec3<f32> {
|
||||||
|
let n = cross(p1-p0, p2-p0);
|
||||||
|
return ray.origin + ray.direction * dot(p0 - ray.origin, n) / dot(ray.direction, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn point_is_inside_triangle_side(p: vec3<f32>,
|
||||||
|
p0: vec3<f32>, p1: vec3<f32>, p2: vec3<f32>) -> bool {
|
||||||
|
return dot(cross(p2-p1, p-p1), cross(p2-p1, p0-p1)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn point_is_in_triangle(p: vec3<f32>,
|
||||||
|
p0: vec3<f32>, p1: vec3<f32>, p2: vec3<f32>) -> bool {
|
||||||
|
return point_is_inside_triangle_side(p, p0, p1, p2)
|
||||||
|
&& point_is_inside_triangle_side(p, p1, p2, p0)
|
||||||
|
&& point_is_inside_triangle_side(p, p2, p0, p1);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue