Disable shadowmapping on WebGL
This commit is contained in:
parent
2616b2f5c9
commit
ccaf9261cc
7 changed files with 67 additions and 45 deletions
|
@ -5,6 +5,7 @@ A small [wgpu](https://github.com/gfx-rs/wgpu) renderer written in [Rust](https:
|
||||||
## Try it out
|
## Try it out
|
||||||
[rasanen.dev/wgpu-renderer](https://rasanen.dev/wgpu-renderer)
|
[rasanen.dev/wgpu-renderer](https://rasanen.dev/wgpu-renderer)
|
||||||
Note: the .wasm is about 50 MB because it embeds Sponza.
|
Note: the .wasm is about 50 MB because it embeds Sponza.
|
||||||
|
Note: shadowmaps are not enabled on WebGL.
|
||||||
|
|
||||||
Controls:
|
Controls:
|
||||||
- WASD - Move horizontally
|
- WASD - Move horizontally
|
||||||
|
@ -18,8 +19,8 @@ Controls:
|
||||||
- PBS
|
- PBS
|
||||||
- glTF models
|
- glTF models
|
||||||
- 1 realtime pointlight
|
- 1 realtime pointlight
|
||||||
- Shadow mapping
|
- Shadow mapping*
|
||||||
- Soft shadows
|
- Soft shadows*
|
||||||
- Simple wgsl preprocessor for includes
|
- Simple wgsl preprocessor for includes
|
||||||
- Runs on WASM and native desktop
|
- Runs on WASM and native desktop
|
||||||
- Tested on:
|
- Tested on:
|
||||||
|
@ -28,6 +29,8 @@ Controls:
|
||||||
- `Firefox 109.0`
|
- `Firefox 109.0`
|
||||||
- `Chrome 109.0.5414.120`
|
- `Chrome 109.0.5414.120`
|
||||||
|
|
||||||
|
*Native only
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- Transparency
|
- Transparency
|
||||||
- Restructuring
|
- Restructuring
|
||||||
|
|
16
index.html
16
index.html
|
@ -12,12 +12,14 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
#loading {
|
#loading {
|
||||||
color: white;
|
color: white;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -29,14 +31,20 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1 id="loading">Loading...</h1>
|
<h1 id="loading">Loading...</h1>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import init from "./pkg/wgpu_renderer.js";
|
import init from "./pkg/wgpu_renderer.js";
|
||||||
|
|
||||||
|
// TODO: still on GL, uncomment once WebGPU works
|
||||||
|
// if (!navigator.gpu) {
|
||||||
|
// document.getElementById("loading").innerText = "WebGPU not supported :(";
|
||||||
|
// } else {
|
||||||
init().then(() => {
|
init().then(() => {
|
||||||
console.log("WASM Loaded");
|
console.log("WASM Loaded");
|
||||||
document.getElementById("loading")?.remove();
|
document.getElementById("loading").remove();
|
||||||
});
|
});
|
||||||
</script>
|
// }
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -13,5 +13,5 @@ fn vs_main(
|
||||||
);
|
);
|
||||||
|
|
||||||
let world_position = model_matrix * vec4<f32>(model.position, 1.0);
|
let world_position = model_matrix * vec4<f32>(model.position, 1.0);
|
||||||
return light.matrices[light_matrix_index.value] * world_position;
|
return light.matrices[global_uniforms.light_matrix_index] * world_position;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,14 @@ struct Light {
|
||||||
var<uniform> light: Light;
|
var<uniform> light: Light;
|
||||||
|
|
||||||
// Needs to be 16 bytes in WebGL
|
// Needs to be 16 bytes in WebGL
|
||||||
struct LightMatrixIndex {
|
struct GlobalUniforms {
|
||||||
value: u32,
|
light_matrix_index: u32,
|
||||||
_padding: u32,
|
use_shadowmaps: u32,
|
||||||
_padding1: u32,
|
_padding1: u32,
|
||||||
_padding2: u32,
|
_padding2: u32,
|
||||||
}
|
}
|
||||||
@group(1) @binding(1)
|
@group(1) @binding(1)
|
||||||
var<uniform> light_matrix_index: LightMatrixIndex;
|
var<uniform> global_uniforms: GlobalUniforms;
|
||||||
|
|
||||||
struct VertexInput {
|
struct VertexInput {
|
||||||
@location(0) position: vec3<f32>,
|
@location(0) position: vec3<f32>,
|
||||||
|
|
|
@ -116,6 +116,10 @@ fn fs_main(vert: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
var total_radiance: vec3<f32>;
|
var total_radiance: vec3<f32>;
|
||||||
|
|
||||||
var in_light = 0.0;
|
var in_light = 0.0;
|
||||||
|
|
||||||
|
// Depth sampling is broken in WebGL...
|
||||||
|
// TODO: remove once WebGPU
|
||||||
|
if (global_uniforms.use_shadowmaps > 0u) {
|
||||||
for (var i: i32 = 0; i < 6; i++) {
|
for (var i: i32 = 0; i < 6; i++) {
|
||||||
let light_coords = light.matrices[i] * vert.world_position;
|
let light_coords = light.matrices[i] * vert.world_position;
|
||||||
|
|
||||||
|
@ -140,6 +144,9 @@ fn fs_main(vert: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
in_light = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
if (in_light > 0.0) {
|
if (in_light > 0.0) {
|
||||||
// lighting vecs
|
// lighting vecs
|
||||||
|
|
|
@ -43,10 +43,11 @@ impl LightUniform {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Debug, Default, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
pub struct LightMatrixUniform {
|
pub struct GlobalUniforms {
|
||||||
pub value: u32,
|
pub light_matrix_index: u32,
|
||||||
// No DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED in WebGL
|
// No DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED in WebGL
|
||||||
_padding: [u32; 3],
|
pub use_shadowmaps: u32,
|
||||||
|
_padding: [u32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DrawLight<'a> {
|
pub trait DrawLight<'a> {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::time::Duration;
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
use winit::{event::*, window::Window};
|
use winit::{event::*, window::Window};
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
use crate::core::light::LightMatrixUniform;
|
use crate::core::light::GlobalUniforms;
|
||||||
|
|
||||||
use super::camera::{Camera, CameraController, CameraUniform};
|
use super::camera::{Camera, CameraController, CameraUniform};
|
||||||
use super::instance::{Instance, InstanceRaw};
|
use super::instance::{Instance, InstanceRaw};
|
||||||
|
@ -45,7 +45,7 @@ pub struct State {
|
||||||
light_depth_bind_group: wgpu::BindGroup,
|
light_depth_bind_group: wgpu::BindGroup,
|
||||||
light_depth_pass: RenderPass,
|
light_depth_pass: RenderPass,
|
||||||
light_depth_texture_target_views: [TextureView; SHADOW_MAP_LAYERS as usize],
|
light_depth_texture_target_views: [TextureView; SHADOW_MAP_LAYERS as usize],
|
||||||
light_matrix_uniform: LightMatrixUniform,
|
light_matrix_uniform: GlobalUniforms,
|
||||||
light_matrix_buffer: wgpu::Buffer,
|
light_matrix_buffer: wgpu::Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ impl State {
|
||||||
let mut size = window.inner_size();
|
let mut size = window.inner_size();
|
||||||
size.width = size.width.max(1);
|
size.width = size.width.max(1);
|
||||||
size.height = size.height.max(1);
|
size.height = size.height.max(1);
|
||||||
let instance = wgpu::Instance::new(InstanceDescriptor { backends: Backends::all(), ..Default::default() });
|
let instance = wgpu::Instance::new(InstanceDescriptor { backends: Backends::PRIMARY | Backends::GL, ..Default::default() });
|
||||||
let surface = unsafe { instance.create_surface(window) }.unwrap();
|
let surface = unsafe { instance.create_surface(window) }.unwrap();
|
||||||
|
|
||||||
let adapter = instance
|
let adapter = instance
|
||||||
|
@ -73,13 +73,14 @@ impl State {
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
features: wgpu::Features::default(),
|
features: wgpu::Features::default(),
|
||||||
limits: if cfg!(target_arch = "wasm32") {
|
limits: if cfg!(target_arch = "wasm32") {
|
||||||
|
// TODO: remove once webgpu?
|
||||||
wgpu::Limits::downlevel_webgl2_defaults()
|
wgpu::Limits::downlevel_webgl2_defaults()
|
||||||
} else {
|
} else {
|
||||||
wgpu::Limits::default()
|
wgpu::Limits::default()
|
||||||
},
|
},
|
||||||
label: None,
|
label: None,
|
||||||
},
|
},
|
||||||
None, // Trace path
|
None,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.expect("failed to get device");
|
.expect("failed to get device");
|
||||||
|
@ -186,7 +187,7 @@ impl State {
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
});
|
});
|
||||||
|
|
||||||
let light_matrix_uniform = LightMatrixUniform::default();
|
let light_matrix_uniform = GlobalUniforms::default();
|
||||||
let light_matrix_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let light_matrix_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("Light Matrix UB"),
|
label: Some("Light Matrix UB"),
|
||||||
contents: bytemuck::cast_slice(&[light_matrix_uniform]),
|
contents: bytemuck::cast_slice(&[light_matrix_uniform]),
|
||||||
|
@ -194,7 +195,7 @@ impl State {
|
||||||
});
|
});
|
||||||
|
|
||||||
let light_uniform_size = mem::size_of::<LightUniform>() as u64;
|
let light_uniform_size = mem::size_of::<LightUniform>() as u64;
|
||||||
let light_matrix_uniform_size = mem::size_of::<LightMatrixUniform>() as u64;
|
let light_matrix_uniform_size = mem::size_of::<GlobalUniforms>() as u64;
|
||||||
let light_bind_group_layout =
|
let light_bind_group_layout =
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
entries: &[
|
entries: &[
|
||||||
|
@ -209,10 +210,11 @@ impl State {
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
},
|
},
|
||||||
// matrix index
|
// matrix index, use shadowmaps
|
||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
visibility: wgpu::ShaderStages::VERTEX,
|
// TODO: remove fragment vis once no shadowmap uniform
|
||||||
|
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: false,
|
||||||
|
@ -506,7 +508,8 @@ impl State {
|
||||||
|
|
||||||
// render light to depth textures
|
// render light to depth textures
|
||||||
for i in 0..SHADOW_MAP_LAYERS as usize {
|
for i in 0..SHADOW_MAP_LAYERS as usize {
|
||||||
self.light_matrix_uniform.value = i as u32;
|
self.light_matrix_uniform.light_matrix_index = i as u32;
|
||||||
|
self.light_matrix_uniform.use_shadowmaps = if cfg!(target_arch = "wasm32") { 0u32 } else { 1u32 };
|
||||||
self.queue.write_buffer(
|
self.queue.write_buffer(
|
||||||
&self.light_matrix_buffer,
|
&self.light_matrix_buffer,
|
||||||
0,
|
0,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue