Dont duplicate model verts for flat shading

This commit is contained in:
Connor Slade
2025-02-09 11:17:28 -05:00
parent 738a22bce5
commit fc51037e82
7 changed files with 46 additions and 68 deletions

View File

@@ -2,6 +2,7 @@ use std::mem;
use dispatch::solid_line::SolidLineDispatch; use dispatch::solid_line::SolidLineDispatch;
use eframe::CreationContext; use eframe::CreationContext;
use nalgebra::Vector4;
use pipelines::{ use pipelines::{
model::ModelPipeline, slice_preview::SlicePreviewPipeline, target_point::TargetPointPipeline, model::ModelPipeline, slice_preview::SlicePreviewPipeline, target_point::TargetPointPipeline,
}; };
@@ -20,25 +21,17 @@ pub mod workspace;
pub const VERTEX_BUFFER_LAYOUT: VertexBufferLayout = VertexBufferLayout { pub const VERTEX_BUFFER_LAYOUT: VertexBufferLayout = VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as BufferAddress, array_stride: mem::size_of::<ModelVertex>() as BufferAddress,
step_mode: VertexStepMode::Vertex, step_mode: VertexStepMode::Vertex,
attributes: &[ attributes: &[VertexAttribute {
VertexAttribute { format: VertexFormat::Float32x4,
format: VertexFormat::Float32x4, offset: 0,
offset: 0, shader_location: 0,
shader_location: 0, }],
},
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 4 * 4,
shader_location: 1,
},
],
}; };
#[repr(C)] #[repr(C)]
#[derive(Default, Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Default, Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct ModelVertex { pub struct ModelVertex {
pub position: [f32; 4], pub position: [f32; 4],
pub normal: [f32; 3],
} }
pub fn init_wgpu(cc: &CreationContext) { pub fn init_wgpu(cc: &CreationContext) {
@@ -55,3 +48,11 @@ pub fn init_wgpu(cc: &CreationContext) {
slice_preview_pipeline: SlicePreviewPipeline::new(device), slice_preview_pipeline: SlicePreviewPipeline::new(device),
}); });
} }
impl ModelVertex {
pub fn new(pos: Vector4<f32>) -> Self {
Self {
position: [pos.x, pos.y, pos.z, pos.w],
}
}
}

View File

@@ -105,7 +105,6 @@ impl SlicePreviewPipeline {
.into_iter() .into_iter()
.map(|[x, y]| ModelVertex { .map(|[x, y]| ModelVertex {
position: [x, y, 0.0, 1.0], position: [x, y, 0.0, 1.0],
normal: [0.0, 0.0, 1.0],
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let vertex_buffer = device.create_buffer_init(&BufferInitDescriptor { let vertex_buffer = device.create_buffer_init(&BufferInitDescriptor {

View File

@@ -176,7 +176,6 @@ fn generate_sphere(precision: usize) -> (Vec<ModelVertex>, Vec<u32>) {
x.2.into_inner() as f32, x.2.into_inner() as f32,
1.0, 1.0,
], ],
normal: [0.0, 0.0, 0.0],
}) })
.collect(); .collect();

View File

@@ -21,6 +21,7 @@ pub struct RenderedMesh {
pub locked_scale: bool, pub locked_scale: bool,
vertices: Vec<ModelVertex>, vertices: Vec<ModelVertex>,
index: Vec<u32>,
buffers: Option<RenderedMeshBuffers>, buffers: Option<RenderedMeshBuffers>,
} }
@@ -31,32 +32,13 @@ pub struct RenderedMeshBuffers {
impl RenderedMesh { impl RenderedMesh {
pub fn from_mesh(mesh: Mesh) -> Self { pub fn from_mesh(mesh: Mesh) -> Self {
let mut out = Vec::new(); let (vertices, faces) = (mesh.vertices(), mesh.faces());
let (vertices, normals) = (mesh.vertices(), mesh.normals()); let index = faces.iter().flatten().copied().collect::<Vec<_>>();
for (i, face) in mesh.faces().iter().enumerate() { let vertices = vertices
let (a, b, c) = ( .iter()
vertices[face[0] as usize], .map(|vert| ModelVertex::new(vert.push(1.0)))
vertices[face[1] as usize], .collect();
vertices[face[2] as usize],
);
let normal = normals[i];
out.extend_from_slice(&[
ModelVertex {
position: [a.x, a.y, a.z, 1.0],
normal: normal.into(),
},
ModelVertex {
position: [b.x, b.y, b.z, 1.0],
normal: normal.into(),
},
ModelVertex {
position: [c.x, c.y, c.z, 1.0],
normal: normal.into(),
},
]);
}
Self { Self {
name: String::new(), name: String::new(),
@@ -65,7 +47,8 @@ impl RenderedMesh {
color: Color32::WHITE, color: Color32::WHITE,
hidden: false, hidden: false,
locked_scale: true, locked_scale: true,
vertices: out, index,
vertices,
buffers: None, buffers: None,
} }
} }
@@ -121,9 +104,7 @@ impl RenderedMesh {
let index_buffer = device.create_buffer_init(&BufferInitDescriptor { let index_buffer = device.create_buffer_init(&BufferInitDescriptor {
label: None, label: None,
contents: bytemuck::cast_slice( contents: bytemuck::cast_slice(&self.index),
&(0..self.mesh.face_count() as u32 * 3).collect::<Vec<u32>>(),
),
usage: BufferUsages::INDEX | BufferUsages::COPY_DST, usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
}); });
@@ -147,6 +128,7 @@ impl Clone for RenderedMesh {
hidden: self.hidden, hidden: self.hidden,
locked_scale: self.locked_scale, locked_scale: self.locked_scale,
vertices: self.vertices.clone(), vertices: self.vertices.clone(),
index: self.index.clone(),
buffers: None, buffers: None,
} }
} }

View File

@@ -9,37 +9,43 @@ struct Context {
render_style: u32, render_style: u32,
} }
struct VertexInput {
@location(0)
position: vec4<f32>
}
struct VertexOutput { struct VertexOutput {
@builtin(position) @builtin(position)
position: vec4<f32>, position: vec4<f32>,
@location(1) @location(1)
normal: vec3<f32>, world_position: vec3<f32>
}; };
@vertex @vertex
fn vert( fn vert(in: VertexInput) -> VertexOutput {
@location(0) position: vec4<f32>,
@location(1) normal: vec3<f32>,
) -> VertexOutput {
var out: VertexOutput; var out: VertexOutput;
out.position = context.transform * position; out.position = context.transform * in.position;
out.normal = normalize((context.model_transform * vec4(normal, 0.0)).xyz); out.world_position = (context.model_transform * in.position).xyz;
return out; return out;
} }
@fragment @fragment
fn frag(in: VertexOutput) -> @location(0) vec4<f32> { fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
let dy = dpdy(in.world_position);
let dx = dpdx(in.world_position);
let normal = normalize(cross(dy, dx));
if context.render_style == 0 { if context.render_style == 0 {
return vec4<f32>(in.normal, 1.0); return vec4<f32>(normal, 1.0);
} else { } else {
let camera_direction = normalize(context.camera_position + context.camera_target); let camera_direction = normalize(context.camera_position + context.camera_target);
let diffuse = max(dot(in.normal, camera_direction), 0.0); let diffuse = max(dot(normal, camera_direction), 0.0);
let reflect_dir = reflect(-camera_direction, in.normal); let reflect_dir = reflect(-camera_direction, normal);
let specular = pow(max(dot(camera_direction, reflect_dir), 0.0), 32.0); let specular = pow(max(dot(camera_direction, reflect_dir), 0.0), 32.0);
let intensity = (diffuse + specular + 0.1) * context.model_color.rgb; let intensity = (diffuse + specular + 0.1) * context.model_color.rgb;
return vec4<f32>(intensity, context.model_color.a); return vec4<f32>(intensity, context.model_color.a);
} }
} }

View File

@@ -15,10 +15,7 @@ struct VertexOutput {
}; };
@vertex @vertex
fn vert( fn vert(@location(0) position: vec4<f32>) -> VertexOutput {
@location(0) position: vec4<f32>,
@location(1) normal: vec3<f32>,
) -> VertexOutput {
var out: VertexOutput; var out: VertexOutput;
out.camera_position = position; out.camera_position = position;
out.position = position; out.position = position;
@@ -42,4 +39,4 @@ fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
u32(pos.y * f32(context.dimensions.y) + context.offset.y) u32(pos.y * f32(context.dimensions.y) + context.offset.y)
); );
return vec4<f32>(value, value, value, 1.0); return vec4<f32>(value, value, value, 1.0);
} }

View File

@@ -8,22 +8,16 @@ struct Context {
struct VertexOutput { struct VertexOutput {
@builtin(position) @builtin(position)
position: vec4<f32>, position: vec4<f32>,
@location(0)
normal: vec3<f32>,
}; };
@vertex @vertex
fn vert( fn vert(@location(0) position: vec4<f32>) -> VertexOutput {
@location(0) position: vec4<f32>,
@location(1) normal: vec3<f32>,
) -> VertexOutput {
var out: VertexOutput; var out: VertexOutput;
out.position = context.transform * position; out.position = context.transform * position;
out.normal = normal;
return out; return out;
} }
@fragment @fragment
fn frag(in: VertexOutput) -> @location(0) vec4<f32> { fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
return context.color; return context.color;
} }