EnvironmentMapLight support for WebGL2 (#7737)
# Objective - Fix the environment map shader not working under webgl due to textureNumLevels() not being supported - Fixes https://github.com/bevyengine/bevy/issues/7722 ## Solution - Instead of using textureNumLevels(), put an extra field in the GpuLights uniform to store the mip count
This commit is contained in:
parent
912fb58869
commit
03575aef22
@ -18,8 +18,9 @@ fn environment_map_light(
|
|||||||
) -> EnvironmentMapLight {
|
) -> EnvironmentMapLight {
|
||||||
|
|
||||||
// Split-sum approximation for image based lighting: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
|
// 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;
|
// Technically we could use textureNumLevels(environment_map_specular) - 1 here, but we use a uniform
|
||||||
let radiance_level = perceptual_roughness * f32(smallest_specular_mip_level);
|
// 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 irradiance = textureSample(environment_map_diffuse, environment_map_sampler, N).rgb;
|
||||||
let radiance = textureSampleLevel(environment_map_specular, environment_map_sampler, R, radiance_level).rgb;
|
let radiance = textureSampleLevel(environment_map_specular, environment_map_sampler, R, radiance_level).rgb;
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
directional_light_order, point_light_order, AmbientLight, Cascade, CascadeShadowConfig,
|
directional_light_order, point_light_order, AmbientLight, Cascade, CascadeShadowConfig,
|
||||||
Cascades, CascadesVisibleEntities, Clusters, CubemapVisibleEntities, DirectionalLight,
|
Cascades, CascadesVisibleEntities, Clusters, CubemapVisibleEntities, DirectionalLight,
|
||||||
DirectionalLightShadowMap, DrawMesh, GlobalVisiblePointLights, MeshPipeline, NotShadowCaster,
|
DirectionalLightShadowMap, DrawMesh, EnvironmentMapLight, GlobalVisiblePointLights,
|
||||||
PointLight, PointLightShadowMap, SetMeshBindGroup, SpotLight, VisiblePointLights,
|
MeshPipeline, NotShadowCaster, PointLight, PointLightShadowMap, SetMeshBindGroup, SpotLight,
|
||||||
SHADOW_SHADER_HANDLE,
|
VisiblePointLights, SHADOW_SHADER_HANDLE,
|
||||||
};
|
};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_core_pipeline::core_3d::Transparent3d;
|
use bevy_core_pipeline::core_3d::Transparent3d;
|
||||||
@ -218,6 +218,7 @@ pub struct GpuLights {
|
|||||||
n_directional_lights: u32,
|
n_directional_lights: u32,
|
||||||
// offset from spot light's light index to spot light's shadow map index
|
// offset from spot light's light index to spot light's shadow map index
|
||||||
spot_light_shadowmap_offset: i32,
|
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
|
// 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 {
|
|||||||
pub fn prepare_lights(
|
pub fn prepare_lights(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut texture_cache: ResMut<TextureCache>,
|
mut texture_cache: ResMut<TextureCache>,
|
||||||
|
images: Res<RenderAssets<Image>>,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
render_queue: Res<RenderQueue>,
|
render_queue: Res<RenderQueue>,
|
||||||
mut global_light_meta: ResMut<GlobalLightMeta>,
|
mut global_light_meta: ResMut<GlobalLightMeta>,
|
||||||
mut light_meta: ResMut<LightMeta>,
|
mut light_meta: ResMut<LightMeta>,
|
||||||
views: Query<
|
views: Query<
|
||||||
(Entity, &ExtractedView, &ExtractedClusterConfig),
|
(
|
||||||
|
Entity,
|
||||||
|
&ExtractedView,
|
||||||
|
&ExtractedClusterConfig,
|
||||||
|
Option<&EnvironmentMapLight>,
|
||||||
|
),
|
||||||
With<RenderPhase<Transparent3d>>,
|
With<RenderPhase<Transparent3d>>,
|
||||||
>,
|
>,
|
||||||
ambient_light: Res<AmbientLight>,
|
ambient_light: Res<AmbientLight>,
|
||||||
@ -1029,7 +1036,7 @@ pub fn prepare_lights(
|
|||||||
.write_buffer(&render_device, &render_queue);
|
.write_buffer(&render_device, &render_queue);
|
||||||
|
|
||||||
// set up light data for each view
|
// 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(
|
let point_light_depth_texture = texture_cache.get(
|
||||||
&render_device,
|
&render_device,
|
||||||
TextureDescriptor {
|
TextureDescriptor {
|
||||||
@ -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.
|
// 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
|
spot_light_shadowmap_offset: num_directional_cascades_enabled as i32
|
||||||
- point_light_count 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
|
// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
|
||||||
|
@ -546,6 +546,7 @@ impl FromWorld for MeshPipeline {
|
|||||||
image.texture_descriptor.size.width as f32,
|
image.texture_descriptor.size.width as f32,
|
||||||
image.texture_descriptor.size.height as f32,
|
image.texture_descriptor.size.height as f32,
|
||||||
),
|
),
|
||||||
|
mip_level_count: image.texture_descriptor.mip_level_count,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ struct DirectionalCascade {
|
|||||||
texel_size: f32,
|
texel_size: f32,
|
||||||
far_bound: f32,
|
far_bound: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DirectionalLight {
|
struct DirectionalLight {
|
||||||
cascades: array<DirectionalCascade, #{MAX_CASCADES_PER_LIGHT}>,
|
cascades: array<DirectionalCascade, #{MAX_CASCADES_PER_LIGHT}>,
|
||||||
color: vec4<f32>,
|
color: vec4<f32>,
|
||||||
@ -59,6 +59,7 @@ struct Lights {
|
|||||||
cluster_factors: vec4<f32>,
|
cluster_factors: vec4<f32>,
|
||||||
n_directional_lights: u32,
|
n_directional_lights: u32,
|
||||||
spot_light_shadowmap_offset: i32,
|
spot_light_shadowmap_offset: i32,
|
||||||
|
environment_map_smallest_specular_mip_level: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Fog {
|
struct Fog {
|
||||||
|
@ -78,6 +78,7 @@ fn fallback_image_new(
|
|||||||
image.texture_descriptor.size.width as f32,
|
image.texture_descriptor.size.width as f32,
|
||||||
image.texture_descriptor.size.height as f32,
|
image.texture_descriptor.size.height as f32,
|
||||||
),
|
),
|
||||||
|
mip_level_count: image.texture_descriptor.mip_level_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,6 +499,7 @@ pub struct GpuImage {
|
|||||||
pub texture_format: TextureFormat,
|
pub texture_format: TextureFormat,
|
||||||
pub sampler: Sampler,
|
pub sampler: Sampler,
|
||||||
pub size: Vec2,
|
pub size: Vec2,
|
||||||
|
pub mip_level_count: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderAsset for Image {
|
impl RenderAsset for Image {
|
||||||
@ -548,6 +549,7 @@ impl RenderAsset for Image {
|
|||||||
texture_format: image.texture_descriptor.format,
|
texture_format: image.texture_descriptor.format,
|
||||||
sampler,
|
sampler,
|
||||||
size,
|
size,
|
||||||
|
mip_level_count: image.texture_descriptor.mip_level_count,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,6 +253,7 @@ impl FromWorld for Mesh2dPipeline {
|
|||||||
image.texture_descriptor.size.width as f32,
|
image.texture_descriptor.size.width as f32,
|
||||||
image.texture_descriptor.size.height as f32,
|
image.texture_descriptor.size.height as f32,
|
||||||
),
|
),
|
||||||
|
mip_level_count: image.texture_descriptor.mip_level_count,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Mesh2dPipeline {
|
Mesh2dPipeline {
|
||||||
|
@ -134,6 +134,7 @@ impl FromWorld for SpritePipeline {
|
|||||||
image.texture_descriptor.size.width as f32,
|
image.texture_descriptor.size.width as f32,
|
||||||
image.texture_descriptor.size.height as f32,
|
image.texture_descriptor.size.height as f32,
|
||||||
),
|
),
|
||||||
|
mip_level_count: image.texture_descriptor.mip_level_count,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user