Fix issues with the normal matrix

This commit is contained in:
SeanOMik 2023-11-17 14:52:38 -05:00
parent 6826d43c8b
commit 039e99281a
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
7 changed files with 84 additions and 39 deletions

View File

@ -27,7 +27,7 @@ tobj = { version = "3.2.1", features = [
]}
instant = "0.1"
async-trait = "0.1.65"
glam = { version = "0.24.0", features = ["bytemuck"] }
glam = { version = "0.24.0", features = ["bytemuck", "debug-glam-assert"] }
gilrs-core = "0.5.6"
syn = "2.0.26"
quote = "1.0.29"

View File

@ -57,6 +57,9 @@ impl Criteria for FixedTimestep {
#[derive(Clone)]
struct TpsAccumulator(f32);
#[derive(Component)]
struct CubeFlag;
#[async_std::main]
async fn main() {
let setup_sys = |world: &mut World| -> anyhow::Result<()> {
@ -68,7 +71,7 @@ async fn main() {
let mut resman = world.get_resource_mut::<ResourceManager>().unwrap();
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
//let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap();
drop(resman);
@ -103,17 +106,22 @@ async fn main() {
}, */
TransformComponent::from(cube_tran),
ModelComponent(cube_model.clone()),
CubeFlag,
));
let mut light_tran = Transform::from_xyz(3.5, 0.0, -7.0);
let mut light_tran = Transform::from_xyz(1.5, 2.5, -8.5);
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
world.spawn((
PointLight {
color: Vec3::new(0.361, 0.984, 0.0),
color: Vec3::new(1.0, 1.0, 1.0), //Vec3::new(0.361, 0.984, 0.0),
intensity: 1.0,
constant: 1.0,
/* constant: 1.0,
linear: 0.045,
quadratic: 0.0075,
quadratic: 0.0075, */
constant: 1.0,
linear: 0.09,
quadratic: 0.032,
ambient: 0.2,
diffuse: 0.5,
@ -147,10 +155,10 @@ async fn main() {
};
let spin_system = |world: &mut World| -> anyhow::Result<()> {
const SPEED: f32 = 5.0;
const SPEED: f32 = 7.0;
let delta_time = **world.get_resource::<DeltaTime>().unwrap();
for transform in world.query_mut::<(&mut TransformComponent,)>().iter_mut() {
for (transform, _) in world.query_mut::<(&mut TransformComponent, &CubeFlag)>().iter_mut() {
let t = &mut transform.transform;
t.rotate_y(math::Angle::Degrees(SPEED * delta_time));
}
@ -164,7 +172,7 @@ async fn main() {
let mut sys = BatchedSystem::new();
sys.with_criteria(FixedTimestep::new(45));
//sys.with_system(spin_system);
sys.with_system(fps_system);
//sys.with_system(fps_system);
game.with_system("fixed", sys, &[]);
fps_plugin(game);
@ -203,7 +211,7 @@ async fn main() {
game.world().insert_resource(action_handler);
game.with_plugin(InputActionPlugin);
game.with_system("test_actions", test_system, &[]);
//game.with_system("test_actions", test_system, &[]);
};
Game::initialize().await

View File

@ -92,11 +92,17 @@ impl Transform {
/// will be equal to `rhs`. When `alpha` is outside of range `[0, 1]`, the result is linearly
/// extrapolated.
pub fn lerp(&self, rhs: Transform, alpha: f32) -> Self {
let mut res = self.clone();
res.translation = self.translation.lerp(rhs.translation, alpha);
res.rotation = self.rotation.lerp(rhs.rotation, alpha);
res.scale = self.scale.lerp(rhs.scale, alpha);
res
if alpha.is_finite() {
let mut res = self.clone();
res.translation = self.translation.lerp(rhs.translation, alpha);
res.rotation = self.rotation.lerp(rhs.rotation, alpha);
res.scale = self.scale.lerp(rhs.scale, alpha);
res
} else {
self.clone()
}
}
}

View File

@ -1,4 +1,5 @@
use super::texture::RenderTexture;
use super::texture::RenderTexture;
#[derive(Clone)]
pub struct Material {
@ -19,7 +20,8 @@ impl Material {
shader_id: value.shader_uuid.unwrap_or(0),
diffuse_texture,
ambient: glam::Vec3::new(1.0, 0.5, 0.31),
diffuse: glam::Vec3::new(value.base_color.x, value.base_color.y, value.base_color.z),
//diffuse: glam::Vec3::new(value.base_color.x, value.base_color.y, value.base_color.z),
diffuse: glam::Vec3::new(1.0, 0.5, 0.31),
specular: glam::Vec3::new(0.5, 0.5, 0.5),
shininess: 32.0,
}

View File

@ -1,5 +1,6 @@
// Vertex shader
const max_light_count: u32 = 16u;
const max_light_count: u32 = 16u;
struct VertexInput {
@ -24,6 +25,7 @@ struct PointLight {
position: vec4<f32>,
color: vec4<f32>,
intensity: f32,
constant: f32,
linear: f32,
@ -32,6 +34,10 @@ struct PointLight {
ambient: f32,
diffuse: f32,
specular: f32,
ambient: f32,
diffuse: f32,
specular: f32,
};
struct Lights {
@ -42,7 +48,7 @@ struct Lights {
@group(1) @binding(0)
var<uniform> u_model_transform: mat4x4<f32>;
@group(1) @binding(1)
var<uniform> u_model_normal_matrix: mat3x3<f32>;
var<uniform> u_model_normal_matrix: mat4x4<f32>;
@group(2) @binding(0)
var<uniform> u_camera: CameraUniform;
@ -59,7 +65,9 @@ fn vs_main(
out.tex_coords = model.tex_coords;
out.clip_position = u_camera.view_proj * u_model_transform * vec4<f32>(model.position, 1.0);
out.world_normal = u_model_normal_matrix * model.normal;
// the normal mat is actually only a mat3x3, but there's a bug in wgpu: https://github.com/gfx-rs/wgpu-rs/issues/36
let normal_mat = mat3x3(u_model_normal_matrix[0].xyz, u_model_normal_matrix[1].xyz, u_model_normal_matrix[2].xyz);
out.world_normal = normalize(normal_mat * model.normal, );
var world_position: vec4<f32> = u_model_transform * vec4<f32>(model.position, 1.0);
out.world_position = world_position.xyz;
@ -76,9 +84,17 @@ struct Material {
shininess: f32,
}
struct Material {
ambient: vec4<f32>,
diffuse: vec4<f32>,
specular: vec4<f32>,
shininess: f32,
}
@group(0) @binding(0)
var t_diffuse: texture_2d<f32>;
@group(0) @binding(1)
@group(0) @binding(1)
var s_diffuse: sampler;
@group(4) @binding(0)
@ -91,8 +107,9 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
var light_res = vec3<f32>(0.0);
for (var i = 0u; i < u_lights.point_light_count; i++) {
light_res += blinn_phong_point_light(in.world_position, in.world_normal, u_lights.point_lights[i], u_material);
light_res += blinn_phong_point_light(in.world_position, in.world_normal, u_lights.point_lights[i], u_material);
}
let light_object_res = light_res * object_color.xyz;
let light_object_res = light_res * (object_color.xyz/* * u_material.diffuse.xyz*/);
return vec4<f32>(light_object_res, object_color.a);
}
@ -105,31 +122,40 @@ fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_li
// We don't need (or want) much ambient light, so 0.1 is fine
//let ambient_strength = 0.1;
var ambient_color = light_color * material.ambient.xyz;
//let ambient_strength = 0.1;
var ambient_color = light_color * material.ambient.xyz;
//// diffuse ////
let light_dir = normalize(light_pos - world_pos);
let diffuse_strength = max(dot(world_norm, light_dir), 0.0);
var diffuse_color = light_color * (diffuse_strength * material.diffuse.xyz);
var diffuse_color = light_color * (diffuse_strength * material.diffuse.xyz);
//// end of diffuse ////
//// specular ////
let view_dir = normalize(camera_view_pos - world_pos);
let half_dir = normalize(view_dir + light_dir);
let specular_strength = pow(max(dot(world_norm, half_dir), 0.0), material.shininess);
var specular_color = specular_strength * (light_color * material.specular.xyz);
let specular_strength = pow(max(dot(world_norm, half_dir), 0.0), material.shininess);
var specular_color = specular_strength * (light_color * material.specular.xyz);
//// end of specular ////
//// point light attenuation ////
let distance = length(light_pos - world_pos);
/*let distance = length(light_pos - world_pos);
let attenuation = 1.0 / (point_light.constant + point_light.linear * distance +
point_light.quadratic * (distance * distance));
point_light.quadratic * (distance * distance));*/
ambient_color *= attenuation * point_light.intensity * point_light.ambient;
diffuse_color *= attenuation * point_light.intensity * point_light.diffuse;
specular_color *= attenuation * point_light.intensity * point_light.specular;
//ambient_color *= attenuation * point_light.intensity * point_light.ambient;
//diffuse_color *= attenuation * point_light.intensity * point_light.diffuse;
//specular_color *= attenuation * point_light.intensity * point_light.specular;
//// end of point light attenuation ////
return (ambient_color + diffuse_color + specular_color);
ambient_color *= point_light.ambient;
diffuse_color *= point_light.diffuse;
specular_color *= point_light.specular;
return (ambient_color + diffuse_color + specular_color) * /*attenuation * */ point_light.intensity;
}

View File

@ -1,6 +1,7 @@
use std::{collections::{VecDeque, HashMap}, num::NonZeroU64};
use edict::EntityId;
use tracing::debug;
use wgpu::Limits;
use std::mem;
@ -63,7 +64,7 @@ impl TransformBuffers {
});
let mut s = Self {
max_transform_count: limits.max_uniform_buffer_binding_size as usize / (mem::size_of::<glam::Mat4>() + mem::size_of::<glam::Mat3>()),
max_transform_count: limits.max_uniform_buffer_binding_size as usize / (mem::size_of::<glam::Mat4>() * 2),
buffer_bindgroups: Vec::new(),
bindgroup_layout,
just_updated: HashMap::new(),
@ -85,6 +86,10 @@ impl TransformBuffers {
.expect("Use 'insert_entity' for new entities");
self.just_updated.insert(entity, indices);
debug!("Normal: {normal_matrix:?}");
let normal_matrix = glam::Mat4::from_mat3(normal_matrix);
let buffer = self.buffer_bindgroups.get(indices.buffer_index).unwrap();
let offset = Self::index_offset(limits, indices);
queue.write_buffer(&buffer.transform_buf, offset, bytemuck::bytes_of(&transform));
@ -173,7 +178,7 @@ impl TransformBuffers {
let transform_buffer = device.create_buffer(
&wgpu::BufferDescriptor {
label: Some(&format!("Transform Buffer {}", self.buffer_bindgroups.len())),
label: Some(&format!("B_Transform_{}", self.buffer_bindgroups.len())),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
size: max_buffer_sizes,
mapped_at_creation: false,
@ -182,19 +187,17 @@ impl TransformBuffers {
let normal_mat_buffer = device.create_buffer(
&wgpu::BufferDescriptor {
label: Some(&format!("Normal Matrix Buffer {}", self.buffer_bindgroups.len())),
label: Some(&format!("B_NormalMatrix_{}", self.buffer_bindgroups.len())),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
size: max_buffer_sizes,
mapped_at_creation: false,
}
);
/* let stride = limits.min_uniform_buffer_offset_alignment as u64
+ mem::size_of::<glam::Mat4>() as u64 + mem::size_of::<glam::Mat3>() as u64; */
let tran_stride = limits.min_uniform_buffer_offset_alignment as u64
+ mem::size_of::<glam::Mat4>() as u64;
let norm_stride = limits.min_uniform_buffer_offset_alignment as u64
+ mem::size_of::<glam::Mat3>() as u64;
let tran_stride = mem::size_of::<glam::Mat4>();
// although a normal matrix only needs to be a mat3, there's a weird issue with
// misalignment from wgpu or spirv-cross: https://github.com/gfx-rs/wgpu-rs/issues/36
let norm_stride = mem::size_of::<glam::Mat4>();
let transform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &self.bindgroup_layout,
@ -205,7 +208,7 @@ impl TransformBuffers {
wgpu::BufferBinding {
buffer: &transform_buffer,
offset: 0,
size: Some(NonZeroU64::new(tran_stride).unwrap())
size: Some(NonZeroU64::new(tran_stride as u64).unwrap())
}
)
},
@ -215,12 +218,12 @@ impl TransformBuffers {
wgpu::BufferBinding {
buffer: &normal_mat_buffer,
offset: 0,
size: Some(NonZeroU64::new(norm_stride).unwrap())
size: Some(NonZeroU64::new(norm_stride as u64).unwrap())
}
)
}
],
label: Some("transform_bind_group"),
label: Some("BG_Transforms"),
});
let entry = TransformBufferEntry {

View File

@ -34,7 +34,7 @@ impl DescVertexBufferLayout for Vertex {
format: wgpu::VertexFormat::Float32x2, // Vec2
},
wgpu::VertexAttribute {
offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
offset: std::mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
shader_location: 2,
format: wgpu::VertexFormat::Float32x3, // Vec3
}