dynamic uniform offsets
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
use crate::texture::{DitherTextures, FlowmapTexture};
|
use crate::texture::{DitherTextures, FlowmapTexture};
|
||||||
|
use std::num::NonZeroU64;
|
||||||
|
|
||||||
|
use super::types::Uniforms;
|
||||||
use super::Renderer;
|
use super::Renderer;
|
||||||
|
|
||||||
impl Renderer
|
impl Renderer
|
||||||
@@ -24,7 +26,11 @@ impl Renderer
|
|||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: uniform_buffer.as_entire_binding(),
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||||
|
buffer: uniform_buffer,
|
||||||
|
offset: 0,
|
||||||
|
size: NonZeroU64::new(std::mem::size_of::<Uniforms>() as u64),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
|
|||||||
@@ -102,8 +102,7 @@ impl DebugOverlay
|
|||||||
cache: None,
|
cache: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let pipeline_snow_light =
|
let pipeline_snow_light = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
||||||
label: Some("Snow Light Debug Pipeline"),
|
label: Some("Snow Light Debug Pipeline"),
|
||||||
layout: Some(&snow_light_layout),
|
layout: Some(&snow_light_layout),
|
||||||
vertex: wgpu::VertexState {
|
vertex: wgpu::VertexState {
|
||||||
|
|||||||
@@ -6,12 +6,19 @@ mod types;
|
|||||||
|
|
||||||
pub use types::{DrawCall, Pipeline, Spotlight, SpotlightRaw, Uniforms, MAX_SPOTLIGHTS};
|
pub use types::{DrawCall, Pipeline, Spotlight, SpotlightRaw, Uniforms, MAX_SPOTLIGHTS};
|
||||||
|
|
||||||
|
use crate::entity::EntityHandle;
|
||||||
|
|
||||||
use crate::debug::DebugMode;
|
use crate::debug::DebugMode;
|
||||||
use crate::postprocess::{create_blit_pipeline, create_fullscreen_quad, LowResFramebuffer};
|
use crate::postprocess::{create_blit_pipeline, create_fullscreen_quad, LowResFramebuffer};
|
||||||
use crate::texture::{DitherTextures, FlowmapTexture};
|
use crate::texture::{DitherTextures, FlowmapTexture};
|
||||||
use pipeline::{create_debug_lines_pipeline, create_main_pipeline, create_snow_clipmap_pipeline,
|
use pipeline::{
|
||||||
create_wireframe_pipeline};
|
create_debug_lines_pipeline, create_main_pipeline, create_snow_clipmap_pipeline,
|
||||||
|
create_wireframe_pipeline,
|
||||||
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::num::NonZeroU64;
|
||||||
|
|
||||||
|
const MAX_DRAW_CALLS: usize = 64;
|
||||||
|
|
||||||
pub struct Renderer
|
pub struct Renderer
|
||||||
{
|
{
|
||||||
@@ -62,6 +69,8 @@ pub struct Renderer
|
|||||||
|
|
||||||
snow_light_accumulation: Option<crate::snow_light::SnowLightAccumulation>,
|
snow_light_accumulation: Option<crate::snow_light::SnowLightAccumulation>,
|
||||||
snow_light_bound: bool,
|
snow_light_bound: bool,
|
||||||
|
|
||||||
|
pub selected_entity: Option<EntityHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer
|
impl Renderer
|
||||||
@@ -90,8 +99,9 @@ impl Renderer
|
|||||||
.await
|
.await
|
||||||
.map_err(|_| "Failed to find adapter")?;
|
.map_err(|_| "Failed to find adapter")?;
|
||||||
|
|
||||||
let wireframe_supported =
|
let wireframe_supported = adapter
|
||||||
adapter.features().contains(wgpu::Features::POLYGON_MODE_LINE);
|
.features()
|
||||||
|
.contains(wgpu::Features::POLYGON_MODE_LINE);
|
||||||
let required_features = if wireframe_supported
|
let required_features = if wireframe_supported
|
||||||
{
|
{
|
||||||
wgpu::Features::POLYGON_MODE_LINE
|
wgpu::Features::POLYGON_MODE_LINE
|
||||||
@@ -129,7 +139,7 @@ impl Renderer
|
|||||||
|
|
||||||
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: Some("Uniform Buffer"),
|
label: Some("Uniform Buffer"),
|
||||||
size: std::mem::size_of::<Uniforms>() as wgpu::BufferAddress,
|
size: (std::mem::size_of::<Uniforms>() * MAX_DRAW_CALLS) as wgpu::BufferAddress,
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
@@ -306,8 +316,8 @@ impl Renderer
|
|||||||
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
|
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
|
||||||
ty: wgpu::BindingType::Buffer {
|
ty: wgpu::BindingType::Buffer {
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
has_dynamic_offset: false,
|
has_dynamic_offset: true,
|
||||||
min_binding_size: None,
|
min_binding_size: NonZeroU64::new(std::mem::size_of::<Uniforms>() as u64),
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
},
|
},
|
||||||
@@ -463,15 +473,22 @@ impl Renderer
|
|||||||
|
|
||||||
let wireframe_pipeline = if wireframe_supported
|
let wireframe_pipeline = if wireframe_supported
|
||||||
{
|
{
|
||||||
Some(create_wireframe_pipeline(&device, config.format, &bind_group_layout))
|
Some(create_wireframe_pipeline(
|
||||||
|
&device,
|
||||||
|
config.format,
|
||||||
|
&bind_group_layout,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let debug_lines_pipeline =
|
let debug_lines_pipeline = Some(create_debug_lines_pipeline(
|
||||||
Some(create_debug_lines_pipeline(&device, config.format, &bind_group_layout));
|
&device,
|
||||||
|
config.format,
|
||||||
|
&bind_group_layout,
|
||||||
|
));
|
||||||
|
|
||||||
let debug_overlay = Some(debug_overlay::DebugOverlay::new(&device, config.format));
|
let debug_overlay = Some(debug_overlay::DebugOverlay::new(&device, config.format));
|
||||||
|
|
||||||
@@ -533,6 +550,7 @@ impl Renderer
|
|||||||
dummy_snow_light_sampler,
|
dummy_snow_light_sampler,
|
||||||
snow_light_accumulation: None,
|
snow_light_accumulation: None,
|
||||||
snow_light_bound: false,
|
snow_light_bound: false,
|
||||||
|
selected_entity: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,6 +603,9 @@ impl Renderer
|
|||||||
label: Some("Render Encoder"),
|
label: Some("Render Encoder"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let uniform_size = std::mem::size_of::<Uniforms>() as u64;
|
||||||
|
let mut uniform_slot: u64 = 0;
|
||||||
|
|
||||||
for (i, draw_call) in draw_calls.iter().enumerate()
|
for (i, draw_call) in draw_calls.iter().enumerate()
|
||||||
{
|
{
|
||||||
let uniforms = Uniforms::new(
|
let uniforms = Uniforms::new(
|
||||||
@@ -603,8 +624,15 @@ impl Renderer
|
|||||||
&self.spotlights,
|
&self.spotlights,
|
||||||
debug_mode.as_u32(),
|
debug_mode.as_u32(),
|
||||||
);
|
);
|
||||||
self.queue
|
|
||||||
.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]));
|
let offset = uniform_slot * uniform_size;
|
||||||
|
uniform_slot += 1;
|
||||||
|
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.uniform_buffer,
|
||||||
|
offset,
|
||||||
|
bytemuck::cast_slice(&[uniforms]),
|
||||||
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
@@ -660,7 +688,7 @@ impl Renderer
|
|||||||
.unwrap_or(&self.standard_pipeline),
|
.unwrap_or(&self.standard_pipeline),
|
||||||
};
|
};
|
||||||
render_pass.set_pipeline(pipeline);
|
render_pass.set_pipeline(pipeline);
|
||||||
render_pass.set_bind_group(0, &self.bind_group, &[]);
|
render_pass.set_bind_group(0, &self.bind_group, &[offset as u32]);
|
||||||
|
|
||||||
if let Some(ref displacement_bind_group) = draw_call.displacement_bind_group
|
if let Some(ref displacement_bind_group) = draw_call.displacement_bind_group
|
||||||
{
|
{
|
||||||
@@ -686,7 +714,10 @@ impl Renderer
|
|||||||
{
|
{
|
||||||
for draw_call in draw_calls.iter()
|
for draw_call in draw_calls.iter()
|
||||||
{
|
{
|
||||||
if matches!(draw_call.pipeline, Pipeline::SnowClipmap | Pipeline::DebugLines)
|
if matches!(
|
||||||
|
draw_call.pipeline,
|
||||||
|
Pipeline::SnowClipmap | Pipeline::DebugLines
|
||||||
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -707,9 +738,11 @@ impl Renderer
|
|||||||
&self.spotlights,
|
&self.spotlights,
|
||||||
4,
|
4,
|
||||||
);
|
);
|
||||||
|
let wire_offset = uniform_slot * uniform_size;
|
||||||
|
uniform_slot += 1;
|
||||||
self.queue.write_buffer(
|
self.queue.write_buffer(
|
||||||
&self.uniform_buffer,
|
&self.uniform_buffer,
|
||||||
0,
|
wire_offset,
|
||||||
bytemuck::cast_slice(&[uniforms]),
|
bytemuck::cast_slice(&[uniforms]),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -742,7 +775,7 @@ impl Renderer
|
|||||||
});
|
});
|
||||||
|
|
||||||
wire_pass.set_pipeline(wireframe_pipeline);
|
wire_pass.set_pipeline(wireframe_pipeline);
|
||||||
wire_pass.set_bind_group(0, &self.bind_group, &[]);
|
wire_pass.set_bind_group(0, &self.bind_group, &[wire_offset as u32]);
|
||||||
wire_pass.set_vertex_buffer(0, draw_call.vertex_buffer.slice(..));
|
wire_pass.set_vertex_buffer(0, draw_call.vertex_buffer.slice(..));
|
||||||
|
|
||||||
if let Some(ref instance_buffer) = draw_call.instance_buffer
|
if let Some(ref instance_buffer) = draw_call.instance_buffer
|
||||||
@@ -764,6 +797,99 @@ impl Renderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(selected) = self.selected_entity
|
||||||
|
{
|
||||||
|
if let Some(ref wireframe_pipeline) = self.wireframe_pipeline
|
||||||
|
{
|
||||||
|
for draw_call in draw_calls.iter()
|
||||||
|
{
|
||||||
|
if draw_call.entity != Some(selected)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(
|
||||||
|
draw_call.pipeline,
|
||||||
|
Pipeline::SnowClipmap | Pipeline::DebugLines
|
||||||
|
)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uniforms = Uniforms::new(
|
||||||
|
draw_call.model,
|
||||||
|
*view,
|
||||||
|
*projection,
|
||||||
|
&light_view_projections,
|
||||||
|
camera_position,
|
||||||
|
player_position,
|
||||||
|
self.terrain_height_scale,
|
||||||
|
time,
|
||||||
|
self.shadow_bias,
|
||||||
|
draw_call.tile_scale,
|
||||||
|
draw_call.enable_dissolve,
|
||||||
|
draw_call.enable_snow_light,
|
||||||
|
&self.spotlights,
|
||||||
|
4,
|
||||||
|
);
|
||||||
|
let sel_offset = uniform_slot * uniform_size;
|
||||||
|
uniform_slot += 1;
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.uniform_buffer,
|
||||||
|
sel_offset,
|
||||||
|
bytemuck::cast_slice(&[uniforms]),
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut sel_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: Some("Selection Wireframe Pass"),
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &self.framebuffer.view,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Load,
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
},
|
||||||
|
depth_slice: None,
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: Some(
|
||||||
|
wgpu::RenderPassDepthStencilAttachment {
|
||||||
|
view: &self.framebuffer.depth_view,
|
||||||
|
depth_ops: Some(wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Load,
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
}),
|
||||||
|
stencil_ops: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
timestamp_writes: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
multiview_mask: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
sel_pass.set_pipeline(wireframe_pipeline);
|
||||||
|
sel_pass.set_bind_group(0, &self.bind_group, &[sel_offset as u32]);
|
||||||
|
sel_pass.set_vertex_buffer(0, draw_call.vertex_buffer.slice(..));
|
||||||
|
|
||||||
|
if let Some(ref instance_buffer) = draw_call.instance_buffer
|
||||||
|
{
|
||||||
|
sel_pass.set_vertex_buffer(1, instance_buffer.slice(..));
|
||||||
|
}
|
||||||
|
|
||||||
|
sel_pass.set_index_buffer(
|
||||||
|
draw_call.index_buffer.slice(..),
|
||||||
|
wgpu::IndexFormat::Uint32,
|
||||||
|
);
|
||||||
|
sel_pass.draw_indexed(
|
||||||
|
0..draw_call.num_indices,
|
||||||
|
0,
|
||||||
|
0..draw_call.num_instances,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if debug_mode == DebugMode::ShadowMap
|
if debug_mode == DebugMode::ShadowMap
|
||||||
{
|
{
|
||||||
if let Some(ref overlay) = self.debug_overlay
|
if let Some(ref overlay) = self.debug_overlay
|
||||||
@@ -1074,3 +1200,12 @@ pub fn update_spotlights(spotlights: Vec<Spotlight>)
|
|||||||
renderer.spotlights = spotlights;
|
renderer.spotlights = spotlights;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_selected_entity(entity: Option<EntityHandle>)
|
||||||
|
{
|
||||||
|
GLOBAL_RENDERER.with(|r| {
|
||||||
|
let mut renderer = r.borrow_mut();
|
||||||
|
let renderer = renderer.as_mut().expect("Renderer not set");
|
||||||
|
renderer.selected_entity = entity;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
|
|
||||||
|
use crate::entity::EntityHandle;
|
||||||
|
|
||||||
pub const MAX_SPOTLIGHTS: usize = 4;
|
pub const MAX_SPOTLIGHTS: usize = 4;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -156,4 +158,5 @@ pub struct DrawCall
|
|||||||
pub enable_dissolve: bool,
|
pub enable_dissolve: bool,
|
||||||
pub enable_snow_light: bool,
|
pub enable_snow_light: bool,
|
||||||
pub displacement_bind_group: Option<wgpu::BindGroup>,
|
pub displacement_bind_group: Option<wgpu::BindGroup>,
|
||||||
|
pub entity: Option<EntityHandle>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ pub fn render_system(world: &World) -> Vec<DrawCall>
|
|||||||
enable_dissolve: mesh_component.enable_dissolve,
|
enable_dissolve: mesh_component.enable_dissolve,
|
||||||
enable_snow_light: mesh_component.enable_snow_light,
|
enable_snow_light: mesh_component.enable_snow_light,
|
||||||
displacement_bind_group: None,
|
displacement_bind_group: None,
|
||||||
|
entity: Some(entity),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
Reference in New Issue
Block a user