From 90da43535b22b201c4541dafe5eb24662976ab79 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Sun, 11 Apr 2021 21:54:00 -0400 Subject: [PATCH 01/12] Max Light test --- crates/bevy_pbr/src/render_graph/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 507cd3fdb2347..7967c4282d0ad 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -37,7 +37,7 @@ pub(crate) fn add_pbr_graph(world: &mut World) { node::STANDARD_MATERIAL, AssetRenderResourcesNode::::new(true), ); - graph.add_system_node(node::LIGHTS, LightsNode::new(10)); + graph.add_system_node(node::LIGHTS, LightsNode::new(256)); // TODO: replace these with "autowire" groups graph From c0fcbf2ff7a6177dd7ff938c2d05d5e6d49b3627 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Sun, 11 Apr 2021 22:03:45 -0400 Subject: [PATCH 02/12] Revert "Max Light test" This reverts commit 90da43535b22b201c4541dafe5eb24662976ab79. --- crates/bevy_pbr/src/render_graph/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 7967c4282d0ad..507cd3fdb2347 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -37,7 +37,7 @@ pub(crate) fn add_pbr_graph(world: &mut World) { node::STANDARD_MATERIAL, AssetRenderResourcesNode::::new(true), ); - graph.add_system_node(node::LIGHTS, LightsNode::new(256)); + graph.add_system_node(node::LIGHTS, LightsNode::new(10)); // TODO: replace these with "autowire" groups graph From 3410ac5478545b2c5321294a95f2a3fbf3eb7340 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Sun, 11 Apr 2021 22:05:23 -0400 Subject: [PATCH 03/12] Revert "Revert "Max Light test"" This reverts commit c0fcbf2ff7a6177dd7ff938c2d05d5e6d49b3627. --- crates/bevy_pbr/src/render_graph/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 507cd3fdb2347..7967c4282d0ad 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -37,7 +37,7 @@ pub(crate) fn add_pbr_graph(world: &mut World) { node::STANDARD_MATERIAL, AssetRenderResourcesNode::::new(true), ); - graph.add_system_node(node::LIGHTS, LightsNode::new(10)); + graph.add_system_node(node::LIGHTS, LightsNode::new(256)); // TODO: replace these with "autowire" groups graph From 73212014f9e184279e4882ff6e7fbd6f5d6d5d8a Mon Sep 17 00:00:00 2001 From: Josh015 Date: Sun, 11 Apr 2021 22:06:55 -0400 Subject: [PATCH 04/12] Revert "Revert "Revert "Max Light test""" This reverts commit 3410ac5478545b2c5321294a95f2a3fbf3eb7340. --- crates/bevy_pbr/src/render_graph/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 7967c4282d0ad..507cd3fdb2347 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -37,7 +37,7 @@ pub(crate) fn add_pbr_graph(world: &mut World) { node::STANDARD_MATERIAL, AssetRenderResourcesNode::::new(true), ); - graph.add_system_node(node::LIGHTS, LightsNode::new(256)); + graph.add_system_node(node::LIGHTS, LightsNode::new(10)); // TODO: replace these with "autowire" groups graph From 6597c03e9443477f2326dff563cc766e5e59fea8 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Mon, 12 Apr 2021 18:46:50 -0400 Subject: [PATCH 05/12] First pass of spherical area lights. --- crates/bevy_pbr/src/light.rs | 4 ++- .../src/render_graph/pbr_pipeline/pbr.frag | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 149bfd92b2551..bc334ae5bf39a 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -17,6 +17,7 @@ pub struct Light { pub depth: Range, pub intensity: f32, pub range: f32, + pub radius: f32, } impl Default for Light { @@ -27,6 +28,7 @@ impl Default for Light { fov: f32::to_radians(60.0), intensity: 200.0, range: 20.0, + radius: 0.0, } } } @@ -59,7 +61,7 @@ impl LightRaw { LightRaw { proj: proj.to_cols_array_2d(), pos: [x, y, z, 1.0 / (light.range * light.range)], // pos.w is the attenuation. - color, + color: [color[0], color[1], color[2], light.radius], } } } diff --git a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag index 790b50af2fd89..b489c592f630c 100644 --- a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag @@ -340,25 +340,45 @@ void main() { // Diffuse strength inversely related to metallicity vec3 diffuseColor = output_color.rgb * (1.0 - metallic); + vec3 R = reflect(-V, N); + // accumulate color vec3 light_accum = vec3(0.0); for (int i = 0; i < int(NumLights.x) && i < MAX_LIGHTS; ++i) { Light light = SceneLights[i]; vec3 lightDir = light.pos.xyz - v_WorldPosition.xyz; - vec3 L = normalize(lightDir); - float rangeAttenuation = getDistanceAttenuation(lightDir, light.pos.w); + // Diffuse. + vec3 L = normalize(lightDir); vec3 H = normalize(L + V); float NoL = saturate(dot(N, L)); float NoH = saturate(dot(N, H)); float LoH = saturate(dot(L, H)); - vec3 specular = specular(F0, roughness, H, NdotV, NoL, NoH, LoH); vec3 diffuse = diffuseColor * Fd_Burley(roughness, NdotV, NoL, LoH); + // Specular. + // Representative Point Area Lights. + // cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p14-16 + float radius = light.color.a; + vec3 centerToRay = dot(lightDir, R) * R - lightDir; + vec3 closestPoint = lightDir + centerToRay * saturate(radius * inversesqrt(dot(centerToRay, centerToRay))); + float LspecLengthInverse = inversesqrt(dot(closestPoint, closestPoint)); + float a = roughness * roughness; + float normalizationFactor = a / saturate(a + (radius * 0.5 * LspecLengthInverse)); + float specularIntensity = normalizationFactor * normalizationFactor; + + L = normalize(closestPoint * LspecLengthInverse); + H = normalize(L + V); + NoL = saturate(dot(N, L)); + NoH = saturate(dot(N, H)); + LoH = saturate(dot(L, H)); + + vec3 specular = specularIntensity * specular(F0, roughness, H, NdotV, NoL, NoH, LoH); + // Lout = f(v,l) Φ / { 4 π d^2 }⟨n⋅l⟩ // where // f(v,l) = (f_d(v,l) + f_r(v,l)) * light_color From c7ce9cb457c6f68a2fc59e150d7ec593774eb733 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Mon, 12 Apr 2021 19:19:26 -0400 Subject: [PATCH 06/12] Corrected roughness. --- crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag index b489c592f630c..1a2e4f8c244cf 100644 --- a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag @@ -367,7 +367,7 @@ void main() { vec3 centerToRay = dot(lightDir, R) * R - lightDir; vec3 closestPoint = lightDir + centerToRay * saturate(radius * inversesqrt(dot(centerToRay, centerToRay))); float LspecLengthInverse = inversesqrt(dot(closestPoint, closestPoint)); - float a = roughness * roughness; + float a = roughness; float normalizationFactor = a / saturate(a + (radius * 0.5 * LspecLengthInverse)); float specularIntensity = normalizationFactor * normalizationFactor; From e236580e2c660b1ea48f869e3e6db5ef02bbb3cf Mon Sep 17 00:00:00 2001 From: Josh015 Date: Mon, 12 Apr 2021 19:55:56 -0400 Subject: [PATCH 07/12] Small code cleanup and optimization. --- crates/bevy_pbr/src/light.rs | 6 ++++-- crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index bc334ae5bf39a..35bae98bb870a 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -57,11 +57,13 @@ impl LightRaw { // premultiply color by intensity // we don't use the alpha at all, so no reason to multiply only [0..3] - let color: [f32; 4] = (light.color * light.intensity).into(); + let mut color: [f32; 4] = (light.color * light.intensity).into(); + color[3] = light.radius; + LightRaw { proj: proj.to_cols_array_2d(), pos: [x, y, z, 1.0 / (light.range * light.range)], // pos.w is the attenuation. - color: [color[0], color[1], color[2], light.radius], + color, } } } diff --git a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag index 1a2e4f8c244cf..0d721ff9eddaa 100644 --- a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag @@ -194,12 +194,12 @@ vec3 fresnel(vec3 f0, float LoH) { // Cook-Torrance approximation of the microfacet model integration using Fresnel law F to model f_m // f_r(v,l) = { D(h,α) G(v,l,α) F(v,h,f0) } / { 4 (n⋅v) (n⋅l) } vec3 specular(vec3 f0, float roughness, const vec3 h, float NoV, float NoL, - float NoH, float LoH) { + float NoH, float LoH, float specularIntensity) { float D = D_GGX(roughness, NoH, h); float V = V_SmithGGXCorrelated(roughness, NoV, NoL); vec3 F = fresnel(f0, LoH); - return (D * V) * F; + return (specularIntensity * D * V) * F; } // Diffuse BRDF @@ -362,12 +362,12 @@ void main() { // Specular. // Representative Point Area Lights. - // cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p14-16 + // see http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p14-16 + float a = roughness; float radius = light.color.a; vec3 centerToRay = dot(lightDir, R) * R - lightDir; vec3 closestPoint = lightDir + centerToRay * saturate(radius * inversesqrt(dot(centerToRay, centerToRay))); float LspecLengthInverse = inversesqrt(dot(closestPoint, closestPoint)); - float a = roughness; float normalizationFactor = a / saturate(a + (radius * 0.5 * LspecLengthInverse)); float specularIntensity = normalizationFactor * normalizationFactor; @@ -377,7 +377,7 @@ void main() { NoH = saturate(dot(N, H)); LoH = saturate(dot(L, H)); - vec3 specular = specularIntensity * specular(F0, roughness, H, NdotV, NoL, NoH, LoH); + vec3 specular = specular(F0, roughness, H, NdotV, NoL, NoH, LoH, specularIntensity); // Lout = f(v,l) Φ / { 4 π d^2 }⟨n⋅l⟩ // where From d270fed56a64a5420cf0ebf975b2e9397465b2e3 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Mon, 12 Apr 2021 20:02:31 -0400 Subject: [PATCH 08/12] Switched to using correct N.L in lighting equation --- .../src/render_graph/pbr_pipeline/pbr.frag | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag index 0d721ff9eddaa..9782d9435d547 100644 --- a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag @@ -351,15 +351,6 @@ void main() { float rangeAttenuation = getDistanceAttenuation(lightDir, light.pos.w); - // Diffuse. - vec3 L = normalize(lightDir); - vec3 H = normalize(L + V); - float NoL = saturate(dot(N, L)); - float NoH = saturate(dot(N, H)); - float LoH = saturate(dot(L, H)); - - vec3 diffuse = diffuseColor * Fd_Burley(roughness, NdotV, NoL, LoH); - // Specular. // Representative Point Area Lights. // see http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p14-16 @@ -371,13 +362,23 @@ void main() { float normalizationFactor = a / saturate(a + (radius * 0.5 * LspecLengthInverse)); float specularIntensity = normalizationFactor * normalizationFactor; - L = normalize(closestPoint * LspecLengthInverse); + vec3 L = normalize(closestPoint * LspecLengthInverse); + vec3 H = normalize(L + V); + float NoL = saturate(dot(N, L)); + float NoH = saturate(dot(N, H)); + float LoH = saturate(dot(L, H)); + + vec3 specular = specular(F0, roughness, H, NdotV, NoL, NoH, LoH, specularIntensity); + + // Diffuse. + // Comes after specular since its NoL is used in the lighting equation. + L = normalize(lightDir); H = normalize(L + V); NoL = saturate(dot(N, L)); NoH = saturate(dot(N, H)); LoH = saturate(dot(L, H)); - vec3 specular = specular(F0, roughness, H, NdotV, NoL, NoH, LoH, specularIntensity); + vec3 diffuse = diffuseColor * Fd_Burley(roughness, NdotV, NoL, LoH); // Lout = f(v,l) Φ / { 4 π d^2 }⟨n⋅l⟩ // where From 35b10a05c8891f699eaa3bd8872045c6e6a13c9c Mon Sep 17 00:00:00 2001 From: Josh015 Date: Mon, 12 Apr 2021 20:11:24 -0400 Subject: [PATCH 09/12] fmt --- crates/bevy_pbr/src/light.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 35bae98bb870a..9731358716b35 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -59,7 +59,7 @@ impl LightRaw { // we don't use the alpha at all, so no reason to multiply only [0..3] let mut color: [f32; 4] = (light.color * light.intensity).into(); color[3] = light.radius; - + LightRaw { proj: proj.to_cols_array_2d(), pos: [x, y, z, 1.0 / (light.range * light.range)], // pos.w is the attenuation. From 1469079d0fa8846a79787369cf8cbb36f2d1ce04 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Sat, 17 Apr 2021 20:38:20 -0400 Subject: [PATCH 10/12] Applied packing fix to PointLightUniform --- crates/bevy_pbr/src/light.rs | 7 +++---- crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag | 7 ++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 941543394e01e..8204c76939bc1 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -30,7 +30,7 @@ impl Default for PointLight { pub(crate) struct PointLightUniform { pub pos: [f32; 4], pub color: [f32; 4], - pub inverse_range_squared: f32, + pub light_params: [f32; 4], } unsafe impl Byteable for PointLightUniform {} @@ -41,13 +41,12 @@ impl PointLightUniform { // premultiply color by intensity // we don't use the alpha at all, so no reason to multiply only [0..3] - let mut color: [f32; 4] = (light.color * light.intensity).into(); - color[3] = light.radius; + let color: [f32; 4] = (light.color * light.intensity).into(); PointLightUniform { pos: [x, y, z, 1.0], color, - inverse_range_squared: 1.0 / (light.range * light.range), + light_params: [1.0 / (light.range * light.range), light.radius, 0.0, 0.0], } } } diff --git a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag index 796a12d392f64..40ab6fe0d270d 100644 --- a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag @@ -39,7 +39,7 @@ const int MAX_LIGHTS = 10; struct PointLight { vec4 pos; vec4 color; - float inverseRangeSquared; + vec4 lightParams; }; layout(location = 0) in vec3 v_WorldPosition; @@ -348,19 +348,20 @@ void main() { vec3 light_to_frag = light.pos.xyz - v_WorldPosition.xyz; float distance_square = dot(light_to_frag, light_to_frag); float rangeAttenuation = - getDistanceAttenuation(distance_square, light.inverseRangeSquared); + getDistanceAttenuation(distance_square, light.lightParams.r); // Specular. // Representative Point Area Lights. // see http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p14-16 float a = roughness; - float radius = light.color.a; + float radius = light.lightParams.g; vec3 centerToRay = dot(light_to_frag, R) * R - light_to_frag; vec3 closestPoint = light_to_frag + centerToRay * saturate(radius * inversesqrt(dot(centerToRay, centerToRay))); float LspecLengthInverse = inversesqrt(dot(closestPoint, closestPoint)); float normalizationFactor = a / saturate(a + (radius * 0.5 * LspecLengthInverse)); float specularIntensity = normalizationFactor * normalizationFactor; + // TODO: This normalize() might be redundant! vec3 L = normalize(closestPoint * LspecLengthInverse); vec3 H = normalize(L + V); float NoL = saturate(dot(N, L)); From 5f80db21b18bb5120a3e7843729e6c5d23c26028 Mon Sep 17 00:00:00 2001 From: Josh015 Date: Sat, 17 Apr 2021 20:46:20 -0400 Subject: [PATCH 11/12] Removed redundant normalize() in shader --- crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag index 40ab6fe0d270d..3891e90e0ba5d 100644 --- a/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag +++ b/crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag @@ -361,8 +361,7 @@ void main() { float normalizationFactor = a / saturate(a + (radius * 0.5 * LspecLengthInverse)); float specularIntensity = normalizationFactor * normalizationFactor; - // TODO: This normalize() might be redundant! - vec3 L = normalize(closestPoint * LspecLengthInverse); + vec3 L = closestPoint * LspecLengthInverse; // normalize() equivalent? vec3 H = normalize(L + V); float NoL = saturate(dot(N, L)); float NoH = saturate(dot(N, H)); From 8ae596ff29db0c9b7077a6887ad493149bec745b Mon Sep 17 00:00:00 2001 From: Josh015 Date: Mon, 19 Apr 2021 16:30:18 -0400 Subject: [PATCH 12/12] Restored a comment lost in the merge --- crates/bevy_pbr/src/light.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 8204c76939bc1..7e5b9766a4dd9 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -30,6 +30,7 @@ impl Default for PointLight { pub(crate) struct PointLightUniform { pub pos: [f32; 4], pub color: [f32; 4], + // storing as a `[f32; 4]` for memory alignement pub light_params: [f32; 4], }