From dca295dde280156be34ace80190553024c4dda5e Mon Sep 17 00:00:00 2001 From: Yuval Tassa Date: Thu, 6 Aug 2026 16:06:43 -0700 Subject: [PATCH] Composite Filament planar reflections as Fresnel-weighted specular. PiperOrigin-RevId: 960554436 Change-Id: Ife6f5c760993ad185e9421cd7b3ce7fd06fffc90 --- src/render/filament/assets/phong_2d_reflect.mat | 9 +++++++-- src/render/filament/assets/phong_2d_uv_reflect.mat | 9 +++++++-- src/render/filament/assets/phong_color_reflect.mat | 9 +++++++-- src/render/filament/assets/phong_cube_reflect.mat | 9 +++++++-- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/render/filament/assets/phong_2d_reflect.mat b/src/render/filament/assets/phong_2d_reflect.mat index bbf7ba46..ab77a5fc 100644 --- a/src/render/filament/assets/phong_2d_reflect.mat +++ b/src/render/filament/assets/phong_2d_reflect.mat @@ -15,6 +15,7 @@ material { name : phong_2d_reflect, shadingModel : specularGlossiness, + postLightingBlending : add, flipUV : false, parameters : [ { type : float4, name : BaseColorFactor }, @@ -51,8 +52,12 @@ fragment { material.emissive = vec4( materialParams.BaseColorFactor.rgb * materialParams.EmissiveFactor, 0.0); - // Apply reflection. + // The reflection is radiance arriving from the mirror direction, so it is + // weighted by the Fresnel term and added after lighting. Reflectance is + // the reflectivity at normal incidence; grazing angles approach a mirror. vec4 reflection = texture(materialParams_Reflection, screen_uv); - material.baseColor.rgb = mix(material.baseColor.rgb, reflection.rgb, materialParams.Reflectance); + float f0 = materialParams.Reflectance; + float fresnel = f0 + (1.0 - f0) * pow(1.0 - getNdotV(), 5.0); + material.postLightingColor = vec4(reflection.rgb * fresnel, 0.0); } } diff --git a/src/render/filament/assets/phong_2d_uv_reflect.mat b/src/render/filament/assets/phong_2d_uv_reflect.mat index 4160167d..15456c77 100644 --- a/src/render/filament/assets/phong_2d_uv_reflect.mat +++ b/src/render/filament/assets/phong_2d_uv_reflect.mat @@ -15,6 +15,7 @@ material { name : phong_2d_uv_reflect, shadingModel : specularGlossiness, + postLightingBlending : add, flipUV : false, parameters : [ { type : float4, name : BaseColorFactor }, @@ -43,8 +44,12 @@ fragment { material.emissive = vec4( materialParams.BaseColorFactor.rgb * materialParams.EmissiveFactor, 0.0); - // Apply reflection. + // The reflection is radiance arriving from the mirror direction, so it is + // weighted by the Fresnel term and added after lighting. Reflectance is + // the reflectivity at normal incidence; grazing angles approach a mirror. vec4 reflection = texture(materialParams_Reflection, screen_uv); - material.baseColor.rgb = mix(material.baseColor.rgb, reflection.rgb, materialParams.Reflectance); + float f0 = materialParams.Reflectance; + float fresnel = f0 + (1.0 - f0) * pow(1.0 - getNdotV(), 5.0); + material.postLightingColor = vec4(reflection.rgb * fresnel, 0.0); } } diff --git a/src/render/filament/assets/phong_color_reflect.mat b/src/render/filament/assets/phong_color_reflect.mat index 48a9bfde..81b715c4 100644 --- a/src/render/filament/assets/phong_color_reflect.mat +++ b/src/render/filament/assets/phong_color_reflect.mat @@ -15,6 +15,7 @@ material { name : phong_color_reflect, shadingModel : specularGlossiness, + postLightingBlending : add, parameters : [ { type : float4, name : BaseColorFactor }, { type : float, name : SpecularFactor }, @@ -36,8 +37,12 @@ fragment { material.emissive = vec4( materialParams.BaseColorFactor.rgb * materialParams.EmissiveFactor, 0.0); - // Apply reflection. + // The reflection is radiance arriving from the mirror direction, so it is + // weighted by the Fresnel term and added after lighting. Reflectance is + // the reflectivity at normal incidence; grazing angles approach a mirror. vec4 reflection = texture(materialParams_Reflection, screen_uv); - material.baseColor.rgb = mix(material.baseColor.rgb, reflection.rgb, materialParams.Reflectance); + float f0 = materialParams.Reflectance; + float fresnel = f0 + (1.0 - f0) * pow(1.0 - getNdotV(), 5.0); + material.postLightingColor = vec4(reflection.rgb * fresnel, 0.0); } } diff --git a/src/render/filament/assets/phong_cube_reflect.mat b/src/render/filament/assets/phong_cube_reflect.mat index 98fe663b..b4eb1100 100644 --- a/src/render/filament/assets/phong_cube_reflect.mat +++ b/src/render/filament/assets/phong_cube_reflect.mat @@ -15,6 +15,7 @@ material { name : phong_cube_reflect, shadingModel : specularGlossiness, + postLightingBlending : add, flipUV : false, parameters : [ { type : float4, name : BaseColorFactor }, @@ -50,8 +51,12 @@ fragment { material.emissive = vec4( materialParams.BaseColorFactor.rgb * materialParams.EmissiveFactor, 0.0); - // Apply reflection. + // The reflection is radiance arriving from the mirror direction, so it is + // weighted by the Fresnel term and added after lighting. Reflectance is + // the reflectivity at normal incidence; grazing angles approach a mirror. vec4 reflection = texture(materialParams_Reflection, screen_uv); - material.baseColor.rgb = mix(material.baseColor.rgb, reflection.rgb, materialParams.Reflectance); + float f0 = materialParams.Reflectance; + float fresnel = f0 + (1.0 - f0) * pow(1.0 - getNdotV(), 5.0); + material.postLightingColor = vec4(reflection.rgb * fresnel, 0.0); } }