Skip to content

Commit

Permalink
EnvironmentMapLight support for WebGL2 (#7737)
Browse files Browse the repository at this point in the history
# 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
  • Loading branch information
JMS55 committed Feb 20, 2023
1 parent 912fb58 commit 03575ae
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 8 deletions.
5 changes: 3 additions & 2 deletions crates/bevy_pbr/src/environment_map/environment_map.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ fn environment_map_light(
) -> EnvironmentMapLight {

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

Expand Down
21 changes: 16 additions & 5 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
directional_light_order, point_light_order, AmbientLight, Cascade, CascadeShadowConfig,
Cascades, CascadesVisibleEntities, Clusters, CubemapVisibleEntities, DirectionalLight,
DirectionalLightShadowMap, DrawMesh, GlobalVisiblePointLights, MeshPipeline, NotShadowCaster,
PointLight, PointLightShadowMap, SetMeshBindGroup, SpotLight, VisiblePointLights,
SHADOW_SHADER_HANDLE,
DirectionalLightShadowMap, DrawMesh, EnvironmentMapLight, GlobalVisiblePointLights,
MeshPipeline, NotShadowCaster, PointLight, PointLightShadowMap, SetMeshBindGroup, SpotLight,
VisiblePointLights, SHADOW_SHADER_HANDLE,
};
use bevy_asset::Handle;
use bevy_core_pipeline::core_3d::Transparent3d;
Expand Down Expand Up @@ -218,6 +218,7 @@ pub struct GpuLights {
n_directional_lights: u32,
// offset from spot light's light index to spot light's shadow map index
spot_light_shadowmap_offset: i32,
environment_map_smallest_specular_mip_level: u32,
}

// NOTE: this must be kept in sync with the same constants in pbr.frag
Expand Down Expand Up @@ -787,12 +788,18 @@ pub(crate) fn spot_light_projection_matrix(angle: f32) -> Mat4 {
pub fn prepare_lights(
mut commands: Commands,
mut texture_cache: ResMut<TextureCache>,
images: Res<RenderAssets<Image>>,
render_device: Res<RenderDevice>,
render_queue: Res<RenderQueue>,
mut global_light_meta: ResMut<GlobalLightMeta>,
mut light_meta: ResMut<LightMeta>,
views: Query<
(Entity, &ExtractedView, &ExtractedClusterConfig),
(
Entity,
&ExtractedView,
&ExtractedClusterConfig,
Option<&EnvironmentMapLight>,
),
With<RenderPhase<Transparent3d>>,
>,
ambient_light: Res<AmbientLight>,
Expand Down Expand Up @@ -1029,7 +1036,7 @@ pub fn prepare_lights(
.write_buffer(&render_device, &render_queue);

// set up light data for each view
for (entity, extracted_view, clusters) in &views {
for (entity, extracted_view, clusters, environment_map) in &views {
let point_light_depth_texture = texture_cache.get(
&render_device,
TextureDescriptor {
Expand Down Expand Up @@ -1096,6 +1103,10 @@ pub fn prepare_lights(
// index to shadow map index, we need to subtract point light count and add directional shadowmap count.
spot_light_shadowmap_offset: num_directional_cascades_enabled as i32
- point_light_count as i32,
environment_map_smallest_specular_mip_level: environment_map
.and_then(|env_map| images.get(&env_map.specular_map))
.map(|specular_map| specular_map.mip_level_count - 1)
.unwrap_or(0),
};

// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ impl FromWorld for MeshPipeline {
image.texture_descriptor.size.width as f32,
image.texture_descriptor.size.height as f32,
),
mip_level_count: image.texture_descriptor.mip_level_count,
}
};

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_pbr/src/render/mesh_view_types.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct DirectionalCascade {
texel_size: f32,
far_bound: f32,
}

struct DirectionalLight {
cascades: array<DirectionalCascade, #{MAX_CASCADES_PER_LIGHT}>,
color: vec4<f32>,
Expand Down Expand Up @@ -59,6 +59,7 @@ struct Lights {
cluster_factors: vec4<f32>,
n_directional_lights: u32,
spot_light_shadowmap_offset: i32,
environment_map_smallest_specular_mip_level: u32,
};

struct Fog {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_render/src/texture/fallback_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ fn fallback_image_new(
image.texture_descriptor.size.width as f32,
image.texture_descriptor.size.height as f32,
),
mip_level_count: image.texture_descriptor.mip_level_count,
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_render/src/texture/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ pub struct GpuImage {
pub texture_format: TextureFormat,
pub sampler: Sampler,
pub size: Vec2,
pub mip_level_count: u32,
}

impl RenderAsset for Image {
Expand Down Expand Up @@ -548,6 +549,7 @@ impl RenderAsset for Image {
texture_format: image.texture_descriptor.format,
sampler,
size,
mip_level_count: image.texture_descriptor.mip_level_count,
})
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_sprite/src/mesh2d/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ impl FromWorld for Mesh2dPipeline {
image.texture_descriptor.size.width as f32,
image.texture_descriptor.size.height as f32,
),
mip_level_count: image.texture_descriptor.mip_level_count,
}
};
Mesh2dPipeline {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ impl FromWorld for SpritePipeline {
image.texture_descriptor.size.width as f32,
image.texture_descriptor.size.height as f32,
),
mip_level_count: image.texture_descriptor.mip_level_count,
}
};

Expand Down

0 comments on commit 03575ae

Please sign in to comment.