Skip to content

Commit

Permalink
WebGL2 hacks
Browse files Browse the repository at this point in the history
  • Loading branch information
superdump committed Nov 17, 2021
1 parent 6ef9b65 commit 6813b2e
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 17 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ subpixel_glyph_atlas = ["bevy_internal/subpixel_glyph_atlas"]
# enable systems that allow for automated testing on CI
bevy_ci_testing = ["bevy_internal/bevy_ci_testing"]

[patch.crates-io]
wgpu = { path = "../wgpu/wgpu" }

[dependencies]
bevy_dylib = { path = "crates/bevy_dylib", version = "0.5.0", default-features = false, optional = true }
bevy_internal = { path = "crates/bevy_internal", version = "0.5.0", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_wgpu/src/wgpu_type_converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ impl WgpuFrom<WgpuLimits> for wgpu::Limits {
max_vertex_buffer_array_stride: val.max_vertex_buffer_array_stride,
min_storage_buffer_offset_alignment: val.min_storage_buffer_offset_alignment,
min_uniform_buffer_offset_alignment: val.min_uniform_buffer_offset_alignment,
..Default::default()
}
}
}
7 changes: 7 additions & 0 deletions examples/3d/3d_scene_pipelined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ use bevy::{
camera::{OrthographicProjection, PerspectiveCameraBundle},
color::Color,
mesh::{shape, Mesh},
view::Msaa,
},
window::WindowDescriptor,
PipelinedDefaultPlugins,
};

