@ -13,8 +13,9 @@ use legion::*;
use rapier3d ::parry ::motion ::RigidMotionComposition ;
use wgpu ::util ::DeviceExt ;
use wgpu ::{
BackendBit , BindGroup , BindGroupLayout , Buffer , Device , Instance , Queue , Surface , SwapChain ,
SwapChainDescriptor , SwapChainFrame , TextureView ,
BackendBit , BindGroup , BindGroupLayout , Buffer , BufferBindingType , Device , FragmentState ,
Instance , Queue , Surface , SwapChain , SwapChainDescriptor , SwapChainFrame , TextureView ,
VertexState ,
} ;
use winit ::dpi ::PhysicalSize ;
use winit ::platform ::unix ::x11 ::ffi ::Time ;
@ -160,6 +161,7 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
encoder . insert_debug_marker ( "render entities" ) ;
let mut pass = encoder . begin_render_pass ( & wgpu ::RenderPassDescriptor {
label : Some ( "render pass" ) ,
color_attachments : & [ ] ,
depth_stencil_attachment : Some ( wgpu ::RenderPassDepthStencilAttachmentDescriptor {
attachment : & light . target_view ,
@ -175,7 +177,8 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
for mesh in & mesh_stack {
pass . set_bind_group ( 1 , & mesh . bind_group , & [ ] ) ;
pass . set_index_buffer ( mesh . index_buffer . slice ( .. ) ) ;
// TODO, pipe through this index format through the mesh
pass . set_index_buffer ( mesh . index_buffer . slice ( .. ) , mesh . index_format ) ;
pass . set_vertex_buffer ( 0 , mesh . vertex_buffer . slice ( .. ) ) ;
pass . draw_indexed ( 0 .. mesh . index_count as u32 , 0 , 0 .. 1 ) ;
}
@ -185,6 +188,7 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
encoder . push_debug_group ( "forward rendering pass" ) ;
{
let mut pass = encoder . begin_render_pass ( & wgpu ::RenderPassDescriptor {
label : Some ( "forward render pass" ) ,
color_attachments : & [ wgpu ::RenderPassColorAttachmentDescriptor {
attachment : & frame . output . view ,
resolve_target : None ,
@ -214,7 +218,8 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
for ( pos , mesh , color ) in query . iter_mut ( world ) {
pass . set_bind_group ( 1 , & mesh . bind_group , & [ ] ) ;
pass . set_index_buffer ( mesh . index_buffer . slice ( .. ) ) ;
// TODO: Pipe this in through the mesh
pass . set_index_buffer ( mesh . index_buffer . slice ( .. ) , mesh . index_format ) ;
pass . set_vertex_buffer ( 0 , mesh . vertex_buffer . slice ( .. ) ) ;
pass . draw_indexed ( 0 .. mesh . index_count as u32 , 0 , 0 .. 1 ) ;
}
@ -355,25 +360,33 @@ impl Renderer {
let index_count = indices . len ( ) ;
let ( vertex_buf , index_buf ) = Renderer ::create_buffer ( & self . device , indices , vertices ) ;
let uniform_size = mem ::size_of ::< EntityUniforms > ( ) as wgpu ::BufferAddress ;
let uniform_buf = Arc ::new ( self . device . create_buffer ( & wgpu ::BufferDescriptor {
label : Some ( "Mesh Uniform Buf" ) ,
size : mem::size_of ::< EntityUniforms > ( ) as wgpu ::BufferAddress ,
size : uniform_size ,
usage : wgpu ::BufferUsage ::UNIFORM | wgpu ::BufferUsage ::COPY_DST ,
mapped_at_creation : false ,
} ) ) ;
let bind_group = Arc ::new ( self . device . create_bind_group ( & wgpu ::BindGroupDescriptor {
label : Some ( "Mesh Bind Group" ) ,
layout : & self . entity_bind_group_layout ,
entries : & [ wgpu ::BindGroupEntry {
binding : 0 ,
resource : wgpu ::BindingResource ::Buffer ( uniform_buf . slice ( .. ) ) ,
resource : wgpu ::BindingResource ::Buffer {
buffer : & uniform_buf ,
offset : 0 ,
size : wgpu ::BufferSize ::new ( uniform_size ) ,
} ,
} ] ,
label : Some ( "Mesh Bind Group" ) ,
} ) ) ;
Mesh {
index_buffer : index_buf ,
index_count : index_count ,
// TODO: This is hardcoded by tobj, maybe think about doing something a little more clever?
index_format : wgpu ::IndexFormat ::Uint32 ,
vertex_buffer : vertex_buf ,
uniform_buffer : uniform_buf ,
bind_group : bind_group ,
@ -407,9 +420,9 @@ impl Renderer {
// And then get the device we want
let device = adapter . request_device (
& wgpu ::DeviceDescriptor {
label : Some ( "device descriptor" ) ,
features : ( optional_features & adapter_features ) | required_features ,
limits : needed_limits ,
shader_validation : true ,
} ,
trace_dir . ok ( ) . as_ref ( ) . map ( std ::path ::Path ::new ) ,
) ;
@ -421,7 +434,7 @@ impl Renderer {
let mut sc_desc = ( wgpu ::SwapChainDescriptor {
// Allows a texture to be a output attachment of a renderpass.
usage : wgpu ::TextureUsage ::OUTPUT _ATTACHMENT,
usage : wgpu ::TextureUsage ::RENDER _ATTACHMENT,
format : if cfg! ( target_arch = "wasm32" ) {
wgpu ::TextureFormat ::Bgra8Unorm
} else {
@ -442,8 +455,8 @@ impl Renderer {
// I wanted to get tricky with the 0,1 types
let vertex_size = mem ::size_of ::< Vertex > ( ) ;
let vertex_attr = wgpu ::vertex_attr_array ! [ 0 = > Float4 , 1 = > Float4 ] ;
let vb_desc = wgpu ::VertexBuffer Descriptor {
stride: vertex_size as wgpu ::BufferAddress ,
let vb_desc = wgpu ::VertexBuffer Layout {
array_ stride: vertex_size as wgpu ::BufferAddress ,
step_mode : wgpu ::InputStepMode ::Vertex ,
attributes : & vertex_attr ,
} ;
@ -456,11 +469,12 @@ impl Renderer {
binding : 0 ,
visibility : wgpu ::ShaderStage ::VERTEX | wgpu ::ShaderStage ::FRAGMENT ,
count : None ,
ty : wgpu ::BindingType ::Uniform Buffer {
dynamic: false ,
ty : wgpu ::BindingType :: Buffer {
ty: wgpu ::BufferBindingType ::Uniform ,
min_binding_size : wgpu ::BufferSize ::new (
mem ::size_of ::< EntityUniforms > ( ) as _
) ,
has_dynamic_offset : false ,
} ,
} ] ,
} ) ;
@ -480,9 +494,10 @@ impl Renderer {
entries : & [ wgpu ::BindGroupLayoutEntry {
binding : 0 , // global
visibility : wgpu ::ShaderStage ::VERTEX ,
ty : wgpu ::BindingType ::Uniform Buffer {
dynamic: false ,
ty : wgpu ::BindingType :: Buffer {
ty: wgpu ::BufferBindingType ::Uniform ,
min_binding_size : wgpu ::BufferSize ::new ( uniform_size ) ,
has_dynamic_offset : false ,
} ,
count : None ,
} ] ,
@ -508,51 +523,56 @@ impl Renderer {
layout : & bind_group_layout ,
entries : & [ wgpu ::BindGroupEntry {
binding : 0 ,
resource : wgpu ::BindingResource ::Buffer ( uniform_buf . slice ( .. ) ) ,
resource : wgpu ::BindingResource ::Buffer {
buffer : & uniform_buf ,
offset : 0 ,
size : wgpu ::BufferSize ::new ( uniform_size ) ,
} ,
} ] ,
label : Some ( "Shadow uniform bind group" ) ,
} ) ;
// Create the render pipeline
let vs_module =
device . create_shader_module ( wgpu ::include_spirv ! ( "../resources/bake.vert.spv" ) ) ;
device . create_shader_module ( & wgpu ::include_spirv ! ( "../resources/bake.vert.spv" ) ) ;
let fs_module =
device . create_shader_module ( wgpu ::include_spirv ! ( "../resources/bake.frag.spv" ) ) ;
device . create_shader_module ( & wgpu ::include_spirv ! ( "../resources/bake.frag.spv" ) ) ;
let pipeline = device . create_render_pipeline ( & wgpu ::RenderPipelineDescriptor {
label : Some ( "shadow" ) ,
layout : Some ( & pipeline_layout ) ,
vertex_stage : wgpu ::ProgrammableStageDescriptor {
vertex : VertexState {
module : & vs_module ,
entry_point : "main" ,
buffers : & [ vb_desc . clone ( ) ] ,
} ,
fragment _stage: Some ( wgpu ::ProgrammableStageDescriptor {
fragment : Some ( FragmentState {
module : & fs_module ,
entry_point : "main" ,
targets : & [ ] ,
} ) ,
rasterization_state : Some ( wgpu ::RasterizationStateDescriptor {
primitive : wgpu ::PrimitiveState {
topology : wgpu ::PrimitiveTopology ::TriangleList ,
front_face : wgpu ::FrontFace ::Ccw ,
cull_mode : wgpu ::CullMode ::Back ,
depth_bias : 2 , // corresponds to bilinear filtering
depth_bias_slope_scale : 2.0 ,
depth_bias_clamp : 0.0 ,
clamp_depth : device . features ( ) . contains ( wgpu ::Features ::DEPTH_CLAMPING ) ,
} ) ,
primitive_topology : wgpu ::PrimitiveTopology ::TriangleList ,
color_states : & [ ] ,
depth_stencil_state : Some ( wgpu ::DepthStencilStateDescriptor {
.. Default ::default ( )
} ,
depth_stencil : Some ( wgpu ::DepthStencilState {
format : Self ::SHADOW_FORMAT ,
depth_write_enabled : true ,
depth_compare : wgpu ::CompareFunction ::LessEqual ,
stencil : wgpu ::StencilStateDescriptor ::default ( ) ,
stencil : wgpu ::StencilState ::default ( ) ,
bias : wgpu ::DepthBiasState {
constant : 2 , // corresponds to bilinear filtering
slope_scale : 2.0 ,
clamp : 0.0 ,
} ,
clamp_depth : device . features ( ) . contains (
wgpu ::Features ::DEPTH_CLAMPING
) ,
} ) ,
vertex_state : wgpu ::VertexStateDescriptor {
index_format : wgpu ::IndexFormat ::Uint32 ,
vertex_buffers : & [ vb_desc . clone ( ) ] ,
} ,
sample_count : 1 ,
sample_mask : ! 0 ,
alpha_to_coverage_enabled : false ,
multisample : wgpu ::MultisampleState ::default ( ) ,
} ) ;
Pass {
@ -581,7 +601,7 @@ impl Renderer {
sample_count : 1 ,
dimension : wgpu ::TextureDimension ::D2 ,
format : Self ::SHADOW_FORMAT ,
usage : wgpu ::TextureUsage ::OUTPUT _ATTACHMENT | wgpu ::TextureUsage ::SAMPLED ,
usage : wgpu ::TextureUsage ::RENDER _ATTACHMENT | wgpu ::TextureUsage ::SAMPLED ,
label : Some ( "Shadow texture" ) ,
} ) ;
@ -615,39 +635,44 @@ impl Renderer {
wgpu ::BindGroupLayoutEntry {
binding : 0 , // global
visibility : wgpu ::ShaderStage ::VERTEX | wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::Uniform Buffer {
dynamic: false ,
ty : wgpu ::BindingType :: Buffer {
ty: wgpu ::BufferBindingType ::Uniform ,
min_binding_size : wgpu ::BufferSize ::new ( mem ::size_of ::<
ForwardUniforms ,
> (
)
as _ ) ,
has_dynamic_offset : false ,
} ,
count : None ,
} ,
wgpu ::BindGroupLayoutEntry {
binding : 1 , // lights
visibility : wgpu ::ShaderStage ::VERTEX | wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::Uniform Buffer {
dynamic: false ,
ty : wgpu ::BindingType :: Buffer {
ty: BufferBindingType ::Uniform ,
min_binding_size : wgpu ::BufferSize ::new ( light_uniform_size ) ,
has_dynamic_offset : false ,
} ,
count : None ,
} ,
wgpu ::BindGroupLayoutEntry {
binding : 2 ,
visibility : wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::Sampled Texture {
ty : wgpu ::BindingType :: Texture {
multisampled : false ,
component_type: wgpu ::TextureComponentType ::Float ,
dimension: wgpu ::TextureViewDimension ::D2Array ,
sample_type: wgpu ::TextureSampleType ::Depth ,
view_ dimension: wgpu ::TextureViewDimension ::D2Array ,
} ,
count : None ,
} ,
wgpu ::BindGroupLayoutEntry {
binding : 3 ,
visibility : wgpu ::ShaderStage ::FRAGMENT ,
ty : wgpu ::BindingType ::Sampler { comparison : true } ,
ty : wgpu ::BindingType ::Sampler {
filtering : false ,
comparison : true ,
} ,
count : None ,
} ,
] ,
@ -687,17 +712,29 @@ impl Renderer {
let shadow_view = shadow_texture . create_view ( & wgpu ::TextureViewDescriptor ::default ( ) ) ;
let forward_uniform_size =
wgpu ::BufferSize ::new ( mem ::size_of ::< ForwardUniforms > ( ) as wgpu ::BufferAddress ) ;
let light_uniform_size = wgpu ::BufferSize ::new ( light_uniform_size ) ;
// Create bind group
let bind_group = device . create_bind_group ( & wgpu ::BindGroupDescriptor {
layout : & bind_group_layout ,
entries : & [
wgpu ::BindGroupEntry {
binding : 0 ,
resource : wgpu ::BindingResource ::Buffer ( uniform_buf . slice ( .. ) ) ,
resource : wgpu ::BindingResource ::Buffer {
buffer : & uniform_buf ,
offset : 0 ,
size : forward_uniform_size ,
} ,
} ,
wgpu ::BindGroupEntry {
binding : 1 ,
resource : wgpu ::BindingResource ::Buffer ( light_uniform_buf . slice ( .. ) ) ,
resource : wgpu ::BindingResource ::Buffer {
buffer : & light_uniform_buf ,
offset : 0 ,
size : light_uniform_size ,
} ,
} ,
wgpu ::BindGroupEntry {
binding : 2 ,
@ -713,41 +750,37 @@ impl Renderer {
// Create the render pipeline
let vs_module =
device . create_shader_module ( wgpu ::include_spirv ! ( "../resources/forward.vert.spv" ) ) ;
device . create_shader_module ( & wgpu ::include_spirv ! ( "../resources/forward.vert.spv" ) ) ;
let fs_module =
device . create_shader_module ( wgpu ::include_spirv ! ( "../resources/forward.frag.spv" ) ) ;
device . create_shader_module ( & wgpu ::include_spirv ! ( "../resources/forward.frag.spv" ) ) ;
let pipeline = device . create_render_pipeline ( & wgpu ::RenderPipelineDescriptor {
label : Some ( "main" ) ,
layout : Some ( & pipeline_layout ) ,
vertex _stage: wgpu ::ProgrammableStageDescriptor {
vertex : VertexState {
module : & vs_module ,
entry_point : "main" ,
buffers : & [ vb_desc ] ,
} ,
fragment _stage: Some ( wgpu ::ProgrammableStageDescriptor {
fragment : Some ( FragmentState {
module : & fs_module ,
entry_point : "main" ,
targets : & [ sc_desc . format . into ( ) ] ,
} ) ,
rasterization_state: Some ( wgpu ::RasterizationStateDescriptor {
primitive: wgpu ::PrimitiveState {
front_face : wgpu ::FrontFace ::Ccw ,
cull_mode : wgpu ::CullMode ::Back ,
.. Default ::default ( )
} ) ,
primitive_topology : wgpu ::PrimitiveTopology ::TriangleList ,
color_states : & [ sc_desc . format . into ( ) ] ,
depth_stencil_state : Some ( wgpu ::DepthStencilStateDescriptor {
} ,
depth_stencil : Some ( wgpu ::DepthStencilState {
format : Self ::DEPTH_FORMAT ,
depth_write_enabled : true ,
depth_compare : wgpu ::CompareFunction ::Less ,
stencil : wgpu ::StencilStateDescriptor ::default ( ) ,
stencil : wgpu ::StencilState ::default ( ) ,
bias : wgpu ::DepthBiasState ::default ( ) ,
clamp_depth : false ,
} ) ,
vertex_state : wgpu ::VertexStateDescriptor {
index_format : wgpu ::IndexFormat ::Uint32 ,
vertex_buffers : & [ vb_desc ] ,
} ,
sample_count : 1 ,
sample_mask : ! 0 ,
alpha_to_coverage_enabled : false ,
multisample : Default ::default ( ) ,
} ) ;
Pass {
@ -767,7 +800,7 @@ impl Renderer {
sample_count : 1 ,
dimension : wgpu ::TextureDimension ::D2 ,
format : Self ::DEPTH_FORMAT ,
usage : wgpu ::TextureUsage ::OUTPUT _ATTACHMENT,
usage : wgpu ::TextureUsage ::RENDER _ATTACHMENT,
label : Some ( "Depth Texture" ) ,
} ) ;
@ -825,7 +858,7 @@ impl Renderer {
sample_count : 1 ,
dimension : wgpu ::TextureDimension ::D2 ,
format : Self ::DEPTH_FORMAT ,
usage : wgpu ::TextureUsage ::OUTPUT _ATTACHMENT,
usage : wgpu ::TextureUsage ::RENDER _ATTACHMENT,
label : Some ( "Depth Texture" ) ,
} ) ;
self . forward_depth = depth_texture . create_view ( & wgpu ::TextureViewDescriptor ::default ( ) ) ;