Skip to content

Commit 03575ae

Browse files
committed
EnvironmentMapLight support for WebGL2 (#7737)
# Objective - Fix the environment map shader not working under webgl due to textureNumLevels() not being supported - Fixes #7722 ## Solution - Instead of using textureNumLevels(), put an extra field in the GpuLights uniform to store the mip count
1 parent 912fb58 commit 03575ae

File tree

8 files changed

+27
-8
lines changed

8 files changed

+27
-8
lines changed

crates/bevy_pbr/src/environment_map/environment_map.wgsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ fn environment_map_light(
1818
) -> EnvironmentMapLight {
1919

2020
// Split-sum approximation for image based lighting: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
21-
let smallest_specular_mip_level = textureNumLevels(environment_map_specular) - 1i;
22-
let radiance_level = perceptual_roughness * f32(smallest_specular_mip_level);
21+
// Technically we could use textureNumLevels(environment_map_specular) - 1 here, but we use a uniform
22+
// because textureNumLevels() does not work on WebGL2
23+
let radiance_level = perceptual_roughness * f32(lights.environment_map_smallest_specular_mip_level);
2324
let irradiance = textureSample(environment_map_diffuse, environment_map_sampler, N).rgb;
2425
let radiance = textureSampleLevel(environment_map_specular, environment_map_sampler, R, radiance_level).rgb;
2526

crates/bevy_pbr/src/render/light.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::{
22
directional_light_order, point_light_order, AmbientLight, Cascade, CascadeShadowConfig,
33
Cascades, CascadesVisibleEntities, Clusters, CubemapVisibleEntities, DirectionalLight,
4-
DirectionalLightShadowMap, DrawMesh, GlobalVisiblePointLights, MeshPipeline, NotShadowCaster,
5-
PointLight, PointLightShadowMap, SetMeshBindGroup, SpotLight, VisiblePointLights,
6-
SHADOW_SHADER_HANDLE,
4+
DirectionalLightShadowMap, DrawMesh, EnvironmentMapLight, GlobalVisiblePointLights,
5+
MeshPipeline, NotShadowCaster, PointLight, PointLightShadowMap, SetMeshBindGroup, SpotLight,
6+
VisiblePointLights, SHADOW_SHADER_HANDLE,
77
};
88
use bevy_asset::Handle;
99
use bevy_core_pipeline::core_3d::Transparent3d;
@@ -218,6 +218,7 @@ pub struct GpuLights {
218218
n_directional_lights: u32,
219219
// offset from spot light's light index to spot light's shadow map index
220220
spot_light_shadowmap_offset: i32,
221+
environment_map_smallest_specular_mip_level: u32,
221222
}
222223

223224
// NOTE: this must be kept in sync with the same constants in pbr.frag
@@ -787,12 +788,18 @@ pub(crate) fn spot_light_projection_matrix(angle: f32) -> Mat4 {
787788
pub fn prepare_lights(
788789
mut commands: Commands,
789790
mut texture_cache: ResMut<TextureCache>,
791+
images: Res<RenderAssets<Image>>,
790792
render_device: Res<RenderDevice>,
791793
render_queue: Res<RenderQueue>,
792794
mut global_light_meta: ResMut<GlobalLightMeta>,
793795
mut light_meta: ResMut<LightMeta>,
794796
views: Query<
795-
(Entity, &ExtractedView, &ExtractedClusterConfig),
797+
(
798+
Entity,
799+
&ExtractedView,
800+
&ExtractedClusterConfig,
801+
Option<&EnvironmentMapLight>,
802+
),
796803
With<RenderPhase<Transparent3d>>,
797804
>,
798805
ambient_light: Res<AmbientLight>,
@@ -1029,7 +1036,7 @@ pub fn prepare_lights(
10291036
.write_buffer(&render_device, &render_queue);
10301037

10311038
// set up light data for each view
1032-
for (entity, extracted_view, clusters) in &views {
1039+
for (entity, extracted_view, clusters, environment_map) in &views {
10331040
let point_light_depth_texture = texture_cache.get(
10341041
&render_device,
10351042
TextureDescriptor {
@@ -1096,6 +1103,10 @@ pub fn prepare_lights(
10961103
// index to shadow map index, we need to subtract point light count and add directional shadowmap count.
10971104
spot_light_shadowmap_offset: num_directional_cascades_enabled as i32
10981105
- point_light_count as i32,
1106+
environment_map_smallest_specular_mip_level: environment_map
1107+
.and_then(|env_map| images.get(&env_map.specular_map))
1108+
.map(|specular_map| specular_map.mip_level_count - 1)
1109+
.unwrap_or(0),
10991110
};
11001111

11011112
// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ impl FromWorld for MeshPipeline {
546546
image.texture_descriptor.size.width as f32,
547547
image.texture_descriptor.size.height as f32,
548548
),
549+
mip_level_count: image.texture_descriptor.mip_level_count,
549550
}
550551
};
551552

crates/bevy_pbr/src/render/mesh_view_types.wgsl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct DirectionalCascade {
2424
texel_size: f32,
2525
far_bound: f32,
2626
}
27-
27+
2828
struct DirectionalLight {
2929
cascades: array<DirectionalCascade, #{MAX_CASCADES_PER_LIGHT}>,
3030
color: vec4<f32>,
@@ -59,6 +59,7 @@ struct Lights {
5959
cluster_factors: vec4<f32>,
6060
n_directional_lights: u32,
6161
spot_light_shadowmap_offset: i32,
62+
environment_map_smallest_specular_mip_level: u32,
6263
};
6364

6465
struct Fog {

crates/bevy_render/src/texture/fallback_image.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ fn fallback_image_new(
7878
image.texture_descriptor.size.width as f32,
7979
image.texture_descriptor.size.height as f32,
8080
),
81+
mip_level_count: image.texture_descriptor.mip_level_count,
8182
}
8283
}
8384

crates/bevy_render/src/texture/image.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ pub struct GpuImage {
499499
pub texture_format: TextureFormat,
500500
pub sampler: Sampler,
501501
pub size: Vec2,
502+
pub mip_level_count: u32,
502503
}
503504

504505
impl RenderAsset for Image {
@@ -548,6 +549,7 @@ impl RenderAsset for Image {
548549
texture_format: image.texture_descriptor.format,
549550
sampler,
550551
size,
552+
mip_level_count: image.texture_descriptor.mip_level_count,
551553
})
552554
}
553555
}

crates/bevy_sprite/src/mesh2d/mesh.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ impl FromWorld for Mesh2dPipeline {
253253
image.texture_descriptor.size.width as f32,
254254
image.texture_descriptor.size.height as f32,
255255
),
256+
mip_level_count: image.texture_descriptor.mip_level_count,
256257
}
257258
};
258259
Mesh2dPipeline {

crates/bevy_sprite/src/render/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ impl FromWorld for SpritePipeline {
134134
image.texture_descriptor.size.width as f32,
135135
image.texture_descriptor.size.height as f32,
136136
),
137+
mip_level_count: image.texture_descriptor.mip_level_count,
137138
}
138139
};
139140

0 commit comments

Comments
 (0)