Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine the shader point and spot light lookup into one loop. #17510

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 38 additions & 60 deletions crates/bevy_pbr/src/render/pbr_functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,9 @@ fn apply_pbr_lighting(
var clusterable_object_index_ranges =
clustering::unpack_clusterable_object_index_ranges(cluster_index);

// Point lights (direct)
// Point lights & spot lights (direct)
for (var i: u32 = clusterable_object_index_ranges.first_point_light_index_offset;
i < clusterable_object_index_ranges.first_spot_light_index_offset;
i < clusterable_object_index_ranges.first_reflection_probe_index_offset;
i = i + 1u) {
let light_id = clustering::get_clusterable_object_id(i);

Expand All @@ -416,13 +416,31 @@ fn apply_pbr_lighting(
let enable_diffuse = true;
#endif // LIGHTMAP

// Point lights precede spot lights in the list.
let is_spot_light = i >= clusterable_object_index_ranges.first_spot_light_index_offset;

var shadow: f32 = 1.0;
if ((in.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
&& (view_bindings::clusterable_objects.data[light_id].flags & mesh_view_types::POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
shadow = shadows::fetch_point_shadow(light_id, in.world_position, in.world_normal);
if (is_spot_light) {
shadow = shadows::fetch_spot_shadow(
light_id,
in.world_position,
in.world_normal,
view_bindings::clusterable_objects.data[light_id].shadow_map_near_z
);
} else {
shadow = shadows::fetch_point_shadow(light_id, in.world_position, in.world_normal);
}
}

var light_contrib = lighting::point_light(light_id, &lighting_input, enable_diffuse);

if (is_spot_light) {
// Reuse the point light calculations.
light_contrib *= lighting::spot_light(light_id, &lighting_input);
}

let light_contrib = lighting::point_light(light_id, &lighting_input, enable_diffuse);
direct_light += light_contrib * shadow;

#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION
Expand All @@ -438,71 +456,31 @@ fn apply_pbr_lighting(
var transmitted_shadow: f32 = 1.0;
if ((in.flags & (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)) == (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)
&& (view_bindings::clusterable_objects.data[light_id].flags & mesh_view_types::POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
transmitted_shadow = shadows::fetch_point_shadow(light_id, diffuse_transmissive_lobe_world_position, -in.world_normal);
if (is_spot_light) {
transmitted_shadow = shadows::fetch_spot_shadow(
light_id,
diffuse_transmissive_lobe_world_position,
-in.world_normal,
view_bindings::clusterable_objects.data[light_id].shadow_map_near_z,
);
} else {
transmitted_shadow = shadows::fetch_point_shadow(light_id, diffuse_transmissive_lobe_world_position, -in.world_normal);
}
}

let transmitted_light_contrib =
var transmitted_light_contrib =
lighting::point_light(light_id, &transmissive_lighting_input, enable_diffuse);
transmitted_light += transmitted_light_contrib * transmitted_shadow;
#endif
}

// Spot lights (direct)
for (var i: u32 = clusterable_object_index_ranges.first_spot_light_index_offset;
i < clusterable_object_index_ranges.first_reflection_probe_index_offset;
i = i + 1u) {
let light_id = clustering::get_clusterable_object_id(i);

// If we're lightmapped, disable diffuse contribution from the light if
// requested, to avoid double-counting light.
#ifdef LIGHTMAP
let enable_diffuse =
(view_bindings::clusterable_objects.data[light_id].flags &
mesh_view_types::POINT_LIGHT_FLAGS_AFFECTS_LIGHTMAPPED_MESH_DIFFUSE_BIT) != 0u;
#else // LIGHTMAP
let enable_diffuse = true;
#endif // LIGHTMAP

var shadow: f32 = 1.0;
if ((in.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
&& (view_bindings::clusterable_objects.data[light_id].flags &
mesh_view_types::POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
shadow = shadows::fetch_spot_shadow(
if (is_spot_light) {
// Reuse the point light calculations.
transmitted_light_contrib *= lighting::spot_light(
light_id,
in.world_position,
in.world_normal,
view_bindings::clusterable_objects.data[light_id].shadow_map_near_z,
&transmissive_lighting_input
);
}

let light_contrib = lighting::spot_light(light_id, &lighting_input, enable_diffuse);
direct_light += light_contrib * shadow;

#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION
// NOTE: We use the diffuse transmissive color, the second Lambertian lobe's calculated
// world position, inverted normal and view vectors, and the following simplified
// values for a fully diffuse transmitted light contribution approximation:
//
// roughness = 1.0;
// NdotV = 1.0;
// R = vec3<f32>(0.0) // doesn't really matter
// F_ab = vec2<f32>(0.1)
// F0 = vec3<f32>(0.0)
var transmitted_shadow: f32 = 1.0;
if ((in.flags & (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)) == (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)
&& (view_bindings::clusterable_objects.data[light_id].flags & mesh_view_types::POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
transmitted_shadow = shadows::fetch_spot_shadow(
light_id,
diffuse_transmissive_lobe_world_position,
-in.world_normal,
view_bindings::clusterable_objects.data[light_id].shadow_map_near_z,
);
}

let transmitted_light_contrib =
lighting::spot_light(light_id, &transmissive_lighting_input, enable_diffuse);
transmitted_light += transmitted_light_contrib * transmitted_shadow;
#endif
#endif // STANDARD_MATERIAL_DIFFUSE_TRANSMISSION
}

// directional lights (direct)
Expand Down
19 changes: 8 additions & 11 deletions crates/bevy_pbr/src/render/pbr_lighting.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -543,14 +543,13 @@ fn point_light(
(rangeAttenuation * derived_input.NdotL);
}

fn spot_light(
light_id: u32,
input: ptr<function, LightingInput>,
enable_diffuse: bool
) -> vec3<f32> {
// reuse the point light calculations
let point_light = point_light(light_id, input, enable_diffuse);

// Returns the additional attenuation that should be applied to the given spot
// light to give it the spot shape.
//
// The resulting value should be multiplied by the luminance that results from
// treating the spot light as thought it were a point light (i.e. the results of
pcwalton marked this conversation as resolved.
Show resolved Hide resolved
// calling `point_light`).
fn spot_light(light_id: u32, input: ptr<function, LightingInput>) -> f32 {
let light = &view_bindings::clusterable_objects.data[light_id];

// reconstruct spot dir from x/z and y-direction flag
Expand All @@ -566,9 +565,7 @@ fn spot_light(
// note we normalize here to get "l" from the filament listing. spot_dir is already normalized
let cd = dot(-spot_dir, normalize(light_to_frag));
let attenuation = saturate(cd * (*light).light_custom_data.z + (*light).light_custom_data.w);
let spot_attenuation = attenuation * attenuation;

return point_light * spot_attenuation;
return attenuation * attenuation;
}

fn directional_light(
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/render/shadows.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4<f32>, surface_normal: v
let offset_position = frag_position.xyz + normal_offset + depth_offset;

// similar largest-absolute-axis trick as above, but now with the offset fragment position
let frag_ls = offset_position.xyz - (*light).position_radius.xyz ;
let frag_ls = offset_position.xyz - (*light).position_radius.xyz;
let abs_position_ls = abs(frag_ls);
let major_axis_magnitude = max(abs_position_ls.x, max(abs_position_ls.y, abs_position_ls.z));

Expand Down
Loading