fn main() {
App::new()
.insert_resource(Msaa { samples: 1 })
.insert_resource(WindowDescriptor {
scale_factor_override: Some(1.0),
..Default::default()
})
.add_plugins(PipelinedDefaultPlugins)
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_plugin(LogDiagnosticsPlugin::default())
Expand Down
7 changes: 7 additions & 0 deletions examples/3d/load_gltf_pipelined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ use bevy::{
render2::{
camera::{OrthographicProjection, PerspectiveCameraBundle},
color::Color,
view::Msaa,
},
window::WindowDescriptor,
PipelinedDefaultPlugins,
};

fn main() {
App::new()
.insert_resource(Msaa { samples: 1 })
.insert_resource(WindowDescriptor {
scale_factor_override: Some(1.0),
..Default::default()
})
.insert_resource(AmbientLight {
color: Color::WHITE,
brightness: 1.0 / 5.0f32,
Expand Down
15 changes: 15 additions & 0 deletions index.html.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<script type="module">
import init from "./${EXAMPLE_NAME}.js";
window.addEventListener("load", () => {
init();
});
</script>
</body>
</html>

2 changes: 1 addition & 1 deletion pipelined/bevy_pbr2/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub struct DirectionalLightShadowMap {

impl Default for DirectionalLightShadowMap {
fn default() -> Self {
Self { size: 4096 }
Self { size: 1024 }
}
}

Expand Down
24 changes: 15 additions & 9 deletions pipelined/bevy_pbr2/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,9 @@ pub struct GpuLights {

// NOTE: this must be kept in sync with the same constants in pbr.frag
pub const MAX_POINT_LIGHTS: usize = 256;
pub const MAX_POINT_LIGHT_SHADOW_MAPS: usize = 1;
pub const MAX_DIRECTIONAL_LIGHTS: usize = 1;
// FIXME: How should we handle shadows for clustered forward? Limiting to maximum 10
// point light shadow maps for now
pub const POINT_SHADOW_LAYERS: u32 = (6 * 10) as u32;
pub const POINT_SHADOW_LAYERS: u32 = (6 * MAX_POINT_LIGHT_SHADOW_MAPS) as u32;
pub const DIRECTIONAL_SHADOW_LAYERS: u32 = MAX_DIRECTIONAL_LIGHTS as u32;
pub const SHADOW_FORMAT: TextureFormat = TextureFormat::Depth32Float;

Expand Down Expand Up @@ -189,6 +188,8 @@ impl FromWorld for ShadowPipeline {
min_filter: FilterMode::Linear,
mipmap_filter: FilterMode::Nearest,
compare: Some(CompareFunction::GreaterEqual),
// compare: Some(CompareFunction::LessEqual),
// compare: None,
..Default::default()
}),
directional_light_sampler: render_device.create_sampler(&SamplerDescriptor {
Expand All @@ -199,6 +200,7 @@ impl FromWorld for ShadowPipeline {
min_filter: FilterMode::Linear,
mipmap_filter: FilterMode::Nearest,
compare: Some(CompareFunction::GreaterEqual),
// compare: None,
..Default::default()
}),
}
Expand Down Expand Up @@ -646,8 +648,8 @@ pub fn prepare_lights(
};

// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
for (light_entity, light) in point_lights.iter() {
if !light.shadows_enabled {
for (i, (light_entity, light)) in point_lights.iter().enumerate().take(MAX_POINT_LIGHTS) {
if !light.shadows_enabled || i >= MAX_POINT_LIGHT_SHADOW_MAPS {
continue;
}
let light_index = *global_light_meta
Expand Down Expand Up @@ -787,9 +789,11 @@ pub fn prepare_lights(
point_light_depth_texture
.texture
.create_view(&TextureViewDescriptor {
label: Some("point_light_shadow_map_array_texture_view"),
// label: Some("point_light_shadow_map_array_texture_view"),
label: Some("point_light_shadow_map_texture_view"),
format: None,
dimension: Some(TextureViewDimension::CubeArray),
// dimension: Some(TextureViewDimension::CubeArray),
dimension: Some(TextureViewDimension::Cube),
aspect: TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
Expand All @@ -799,9 +803,11 @@ pub fn prepare_lights(
let directional_light_depth_texture_view = directional_light_depth_texture
.texture
.create_view(&TextureViewDescriptor {
label: Some("directional_light_shadow_map_array_texture_view"),
// label: Some("directional_light_shadow_map_array_texture_view"),
label: Some("directional_light_shadow_map_texture_view"),
format: None,
dimension: Some(TextureViewDimension::D2Array),
// dimension: Some(TextureViewDimension::D2Array),
dimension: Some(TextureViewDimension::D2),
aspect: TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
Expand Down
13 changes: 9 additions & 4 deletions pipelined/bevy_pbr2/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,22 +204,24 @@ impl FromWorld for PbrPipeline {
},
count: None,
},
// Point Shadow Texture Cube Array
// Point Shadow Texture Cube [Array]
BindGroupLayoutEntry {
binding: 2,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture {
multisampled: false,
sample_type: TextureSampleType::Depth,
view_dimension: TextureViewDimension::CubeArray,
// view_dimension: TextureViewDimension::CubeArray,
view_dimension: TextureViewDimension::Cube,
},
count: None,
},
// Point Shadow Texture Array Sampler
// Point Shadow Texture [Array] Sampler
BindGroupLayoutEntry {
binding: 3,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler {
// comparison: false,
comparison: true,
filtering: true,
},
Expand All @@ -232,7 +234,8 @@ impl FromWorld for PbrPipeline {
ty: BindingType::Texture {
multisampled: false,
sample_type: TextureSampleType::Depth,
view_dimension: TextureViewDimension::D2Array,
// view_dimension: TextureViewDimension::D2Array,
view_dimension: TextureViewDimension::D2,
},
count: None,
},
Expand All @@ -242,6 +245,7 @@ impl FromWorld for PbrPipeline {
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler {
comparison: true,
// comparison: false,
filtering: true,
},
count: None,
Expand Down Expand Up @@ -590,6 +594,7 @@ impl SpecializedPipeline for PbrPipeline {
// depth buffer
depth_write_enabled = true;
}
shader_defs.push(String::from("NO_CUBE_ARRAY_TEXTURES_SUPPORT"));
RenderPipelineDescriptor {
vertex: VertexState {
shader: PBR_SHADER_HANDLE.typed::<Shader>(),
Expand Down
50 changes: 48 additions & 2 deletions pipelined/bevy_pbr2/src/render/pbr.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,25 @@ struct ClusterOffsetsAndCounts {

[[group(0), binding(1)]]
var<uniform> lights: Lights;
#ifdef CUBE_ARRAY_TEXTURES_SUPPORT
[[group(0), binding(2)]]
var point_shadow_textures: texture_depth_cube_array;
[[group(0), binding(3)]]
var point_shadow_textures_sampler: sampler_comparison;
#endif
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
[[group(0), binding(2)]]
var point_shadow_textures: texture_depth_cube;
[[group(0), binding(3)]]
var point_shadow_textures_sampler: sampler_comparison;
// var point_shadow_textures_sampler: sampler;
#endif
[[group(0), binding(4)]]
var directional_shadow_textures: texture_depth_2d_array;
// var directional_shadow_textures: texture_depth_2d_array;
var directional_shadow_textures: texture_depth_2d;
[[group(0), binding(5)]]
var directional_shadow_textures_sampler: sampler_comparison;
// var directional_shadow_textures_sampler: sampler;
[[group(0), binding(6)]]
var<uniform> point_lights: PointLights;
[[group(0), binding(7)]]
Expand Down Expand Up @@ -516,7 +527,18 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: v
// a quad (2x2 fragments) being processed not being sampled, and this messing with
// mip-mapping functionality. The shadow maps have no mipmaps so Level just samples
// from LOD 0.
#ifdef CUBE_ARRAY_TEXTURES_SUPPORT
return textureSampleCompareLevel(point_shadow_textures, point_shadow_textures_sampler, frag_ls, i32(light_id), depth);
#endif
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
return textureSampleCompare(point_shadow_textures, point_shadow_textures_sampler, frag_ls, depth);
// let sampled_depth = textureSample(point_shadow_textures, point_shadow_textures_sampler, frag_ls);
// if (sampled_depth >= depth) {
// return 0.0;
// } else {
// return 1.0;
// }
#endif
}

fn fetch_directional_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: vec3<f32>) -> f32 {
Expand Down Expand Up @@ -547,7 +569,24 @@ fn fetch_directional_shadow(light_id: u32, frag_position: vec4<f32>, surface_nor
// do the lookup, using HW PCF and comparison
// NOTE: Due to non-uniform control flow above, we must use the level variant of the texture
// sampler to avoid use of implicit derivatives causing possible undefined behavior.
return textureSampleCompareLevel(directional_shadow_textures, directional_shadow_textures_sampler, light_local, i32(light_id), depth);
// return textureSampleCompareLevel(directional_shadow_textures, directional_shadow_textures_sampler, light_local, i32(light_id), depth);
return textureSampleCompareLevel(directional_shadow_textures, directional_shadow_textures_sampler, light_local, depth);
// let sampled_depth = textureSample(directional_shadow_textures, directional_shadow_textures_sampler, light_local, i32(light_id));
// // No shadow outside the orthographic projection volume

// if (offset_position_clip.w <= 0.0) {
// return 1.0;
// }
// if (any(offset_position_ndc.xy < vec2<f32>(-1.0)) || offset_position_ndc.z < 0.0
// || any(offset_position_ndc > vec3<f32>(1.0))) {
// return 1.0;
// }

// if (sampled_depth >= depth) {
// return 0.0;
// } else {
// return 1.0;
// }
}

fn hsv2rgb(hue: f32, saturation: f32, value: f32) -> vec3<f32> {
Expand Down Expand Up @@ -683,8 +722,15 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
let light_id = get_light_id(i);
let light = point_lights.data[light_id];
var shadow: f32 = 1.0;
#ifdef CUBE_ARRAY_TEXTURES_SUPPORT
if ((mesh.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
|| (light.flags & POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
#endif
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
if (light_id < 1u
&& ((mesh.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
|| (light.flags & POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u)) {
#endif
shadow = fetch_point_shadow(light_id, in.world_position, in.world_normal);
}
let light_contrib = point_light(in.world_position.xyz, light, roughness, NdotV, N, V, R, F0, diffuse_color);
Expand Down
4 changes: 3 additions & 1 deletion pipelined/bevy_render2/src/render_resource/pipeline_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
use bevy_app::EventReader;
use bevy_asset::{AssetEvent, Handle};
use bevy_ecs::system::{Res, ResMut};
use bevy_utils::{HashMap, HashSet};
use bevy_utils::{tracing::error, HashMap, HashSet};
use std::{collections::hash_map::Entry, hash::Hash, ops::Deref, sync::Arc};
use thiserror::Error;
use wgpu::{PipelineLayoutDescriptor, ShaderModule, VertexBufferLayout};
Expand Down Expand Up @@ -54,6 +54,7 @@ impl ShaderCache {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
let processed = self.processor.process_shader(shader, shader_defs)?;
error!("Shader code:\n{:?}", processed);
let module_descriptor = processed.get_module_descriptor()?;
entry.insert(Arc::new(
render_device.create_shader_module(&module_descriptor),
Expand Down Expand Up @@ -249,6 +250,7 @@ impl RenderPipelineCache {
continue;
}
};
error!("Fragment shader module:\n{:?}", fragment_module);
Some((
fragment_module,
fragment.entry_point.deref(),
Expand Down
1 change: 1 addition & 0 deletions pipelined/bevy_render2/src/render_resource/shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub enum Shader {
}

/// A processed [Shader]. This cannot contain preprocessor directions. It must be "ready to compile"
#[derive(Debug)]
pub enum ProcessedShader {
Wgsl(Cow<'static, str>),
Glsl(Cow<'static, str>, naga::ShaderStage),
Expand Down
14 changes: 14 additions & 0 deletions wasm_build_example.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh -ex

export EXAMPLE_NAME="${1}"
cargo build \
--release \
--example "${EXAMPLE_NAME}" \
--target wasm32-unknown-unknown \
--no-default-features \
--features bevy_core_pipeline,bevy_gltf2,bevy_sprite2,bevy_render2,bevy_pbr2,bevy_winit,png,x11,jpeg \
&& wasm-bindgen \
--out-dir web \
--target web \
"target/wasm32-unknown-unknown/release/examples/${EXAMPLE_NAME}.wasm" \
&& envsubst < index.html.template > "web/${EXAMPLE_NAME}.html"

0 comments on commit 6813b2e

Please sign in to comment.