Switch to desktop
ci/woodpecker/push/build Pipeline was successful Details

This commit is contained in:
SeanOMik 2023-11-15 19:47:22 -05:00
parent b2bbbbbfad
commit 6826d43c8b
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
9 changed files with 313 additions and 23 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -69,7 +69,8 @@ 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 cube_model = resman.request::<Model>("assets/cube-texture-bin.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);
/* world.spawn((
@ -113,6 +114,10 @@ async fn main() {
constant: 1.0,
linear: 0.045,
quadratic: 0.0075,
ambient: 0.2,
diffuse: 0.5,
specular: 1.0,
},
TransformComponent::from(light_tran),
ModelComponent(cube_model),

View File

@ -1,5 +1,5 @@
pub mod point;
use std::{collections::{VecDeque, HashMap}, num::NonZeroU64, marker::PhantomData};
use std::{collections::{VecDeque, HashMap}, num::{NonZeroU64, NonZeroU32}, marker::PhantomData};
use edict::query::EpochOf;
pub use point::*;
@ -10,7 +10,7 @@ use std::mem;
use crate::{math::Transform, ecs::components::TransformComponent};
const MAX_LIGHT_COUNT: usize = 32;
const MAX_LIGHT_COUNT: usize = 16;
pub struct LightBuffer<U: Default + bytemuck::Pod + bytemuck::Zeroable> {
_phantom: PhantomData<U>,
@ -106,7 +106,7 @@ impl LightUniformBuffers {
pub fn new(device: &wgpu::Device) -> Self {
let buffer = device.create_buffer(
&wgpu::BufferDescriptor {
label: Some("Lights Uniform buffer"),
label: Some("UB_Lights"),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
size: (mem::size_of::<LightsUniform>() * MAX_LIGHT_COUNT) as u64,
mapped_at_creation: false,
@ -126,7 +126,7 @@ impl LightUniformBuffers {
count: None,
}
],
label: Some("lights_bind_group_layout"),
label: Some("BGL_Lights"),
});
let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor {
@ -143,7 +143,7 @@ impl LightUniformBuffers {
)
}
],
label: Some("light_bind_group"),
label: Some("BG_Lights"),
});
let point_lights = LightBuffer::new(&bindgroup_layout, MAX_LIGHT_COUNT);
@ -199,6 +199,12 @@ pub struct PointLightUniform {
pub linear: f32,
/// The quadratic factor used in the quadratic attenuation calculation.
pub quadratic: f32,
pub ambient: f32,
pub diffuse: f32,
pub specular: f32,
pub _padding: u32,
}
impl PointLightUniform {
@ -213,6 +219,12 @@ impl PointLightUniform {
constant: light.constant,
linear: light.linear,
quadratic: light.quadratic,
ambient: light.ambient,
diffuse: light.diffuse,
specular: light.specular,
_padding: 0,
}
}
}

View File

@ -6,4 +6,7 @@ pub struct PointLight {
pub constant: f32,
pub linear: f32,
pub quadratic: f32,
pub ambient: f32,
pub diffuse: f32,
pub specular: f32,
}

View File

@ -24,4 +24,34 @@ impl Material {
shininess: 32.0,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, bytemuck::Pod, bytemuck::Zeroable)]
pub struct MaterialUniform {
pub ambient: glam::Vec4,
//pub _padding: u32,
pub diffuse: glam::Vec4,
//pub _padding2: u32,
pub specular: glam::Vec4,
//pub _padding3: u32,
pub shininess: f32,
pub _padding1: [u32; 3],
}
impl From<&Material> for MaterialUniform {
fn from(value: &Material) -> Self {
Self {
ambient: glam::Vec4::new(value.ambient.x, value.ambient.y, value.ambient.z, 0.0),
diffuse: glam::Vec4::new(value.diffuse.x, value.diffuse.y, value.diffuse.z, 0.0),
specular: glam::Vec4::new(value.specular.x, value.specular.y, value.specular.z, 0.0),
shininess: value.shininess,
_padding1: [0; 3]
/* _padding: 0,
_padding2: 0,
_padding3: 0,
_padding4: [0; 3], */
}
}
}

View File

@ -1,3 +1,7 @@
use std::{sync::Arc, num::NonZeroU32};
use wgpu::util::DeviceExt;
use super::{desc_buf_lay::DescVertexBufferLayout, vertex::Vertex};
#[allow(dead_code)]
@ -17,6 +21,215 @@ impl RenderBuffer {
}
}
pub struct BindGroupPair {
pub bindgroup: wgpu::BindGroup,
pub layout: Arc<wgpu::BindGroupLayout>,
}
impl BindGroupPair {
pub fn new_from_layout(device: &wgpu::Device, layout: Arc<wgpu::BindGroupLayout>, entries: &[wgpu::BindGroupEntry<'_>]) -> Self {
let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: layout.as_ref(),
entries,
label: None,
});
Self {
bindgroup,
layout,
}
}
}
pub struct BufferWrapper {
pub bindgroup_pair: Option<BindGroupPair>,
pub inner_buf: wgpu::Buffer,
pub len: usize,
}
impl BufferWrapper {
pub fn new_init(device: &wgpu::Device, descriptor: &wgpu::util::BufferInitDescriptor<'_>, bind_group: Option<BindGroupPair>) -> Self {
let buffer = device.create_buffer_init(descriptor);
Self {
bindgroup_pair: bind_group,
inner_buf: buffer,
len: 0,
}
}
pub fn new(device: &wgpu::Device, descriptor: &wgpu::BufferDescriptor<'_>, bind_group: Option<BindGroupPair>) -> Self {
let buffer = device.create_buffer(descriptor);
Self {
bindgroup_pair: bind_group,
inner_buf: buffer,
len: 0,
}
}
pub fn builder() -> BufferWrapperBuilder {
BufferWrapperBuilder::new()
}
}
#[derive(Default)]
pub struct BufferWrapperBuilder {
buffer_usage: Option<wgpu::BufferUsages>,
buffer_dynamic_offset: bool, // default false
label_prefix: Option<String>,
contents: Option<Vec<u8>>,
count: Option<u32>,
size: Option<u64>,
bind_group_pair: Option<BindGroupPair>,
bind_group_visibility: Option<wgpu::ShaderStages>,
}
impl BufferWrapperBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn buffer_usage(mut self, usages: wgpu::BufferUsages) -> Self {
self.buffer_usage = Some(usages);
self
}
pub fn buffer_dynamic_offset(mut self, val: bool) -> Self {
self.buffer_dynamic_offset = val;
self
}
pub fn visibility(mut self, val: wgpu::ShaderStages) -> Self {
self.bind_group_visibility = Some(val);
self
}
pub fn bind_group_pair(mut self, pair: BindGroupPair) -> Self {
self.bind_group_pair = Some(pair);
self
}
pub fn label_prefix(mut self, val: &str) -> Self {
self.label_prefix = Some(val.into());
self
}
pub fn contents<T>(mut self, val: &[T]) -> Self
where
T: bytemuck::NoUninit
{
self.contents = Some(bytemuck::cast_slice(val).to_vec());
self.count = if val.len() > 1 {
Some(val.len() as u32)
} else { None };
self
}
pub fn size(mut self, val: usize) -> Self {
self.size = Some(val as u64);
self
}
fn format_label(&self, prefix: &str) -> Option<String> {
match self.label_prefix.as_ref() {
Some(v) => Some(format!("{}{}", prefix, v)),
None => None
}
}
/// Finish building the BufferWrapper
///
/// You must specify a value for `buffer_usage`
///
/// If you did not provide a BindGroupPair with `BufferWrapperBuilder::bind_group_pair`,
/// one will be created for the buffer. A value for `visibility` is required.
/// You would need to provide `size` or `contents`:
/// * `size` - The size (in bytes) of the buffer.
/// * `contents` - The contents to initialize the buffer with.
///
/// If a field is missing, a panic will occur.
pub fn finish(self, device: &wgpu::Device) -> BufferWrapper {
let buf_usage = self.buffer_usage.expect("Buffer usage was not set");
let buffer = if let Some(contents) = self.contents.as_ref() {
device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: self.format_label("B_").as_deref(),
contents: bytemuck::cast_slice(contents.as_slice()),
usage: buf_usage,
}
)
} else {
device.create_buffer(
&wgpu::BufferDescriptor {
label: self.format_label("B_").as_deref(),
usage: buf_usage,
size: self.size.unwrap(),
mapped_at_creation: false,
}
)
};
let bg_pair = match self.bind_group_pair {
Some(v) => v,
None => {
let buffer_ty = {
let val;
if buf_usage.contains(wgpu::BufferUsages::UNIFORM) {
val = wgpu::BufferBindingType::Uniform;
} else if buf_usage.contains(wgpu::BufferUsages::STORAGE) {
val = wgpu::BufferBindingType::Storage { read_only: false }; // TODO: take in to see if its readonly
} else {
panic!("Unknown buffer binding type!");
}
val
};
let bg_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: self.bind_group_visibility.expect("Expected bind_group_visibility to be set!"),
ty: wgpu::BindingType::Buffer {
ty: buffer_ty,
has_dynamic_offset: self.buffer_dynamic_offset,
min_binding_size: None,
},
count: self.count.and_then(|v| NonZeroU32::try_from(v).ok()),
}
],
label: self.format_label("BGL_").as_deref(),
});
let bg_layout = Arc::new(bg_layout);
let bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bg_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}
],
label: self.format_label("BG_").as_deref(),
});
BindGroupPair {
bindgroup: bg,
layout: bg_layout,
}
}
};
BufferWrapper {
bindgroup_pair: Some(bg_pair),
inner_buf: buffer,
len: self.count.unwrap_or_default() as usize,
}
}
}
#[derive(Debug)]
pub struct BufferStorage {
buffer: wgpu::Buffer,

View File

@ -19,11 +19,14 @@ use crate::ecs::components::model::ModelComponent;
use crate::ecs::components::transform::TransformComponent;
use crate::math::{Transform, self};
use crate::render::light::PointLightUniform;
use crate::render::material::MaterialUniform;
use crate::render::render_buffer::{BufferWrapperBuilder, BindGroupPair};
use super::camera::{RenderCamera, CameraUniform};
use super::desc_buf_lay::DescVertexBufferLayout;
use super::light::{PointLight, LightUniformBuffers};
use super::material::Material;
use super::render_buffer::BufferWrapper;
use super::texture::RenderTexture;
use super::transform_buffer_storage::{TransformBufferIndices, TransformBuffers};
use super::vertex::Vertex;
@ -91,8 +94,7 @@ pub struct BasicRenderer {
default_texture_bind_group: BindGroup,
depth_buffer_texture: RenderTexture,
material_buffer: wgpu::Buffer,
material_bind_group: wgpu::BindGroup,
material_buffer: BufferWrapper,
light_buffers: LightUniformBuffers,
}
@ -127,7 +129,9 @@ impl BasicRenderer {
limits: if cfg!(target_arch = "wasm32") {
wgpu::Limits::downlevel_webgl2_defaults()
} else {
wgpu::Limits::default()
let mut v = wgpu::Limits::default();
v.max_bind_groups = 5;
v
},
label: None,
},
@ -251,6 +255,13 @@ impl BasicRenderer {
let light_uniform_buffers = LightUniformBuffers::new(&device);
let mat_buffer = BufferWrapperBuilder::new()
.buffer_usage(wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST)
.visibility(wgpu::ShaderStages::FRAGMENT)
.contents(&[MaterialUniform::default()])
//.size(mem::size_of::<MaterialUniform>())
.finish(&device);
let mut s = Self {
window,
surface,
@ -282,6 +293,7 @@ impl BasicRenderer {
entity_last_transforms: HashMap::new(),
light_buffers: light_uniform_buffers,
material_buffer: mat_buffer,
};
// create the default pipelines
@ -289,7 +301,7 @@ impl BasicRenderer {
pipelines.insert(0, Arc::new(FullRenderPipeline::new(&s.device, &s.config, &shader,
vec![super::vertex::Vertex::desc(),],
vec![&s.texture_bind_group_layout, &s.transform_buffers.bindgroup_layout, &camera_bind_group_layout,
&s.light_buffers.bindgroup_layout])));
&s.light_buffers.bindgroup_layout, &s.material_buffer.bindgroup_pair.as_ref().unwrap().layout])));
s.render_pipelines = pipelines;
s
@ -384,8 +396,8 @@ impl BasicRenderer {
fn create_mesh_buffers(&mut self, mesh: &Mesh, transform_indices: TransformBufferIndices) -> MeshBufferStorage {
let (vertex_buffer, buffer_indices) = self.create_vertex_index_buffers(mesh);
let material = Material::from_resource(&self.device, &self.queue, &mesh.material());
let diffuse_bindgroup = if let Some(model_texture) = &mesh.material().base_color_texture {
let material = Material::from_resource(&self.device, &self.queue, &mesh.material());
let diffuse_texture = &material.diffuse_texture;
let diffuse_bind_group = self.device.create_bind_group(
@ -410,10 +422,15 @@ impl BasicRenderer {
None
};
//let mat = Material::from_resource(&self.device, &self.queue, )
let uni = MaterialUniform::from(&material);
self.queue.write_buffer(&self.material_buffer.inner_buf, 0, bytemuck::bytes_of(&uni));
debug!("Wrote material to buffer");
MeshBufferStorage {
buffer_vertex: vertex_buffer,
buffer_indices,
material: None,
material: Some(material),
texture_bindgroup: diffuse_bindgroup,
}
}
@ -427,6 +444,9 @@ impl BasicRenderer {
let indices = self.transform_buffers.update_or_insert(&self.queue, &self.render_limits,
entity, || ( transform.calculate_mat4(), glam::Mat3::from_quat(transform.rotation) ));
//let mat = Material::from_resource(&self.device, &self.queue, )
//self.queue.write_buffer(&self.material_buffer.inner_buf, 0, bytemuck::bytes_of(t))
#[allow(clippy::map_entry)]
if !self.mesh_buffers.contains_key(&mesh.uuid) {
// create the mesh's buffers
@ -587,6 +607,8 @@ impl Renderer for BasicRenderer {
// bind light
//render_pass.set_bind_group(3, &self.point_light_bind_group, &[]);
render_pass.set_bind_group(3, &self.light_buffers.bindgroup, &[]);
render_pass.set_bind_group(4, &self.material_buffer.bindgroup_pair.as_ref().unwrap().bindgroup, &[]);
////self.light_buffers.bind_lights(&mut render_pass, 3);

View File

@ -1,6 +1,6 @@
// Vertex shader
const max_light_count: u32 = 32u;
const max_light_count: u32 = 16u;
struct VertexInput {
@location(0) position: vec3<f32>,
@ -23,10 +23,15 @@ struct CameraUniform {
struct PointLight {
position: vec4<f32>,
color: vec4<f32>,
intensity: f32,
constant: f32,
linear: f32,
quadratic: f32,
ambient: f32,
diffuse: f32,
specular: f32,
};
struct Lights {
@ -65,9 +70,9 @@ fn vs_main(
// Fragment shader
struct Material {
ambient: vec3<f32>,
diffuse: vec3<f32>,
specular: vec3<f32>,
ambient: vec4<f32>,
diffuse: vec4<f32>,
specular: vec4<f32>,
shininess: f32,
}
@ -77,7 +82,7 @@ var t_diffuse: texture_2d<f32>;
var s_diffuse: sampler;
@group(4) @binding(0)
var u_material: Material;
var<uniform> u_material: Material;
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
@ -99,13 +104,13 @@ 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;
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);
var diffuse_color = light_color * (diffuse_strength * material.diffuse.xyz);
//// end of diffuse ////
//// specular ////
@ -113,7 +118,7 @@ fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_li
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);
var specular_color = specular_strength * (light_color * material.specular.xyz);
//// end of specular ////
//// point light attenuation ////
@ -121,9 +126,9 @@ fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_li
let attenuation = 1.0 / (point_light.constant + point_light.linear * distance +
point_light.quadratic * (distance * distance));
ambient_color *= attenuation * point_light.intensity;
diffuse_color *= attenuation * point_light.intensity;
specular_color *= attenuation * point_light.intensity;
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);