From b18dde9b25608b87ef183249cdf9174f7e5f57a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 19 Jul 2025 00:06:09 +0800 Subject: [PATCH 01/33] squash merge --- .../Shaders/GrassLighting/GrassLighting.hlsli | 19 +- package/Shaders/Lighting.hlsl | 296 ++++++++++-------- package/Shaders/RunGrass.hlsl | 32 +- 3 files changed, 205 insertions(+), 142 deletions(-) diff --git a/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli b/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli index f85808a56d..30138ce4bf 100644 --- a/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli +++ b/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli @@ -1,12 +1,27 @@ +#include "Common/BRDF.hlsli" + namespace GrassLighting { - float3 GetLightSpecularInput(float3 L, float3 V, float3 N, float3 lightColor, float shininess) + float3 GetLightSpecularInput(float3 L, float3 V, float3 N, float3 lightColor, float roughness, float3 F0) { float3 H = normalize(V + L); - float HdotN = saturate(dot(H, N)); +#if defined(VANILLA_FRESNEL_DL) + float NdotL = saturate(dot(N, L)); + float NdotV = saturate(dot(N, V)); + float NdotH = saturate(dot(N, H)); + float VdotH = saturate(dot(V, H)); + float D = BRDF::D_GGX(roughness, NdotH); + float G = BRDF::Vis_SmithJointApprox(roughness, NdotL, NdotV); + float3 F = BRDF::F_Schlick(F0, VdotH); + float3 specular = D * G * F; + return specular * lightColor * NdotL; +#else + float shininess = (1.0 - roughness) * 100.f; + float HdotN = saturate(dot(H, N)); float lightColorMultiplier = exp2(shininess * log2(HdotN)); return lightColor * lightColorMultiplier.xxx; +#endif } float3 TransformNormal(float3 normal) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 7e88fae3a1..a72b4b29ee 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1,3 +1,4 @@ +#include "Common/BRDF.hlsli" #include "Common/Color.hlsli" #include "Common/FrameBuffer.hlsli" #include "Common/GBuffer.hlsli" @@ -27,6 +28,10 @@ # define LOD #endif +#if defined(VANILLA_FRESNEL_DL) +# define VANILLA_FRESNEL +#endif + struct VS_INPUT { float4 Position : POSITION0; @@ -661,7 +666,7 @@ float ProcessSparkleColor(float color) } # endif -float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float3 lightColor, float shininess, float2 uv) +float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float3 lightColor, float3 specularColor, float shininess, float2 uv) { float3 H = normalize(V + L); float HdotN = 1.0; @@ -676,7 +681,17 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # if defined(SPECULAR) float lightColorMultiplier = exp2(shininess * log2(HdotN)); - +# if defined(VANILLA_FRESNEL_DL) + float NdotV = saturate(dot(N, V)); + float NdotL = saturate(dot(N, L)); + float NdotH = saturate(dot(N, H)); + float HdotV = saturate(dot(H, V)); + float roughness = pow(2.0 / (shininess + 2.0), 0.25); + float D = BRDF::D_GGX(roughness, HdotN); + float3 F = BRDF::F_Schlick(specularColor, HdotV); + float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); + lightColorMultiplier = max(D * G * F * NdotL, 0.0); +# endif # elif defined(SPARKLE) float lightColorMultiplier = 0; # else @@ -2185,6 +2200,124 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float pbrGlossiness = 1 - pbrSurfaceProperties.Roughness; # endif // TRUE_PBR +# if defined(VANILLA_FRESNEL) + float3 F0 = 0.04; +# else + float3 F0 = 0.0; +# endif + float roughness = 1.0; + +# if defined(VANILLA_FRESNEL) +# if defined(SPECULAR) && !defined(TRUE_PBR) + F0 = saturate(glossiness * SpecularColor.xyz); + roughness = pow(2.0 / (shininess + 2.0), 0.25); +# elif defined(EYE) + F0 = 0.027; + roughness = 0.1; +# endif +# endif + +# if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) + float envMask = EnvmapData.x * MaterialData.x; + + float viewNormalAngle = dot(worldNormal.xyz, viewDirection); + float3 envSamplingPoint = (viewNormalAngle * 2) * worldNormal.xyz - viewDirection; + + if (envMask > 0.0) { + if (EnvmapData.y) { + envMask *= TexEnvMaskSampler.Sample(SampEnvMaskSampler, uv).x; + } else { + envMask *= glossiness; + } + } + + float3 envColor = 0.0; + bool dynamicCubemap = false; +# if defined(VANILLA_FRESNEL) + dynamicCubemap = true; +# endif + + if (envMask > 0.0) { +# if defined(DYNAMIC_CUBEMAPS) + uint2 envSize; + TexEnvSampler.GetDimensions(envSize.x, envSize.y); + +# if defined(CREATOR) +# if defined(EMAT) + if (envSize.x == 1 && envSize.y == 1 || complexMaterial || SharedData::cubemapCreatorSettings.Enabled) { +# else + if (envSize.x == 1 && envSize.y == 1 || SharedData::cubemapCreatorSettings.Enabled) { +# endif +# else +# if defined(EMAT) + if (envSize.x == 1 && envSize.y == 1 || complexMaterial) { +# else + if (envSize.x == 1 && envSize.y == 1) { +# endif +# endif + + dynamicCubemap = true; + +# if defined(EMAT) + if (!complexMaterial) +# endif + { + // Dynamic Cubemap Creator sets this value to black, if it is anything but black it is wrong + float3 envColorTest = TexEnvSampler.SampleLevel(SampEnvSampler, float3(0.0, 1.0, 0.0), 15).xyz; + dynamicCubemap = all(envColorTest == 0.0); + } + +# if defined(CREATOR) + if (SharedData::cubemapCreatorSettings.Enabled) { + dynamicCubemap = true; + } +# endif + + if (dynamicCubemap) { + float4 envColorBase = TexEnvSampler.SampleLevel(SampEnvSampler, float3(1.0, 0.0, 0.0), 15); + float envRoughness = 1.0; + + if (envColorBase.a < 1.0) { + F0 = Color::GammaToLinear(envColorBase.rgb); + envRoughness = envColorBase.a; + } else { + F0 = 1.0; + envRoughness = 1.0 / 7.0; + } + +# if defined(CREATOR) + if (SharedData::cubemapCreatorSettings.Enabled) { + F0 = SharedData::cubemapCreatorSettings.CubemapColor.rgb; + envRoughness = SharedData::cubemapCreatorSettings.CubemapColor.a; + } +# endif + +# if defined(EMAT) + float complexMaterialRoughness = 1.0 - complexMaterialColor.y; + envRoughness = lerp(envRoughness, complexMaterialRoughness, complexMaterial); + F0 = lerp(F0, complexSpecular, complexMaterial); +# endif + + envMask = saturate(envMask); + F0 = lerp(glossiness * SpecularColor.xyz, F0, envMask); + roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); + } + } +# endif + +# if defined(EYE) && defined(VANILLA_FRESNEL) + F0 = 0.027; + roughness = 0.1; +# endif + + if (!dynamicCubemap) { + float3 envColorBase = Color::GammaToLinear(TexEnvSampler.Sample(SampEnvSampler, envSamplingPoint).xyz); + envColor = envColorBase.xyz * envMask; + } + } + +# endif // defined (ENVMAP) || defined (MULTI_LAYER_PARALLAX) || defined(EYE) + float porosity = 1.0; # if defined(SKYLIGHTING) @@ -2430,11 +2563,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } else { # if defined(SPECULAR) - lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, shininess, uv); + lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, F0, shininess, uv); # endif } # elif defined(SPECULAR) || defined(SPARKLE) - lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, shininess, uv); + lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, F0, shininess, uv); # endif } @@ -2511,11 +2644,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) transmissionColor += lightTransmissionColor; } else { # if defined(SPECULAR) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); # endif } # elif defined(SPECULAR) || (defined(SPARKLE) && !defined(SNOW)) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); # endif // defined (SPECULAR) || (defined (SPARKLE) && !defined(SNOW)) lightsDiffuseColor += lightDiffuseColor; @@ -2656,11 +2789,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) transmissionColor += lightTransmissionColor; } else { # if defined(SPECULAR) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); # endif } # elif defined(SPECULAR) || (defined(SPARKLE) && !defined(SNOW)) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); # endif lightsDiffuseColor += lightDiffuseColor; @@ -2767,99 +2900,19 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # endif -# if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) - float envMask = EnvmapData.x * MaterialData.x; - - float viewNormalAngle = dot(worldNormal.xyz, viewDirection); - float3 envSamplingPoint = (viewNormalAngle * 2) * worldNormal.xyz - viewDirection; - - if (envMask > 0.0) { - if (EnvmapData.y) { - envMask *= TexEnvMaskSampler.Sample(SampEnvMaskSampler, uv).x; - } else { - envMask *= glossiness; - } - } - - float3 envColor = 0.0; - bool dynamicCubemap = false; - -# if defined(DYNAMIC_CUBEMAPS) - float3 F0 = 0.0; - float envRoughness = 1.0; + float3 reflectance = 0; +# if defined(DYNAMIC_CUBEMAPS) + if (any(F0 > 0.0)) { +# if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) + if (dynamicCubemap) # endif - - if (envMask > 0.0) { -# if defined(DYNAMIC_CUBEMAPS) - uint2 envSize; - TexEnvSampler.GetDimensions(envSize.x, envSize.y); - -# if defined(EMAT) - if (envSize.x == 1 && envSize.y == 1 || complexMaterial) { -# else - if (envSize.x == 1 && envSize.y == 1) { -# endif - - dynamicCubemap = true; - -# if defined(EMAT) - if (!complexMaterial) -# endif - { - // Dynamic Cubemap Creator sets this value to black, if it is anything but black it is wrong - float3 envColorTest = TexEnvSampler.SampleLevel(SampEnvSampler, float3(0.0, 1.0, 0.0), 15).xyz; - dynamicCubemap = all(envColorTest == 0.0); - } - -# if defined(CREATOR) - if (SharedData::cubemapCreatorSettings.Enabled) { - dynamicCubemap = true; - } -# endif - - if (dynamicCubemap) { - float4 envColorBase = TexEnvSampler.SampleLevel(SampEnvSampler, float3(1.0, 0.0, 0.0), 15); - - if (envColorBase.a < 1.0) { - F0 = Color::GammaToLinear(envColorBase.rgb); - envRoughness = envColorBase.a; - } else { - F0 = 1.0; - envRoughness = 1.0 / 7.0; - } - -# if defined(CREATOR) - if (SharedData::cubemapCreatorSettings.Enabled) { - F0 = SharedData::cubemapCreatorSettings.CubemapColor.rgb; - envRoughness = SharedData::cubemapCreatorSettings.CubemapColor.a; - } -# endif - -# if defined(EMAT) - float complexMaterialRoughness = 1.0 - complexMaterialColor.y; - envRoughness = lerp(envRoughness, complexMaterialRoughness, complexMaterial); - F0 = lerp(F0, complexSpecular, complexMaterial); -# endif - - if (any(F0 > 0.0)) -# if defined(SKYLIGHTING) - envColor = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, envRoughness, F0, skylightingSH) * envMask; -# else - envColor = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, envRoughness, F0) * envMask; -# endif - else - envColor = 0.0; - } - } +# if defined(SKYLIGHTING) + reflectance = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, roughness, F0, skylightingSH); +# else + reflectance = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, roughness, F0); # endif - - if (!dynamicCubemap) { - float3 envColorBase = Color::GammaToLinear(TexEnvSampler.Sample(SampEnvSampler, envSamplingPoint).xyz); - envColor = envColorBase.xyz * envMask; - } } - -# endif // defined (ENVMAP) || defined (MULTI_LAYER_PARALLAX) || defined(EYE) +# endif float2 screenMotionVector = MotionBlur::GetSSMotionVector(input.WorldPosition, input.PreviousWorldPosition, eyeIndex); @@ -3040,7 +3093,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # endif // MULTI_LAYER_PARALLAX -# if defined(SPECULAR) +# if defined(SPECULAR) && !defined(VANILLA_FRESNEL_DL) # if defined(HAIR) && defined(CS_HAIR) if (!SharedData::hairSpecularSettings.Enabled) # endif @@ -3058,7 +3111,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) diffuseColor = reflectionDiffuseColor; -# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) +# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && !(defined(VANILLA_FRESNEL) && !defined(EYE)) # if defined(DYNAMIC_CUBEMAPS) if (!dynamicCubemap) # endif @@ -3138,9 +3191,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) baseColor.xyz = 0.0; specularColor = 0.0; diffuseColor = 0.0; - dynamicCubemap = true; - envColor = 1.0; - envRoughness = 0.0; + reflectance = 1.0; + roughness = 0.0; color.xyz = 0; # endif @@ -3283,11 +3335,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Specular = float4(specularColor, psout.Diffuse.w); psout.Albedo = float4(outputAlbedo, psout.Diffuse.w); - float outGlossiness = saturate(glossiness * SSRParams.w); - # if defined(HAIR) && defined(CS_HAIR) if (SharedData::hairSpecularSettings.Enabled) { - outGlossiness = 1.0 - (SharedData::hairSpecularSettings.HairMode == 1 ? 1.0 : pow(abs(2.0 / (glossiness * 0.5 + 2.0)), 0.25)); + roughness = (SharedData::hairSpecularSettings.HairMode == 1 ? 1.0 : pow(abs(2.0 / (glossiness * 0.5 + 2.0)), 0.25)); } # endif @@ -3306,26 +3356,26 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (SharedData::hairSpecularSettings.Enabled) { # if defined(WETNESS_EFFECTS) psout.Reflectance = float4(indirectSpecularLobeWeightPrim + indirectSpecularLobeWeightSec + wetnessReflectance, psout.Diffuse.w); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), lerp(outGlossiness, max(outGlossiness, wetnessGlossinessSpecular), wetnessGlossinessSpecular), psout.Diffuse.w); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), lerp(1.0 - roughness, max(1 - roughness, wetnessGlossinessSpecular), wetnessGlossinessSpecular), psout.Diffuse.w); # else psout.Reflectance = float4(indirectSpecularLobeWeightPrim + indirectSpecularLobeWeightSec, psout.Diffuse.w); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), outGlossiness, psout.Diffuse.w); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), 1.0 - roughness, psout.Diffuse.w); # endif } else { # if defined(WETNESS_EFFECTS) - psout.Reflectance = float4(wetnessReflectance, psout.Diffuse.w); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), lerp(outGlossiness, max(outGlossiness, wetnessGlossinessSpecular), wetnessGlossinessSpecular), psout.Diffuse.w); + psout.Reflectance = float4(max(reflectance, wetnessReflectance), psout.Diffuse.w); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), lerp(1.0 - roughness, max(1 - roughness, wetnessGlossinessSpecular), wetnessGlossinessSpecular), psout.Diffuse.w); # else - psout.Reflectance = float4(0.0.xxx, psout.Diffuse.w); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), outGlossiness, psout.Diffuse.w); + psout.Reflectance = float4(reflectance, psout.Diffuse.w); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), 1.0 - roughness, psout.Diffuse.w); # endif } # elif defined(WETNESS_EFFECTS) - psout.Reflectance = float4(wetnessReflectance, psout.Diffuse.w); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), lerp(outGlossiness, max(outGlossiness, wetnessGlossinessSpecular), wetnessGlossinessSpecular), psout.Diffuse.w); + psout.Reflectance = float4(max(reflectance, wetnessReflectance), psout.Diffuse.w); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), lerp(1.0 - roughness, max(1 - roughness, wetnessGlossinessSpecular), wetnessGlossinessSpecular), psout.Diffuse.w); # else - psout.Reflectance = float4(0.0.xxx, psout.Diffuse.w); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), outGlossiness, psout.Diffuse.w); + psout.Reflectance = float4(reflectance, psout.Diffuse.w); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), 1.0 - roughness, psout.Diffuse.w); # endif # if defined(SNOW) @@ -3338,20 +3388,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Parameters.w = psout.Diffuse.w; # endif -# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) -# if defined(DYNAMIC_CUBEMAPS) - if (dynamicCubemap) { -# if defined(WETNESS_EFFECTS) - psout.Reflectance.xyz = max(envColor, wetnessReflectance); - psout.NormalGlossiness.z = lerp(1.0 - envRoughness, max(1.0 - envRoughness, wetnessGlossinessSpecular), wetnessGlossinessSpecular); -# else - psout.Reflectance.xyz = envColor; - psout.NormalGlossiness.z = 1.0 - envRoughness; -# endif - } -# endif -# endif - # if defined(SSS) && defined(SKIN) psout.Masks = float4(saturate(baseColor.a), !(Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::IsBeastRace), Color::RGBToYCoCg(directionalAmbientColor).x, psout.Diffuse.w); # else diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index d2af9390dc..fe0cde296e 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -15,6 +15,10 @@ # undef IBL #endif +#if defined(VANILLA_FRESNEL_DL) +# define VANILLA_FRESNEL +#endif + struct VS_INPUT { float4 Position : POSITION0; @@ -331,14 +335,9 @@ struct PS_OUTPUT float4 NormalGlossiness : SV_Target2; float4 Albedo : SV_Target3; float4 Specular : SV_Target4; -# if defined(TRUE_PBR) float4 Reflectance : SV_Target5; -# endif // TRUE_PBR float4 Masks : SV_Target6; -# if defined(TRUE_PBR) - float4 Parameters : SV_Target7; -# endif // TRUE_PBR -# endif // RENDER_DEPTH +# endif // RENDER_DEPTH }; #else struct PS_OUTPUT @@ -530,6 +529,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) baseColor.xyz *= SharedData::grassLightingSettings.BasicGrassBrightness; # endif // !TRUE_PBR + float3 F0 = specColor.w * SharedData::grassLightingSettings.SpecularStrength; + float roughness = saturate(1.0 - SharedData::grassLightingSettings.Glossiness * 0.01); + # if defined(TRUE_PBR) float4 rawRMAOS = TexRMAOSSampler.SampleBias(SampRMAOSSampler, input.TexCoord.xy, SharedData::MipBias) * float4(PBRParams1.x, 1, 1, PBRParams1.y); @@ -621,7 +623,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float3 sss = dirLightColor * saturate(-dirLightAngle); if (complex) - lightsSpecularColor += GrassLighting::GetLightSpecularInput(DirLightDirection, viewDirection, normal, dirLightColor, SharedData::grassLightingSettings.Glossiness); + lightsSpecularColor += GrassLighting::GetLightSpecularInput(DirLightDirection, viewDirection, normal, dirLightColor, roughness, F0); # endif # if defined(LIGHT_LIMIT_FIX) @@ -687,7 +689,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) lightsDiffuseColor += lightDiffuseColor; if (complex) - lightsSpecularColor += GrassLighting::GetLightSpecularInput(normalizedLightDirection, viewDirection, normal, lightColor, SharedData::grassLightingSettings.Glossiness) * intensityMultiplier; + lightsSpecularColor += GrassLighting::GetLightSpecularInput(normalizedLightDirection, viewDirection, normal, lightColor, roughness, F0) * intensityMultiplier; # endif } } @@ -765,7 +767,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif specularColor += lightsSpecularColor; +# if !defined(VANILLA_FRESNEL_DL) specularColor *= specColor.w * SharedData::grassLightingSettings.SpecularStrength; +# endif specularColor = Color::GammaToLinear(specularColor); # endif @@ -790,10 +794,18 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Albedo = float4(Color::LinearToGamma(indirectDiffuseLobeWeight), 1); psout.NormalGlossiness = float4(GBuffer::EncodeNormal(normalVS), 1 - pbrSurfaceProperties.Roughness, 1); psout.Reflectance = float4(indirectSpecularLobeWeight, 1); - psout.Parameters = float4(0, 0, 1, 1); # else + +# if defined(DYNAMIC_CUBEMAPS) && (defined(VANILLA_FRESNEL) || defined(TRUE_PBR)) + float2 specularBDRF = DynamicCubemaps::EnvBRDFApprox(roughness, saturate(dot(viewDirection, normalVS))); + float3 reflectance = F0 * specularBDRF.x + specularBDRF.y; +# else + float3 reflectance = 0; +# endif + + psout.Reflectance = float4(reflectance, 1); psout.Albedo = float4(albedo, 1); - psout.NormalGlossiness = float4(GBuffer::EncodeNormal(normalVS), specColor.w, 1); + psout.NormalGlossiness = float4(GBuffer::EncodeNormal(normalVS), 1.0 - roughness, 1); # endif psout.Specular = float4(specularColor, 1); From c4c6209c220e0c2d30ac3835cbff13651e0ed9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Mon, 28 Jul 2025 15:03:19 +0800 Subject: [PATCH 02/33] fix flickering --- package/Shaders/Lighting.hlsl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index a72b4b29ee..1631fc2006 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1031,8 +1031,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if !defined(TRUE_PBR) # if defined(LANDSCAPE) float shininess = dot(input.LandBlendWeights1, LandscapeTexture1to4IsSpecPower) + input.LandBlendWeights2.x * LandscapeTexture5to6IsSpecPower.x + input.LandBlendWeights2.y * LandscapeTexture5to6IsSpecPower.y; -# else +# elif defined(SPECULAR) float shininess = SpecularColor.w; +# else + float shininess = 0.0; # endif // defined (LANDSCAPE) # endif @@ -2299,7 +2301,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif envMask = saturate(envMask); +# if defined(SPECULAR) F0 = lerp(glossiness * SpecularColor.xyz, F0, envMask); +# endif roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); } } From b6e34f78312f57cf96bf9234c1737037f25bd08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Thu, 31 Jul 2025 14:18:58 +0800 Subject: [PATCH 03/33] fix complex material --- package/Shaders/Lighting.hlsl | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 1631fc2006..31baa3f2c4 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1903,7 +1903,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) complexMaterial = complexMaterial && complexMaterialColor.y > (4.0 / 255.0); shininess = lerp(shininess, shininess * complexMaterialColor.y, complexMaterial); if (complexMaterial) { - complexSpecular = lerp(1.0, baseColor.xyz, complexMaterialColor.z); + complexSpecular = lerp(0.04, baseColor.xyz, complexMaterialColor.z); baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z); } @@ -2244,18 +2244,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) uint2 envSize; TexEnvSampler.GetDimensions(envSize.x, envSize.y); -# if defined(CREATOR) -# if defined(EMAT) - if (envSize.x == 1 && envSize.y == 1 || complexMaterial || SharedData::cubemapCreatorSettings.Enabled) { -# else - if (envSize.x == 1 && envSize.y == 1 || SharedData::cubemapCreatorSettings.Enabled) { -# endif -# else -# if defined(EMAT) +# if defined(EMAT) if (envSize.x == 1 && envSize.y == 1 || complexMaterial) { -# else +# else if (envSize.x == 1 && envSize.y == 1) { -# endif # endif dynamicCubemap = true; From 1314998392ad6ec5fa790e46fcdc7729bd28d2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Thu, 31 Jul 2025 17:14:52 +0800 Subject: [PATCH 04/33] add dynamic cubemaps for nondeferred --- package/Shaders/Lighting.hlsl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 31baa3f2c4..2c1a8cac14 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -3047,6 +3047,17 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } # else color.xyz += diffuseColor * baseColor.xyz; +# if !defined(DEFERRED) && defined(VANILLA_FRESNEL) +# if defined(DYNAMIC_CUBEMAPS) +# if defined(SKYLIGHTING) + specularColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness, skylightingSH) * reflectance; +# else + specularColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness) * reflectance; +# endif +# else + specularColor += directionalAmbientColor * reflectance; +# endif +# endif # endif # if defined(HAIR) && defined(CS_HAIR) From ee9a677a8ec3d27087b13ea7cd26d65d150f93b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Fri, 1 Aug 2025 14:32:10 +0800 Subject: [PATCH 05/33] fix complex material --- package/Shaders/Lighting.hlsl | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 2c1a8cac14..1d1f404d55 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1903,7 +1903,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) complexMaterial = complexMaterial && complexMaterialColor.y > (4.0 / 255.0); shininess = lerp(shininess, shininess * complexMaterialColor.y, complexMaterial); if (complexMaterial) { - complexSpecular = lerp(0.04, baseColor.xyz, complexMaterialColor.z); + complexSpecular = lerp(1.0, baseColor.xyz, complexMaterialColor.z); baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z); } @@ -2293,8 +2293,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif envMask = saturate(envMask); -# if defined(SPECULAR) +# if defined(VANILLA_FRESNEL) +# if defined(SPECULAR) F0 = lerp(glossiness * SpecularColor.xyz, F0, envMask); +# else + F0 = lerp(0.04, F0, envMask); +# endif # endif roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); } @@ -2907,6 +2911,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # else reflectance = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, roughness, F0); # endif + +# if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) && !defined(VANILLA_FRESNEL) + reflectance *= envMask; +# endif } # endif @@ -3047,15 +3055,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } # else color.xyz += diffuseColor * baseColor.xyz; -# if !defined(DEFERRED) && defined(VANILLA_FRESNEL) -# if defined(DYNAMIC_CUBEMAPS) -# if defined(SKYLIGHTING) - specularColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness, skylightingSH) * reflectance; -# else - specularColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness) * reflectance; -# endif +# if !defined(DEFERRED) && (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && defined(DYNAMIC_CUBEMAPS) + if (dynamicCubemap) +# if defined(SKYLIGHTING) + envColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness, skylightingSH) * reflectance; # else - specularColor += directionalAmbientColor * reflectance; + envColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness) * reflectance; # endif # endif # endif From 037189916689576bc0cda695d24ea74b494c5ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 2 Aug 2025 02:56:50 +0800 Subject: [PATCH 06/33] fix define --- package/Shaders/Lighting.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 1d1f404d55..7970a62955 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2912,7 +2912,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) reflectance = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, roughness, F0); # endif -# if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) && !defined(VANILLA_FRESNEL) +# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && !defined(VANILLA_FRESNEL) reflectance *= envMask; # endif } From 29ca1783b0158f5b4a53690c009fc7f4af789bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 2 Aug 2025 14:49:31 +0800 Subject: [PATCH 07/33] fix vanilla/cm reflectance --- package/Shaders/Lighting.hlsl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 7970a62955..3a12ac5076 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2299,8 +2299,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # else F0 = lerp(0.04, F0, envMask); # endif -# endif roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); +# else + roughness = envRoughness; +# endif } } # endif @@ -3057,11 +3059,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) color.xyz += diffuseColor * baseColor.xyz; # if !defined(DEFERRED) && (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && defined(DYNAMIC_CUBEMAPS) if (dynamicCubemap) -# if defined(SKYLIGHTING) - envColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness, skylightingSH) * reflectance; -# else - envColor += DynamicCubemaps::GetDynamicCubemapSpecularIrradiance(screenUV, worldNormal, vertexNormal, viewDirection, roughness) * reflectance; -# endif + envColor += reflectance; # endif # endif From 10d9f00d96521bb132871f10b9a537dd150c7a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 2 Aug 2025 17:15:44 +0800 Subject: [PATCH 08/33] fix vanilla/cm env, add dynamic cubemap for envmask shader --- package/Shaders/Lighting.hlsl | 42 ++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 3a12ac5076..2615e7ab6f 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -666,7 +666,7 @@ float ProcessSparkleColor(float color) } # endif -float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float3 lightColor, float3 specularColor, float shininess, float2 uv) +float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float3 lightColor, float3 F0, float roughness, float shininess, float2 uv) { float3 H = normalize(V + L); float HdotN = 1.0; @@ -680,15 +680,14 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # endif # if defined(SPECULAR) - float lightColorMultiplier = exp2(shininess * log2(HdotN)); + float3 lightColorMultiplier = exp2(shininess * log2(HdotN)); # if defined(VANILLA_FRESNEL_DL) float NdotV = saturate(dot(N, V)); float NdotL = saturate(dot(N, L)); float NdotH = saturate(dot(N, H)); float HdotV = saturate(dot(H, V)); - float roughness = pow(2.0 / (shininess + 2.0), 0.25); float D = BRDF::D_GGX(roughness, HdotN); - float3 F = BRDF::F_Schlick(specularColor, HdotV); + float3 F = BRDF::F_Schlick(F0, HdotV); float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); lightColorMultiplier = max(D * G * F * NdotL, 0.0); # endif @@ -2235,17 +2234,16 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float3 envColor = 0.0; bool dynamicCubemap = false; -# if defined(VANILLA_FRESNEL) - dynamicCubemap = true; -# endif if (envMask > 0.0) { # if defined(DYNAMIC_CUBEMAPS) uint2 envSize; TexEnvSampler.GetDimensions(envSize.x, envSize.y); -# if defined(EMAT) +# if defined(EMAT) && !defined(VANILLA_FRESNEL) if (envSize.x == 1 && envSize.y == 1 || complexMaterial) { +# elif defined(VANILLA_FRESNEL) + if (true) { # else if (envSize.x == 1 && envSize.y == 1) { # endif @@ -2267,6 +2265,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } # endif +# if defined(VANILLA_FRESNEL) + dynamicCubemap = true; +# endif + if (dynamicCubemap) { float4 envColorBase = TexEnvSampler.SampleLevel(SampEnvSampler, float3(1.0, 0.0, 0.0), 15); float envRoughness = 1.0; @@ -2275,8 +2277,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) F0 = Color::GammaToLinear(envColorBase.rgb); envRoughness = envColorBase.a; } else { +# if defined(VANILLA_FRESNEL) + F0 = saturate(Color::GammaToLinear(envColorBase.rgb) * Math::PI); + envRoughness = roughness; + baseColor.xyz = lerp(baseColor.xyz, 0, envMask); +# else F0 = 1.0; envRoughness = 1.0 / 7.0; +# endif } # if defined(CREATOR) @@ -2295,7 +2303,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) envMask = saturate(envMask); # if defined(VANILLA_FRESNEL) # if defined(SPECULAR) - F0 = lerp(glossiness * SpecularColor.xyz, F0, envMask); + F0 = max(lerp(glossiness * SpecularColor.xyz, F0, envMask), glossiness * SpecularColor.xyz); # else F0 = lerp(0.04, F0, envMask); # endif @@ -2565,11 +2573,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } else { # if defined(SPECULAR) - lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, F0, shininess, uv); + lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, F0, roughness, shininess, uv); # endif } # elif defined(SPECULAR) || defined(SPARKLE) - lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, F0, shininess, uv); + lightsSpecularColor = GetLightSpecularInput(input, DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz * dirDetailShadow, F0, roughness, shininess, uv); # endif } @@ -2646,11 +2654,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) transmissionColor += lightTransmissionColor; } else { # if defined(SPECULAR) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, roughness, shininess, uv); # endif } # elif defined(SPECULAR) || (defined(SPARKLE) && !defined(SNOW)) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, roughness, shininess, uv); # endif // defined (SPECULAR) || (defined (SPARKLE) && !defined(SNOW)) lightsDiffuseColor += lightDiffuseColor; @@ -2791,11 +2799,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) transmissionColor += lightTransmissionColor; } else { # if defined(SPECULAR) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, roughness, shininess, uv); # endif } # elif defined(SPECULAR) || (defined(SPARKLE) && !defined(SNOW)) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, F0, roughness, shininess, uv); # endif lightsDiffuseColor += lightDiffuseColor; @@ -3107,7 +3115,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(HAIR) && defined(CS_HAIR) if (!SharedData::hairSpecularSettings.Enabled) # endif +# if defined(VANILLA_FRESNEL) && (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) + specularColor = (specularColor * glossiness * MaterialData.yyy) * lerp(SpecularColor.xyz, F0, envMask); +# else specularColor = (specularColor * glossiness * MaterialData.yyy) * SpecularColor.xyz; +# endif # elif defined(SPARKLE) specularColor *= glossiness; # endif // SPECULAR From 99a8d9278d21a148dd454d3d5dfdf0078e6b80ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sun, 3 Aug 2025 00:56:46 +0800 Subject: [PATCH 09/33] fix eye color --- package/Shaders/Lighting.hlsl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 2615e7ab6f..036b29b34b 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2280,7 +2280,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) F0 = saturate(Color::GammaToLinear(envColorBase.rgb) * Math::PI); envRoughness = roughness; +# if !defined(EYE) baseColor.xyz = lerp(baseColor.xyz, 0, envMask); +# endif # else F0 = 1.0; envRoughness = 1.0 / 7.0; @@ -3133,7 +3135,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) diffuseColor = reflectionDiffuseColor; -# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && !(defined(VANILLA_FRESNEL) && !defined(EYE)) +# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && !defined(VANILLA_FRESNEL) # if defined(DYNAMIC_CUBEMAPS) if (!dynamicCubemap) # endif From e47a146f3b8d045fdd8c528f9d7f5b5f296bdfb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sun, 3 Aug 2025 14:33:41 +0800 Subject: [PATCH 10/33] remove basecolor lerp --- package/Shaders/Lighting.hlsl | 3 --- 1 file changed, 3 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 036b29b34b..a0d4ddc596 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2280,9 +2280,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) F0 = saturate(Color::GammaToLinear(envColorBase.rgb) * Math::PI); envRoughness = roughness; -# if !defined(EYE) - baseColor.xyz = lerp(baseColor.xyz, 0, envMask); -# endif # else F0 = 1.0; envRoughness = 1.0 / 7.0; From 38e3e0da16c31b366ccaa7a0e1980f1a54f17447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Fri, 8 Aug 2025 21:07:38 +0800 Subject: [PATCH 11/33] vanilla fresnel as feature --- .../Shaders/GrassLighting/GrassLighting.hlsli | 25 ++++---- package/Shaders/Common/SharedData.hlsli | 12 ++++ package/Shaders/Lighting.hlsl | 64 +++++++++++-------- package/Shaders/RunGrass.hlsl | 20 +++--- src/Feature.cpp | 2 + src/FeatureBuffer.cpp | 4 +- src/Features/VanillaFresnel.cpp | 36 +++++++++++ src/Features/VanillaFresnel.h | 45 +++++++++++++ src/Globals.cpp | 2 + src/Globals.h | 2 + 10 files changed, 165 insertions(+), 47 deletions(-) create mode 100644 src/Features/VanillaFresnel.cpp create mode 100644 src/Features/VanillaFresnel.h diff --git a/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli b/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli index 30138ce4bf..bc8ce85ca5 100644 --- a/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli +++ b/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli @@ -5,23 +5,24 @@ namespace GrassLighting float3 GetLightSpecularInput(float3 L, float3 V, float3 N, float3 lightColor, float roughness, float3 F0) { float3 H = normalize(V + L); -#if defined(VANILLA_FRESNEL_DL) - float NdotL = saturate(dot(N, L)); - float NdotV = saturate(dot(N, V)); - float NdotH = saturate(dot(N, H)); - float VdotH = saturate(dot(V, H)); +#if defined(VANILLA_FRESNEL) + if (SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGXOnGrass) { + float NdotL = saturate(dot(N, L)); + float NdotV = saturate(dot(N, V)); + float NdotH = saturate(dot(N, H)); + float VdotH = saturate(dot(V, H)); - float D = BRDF::D_GGX(roughness, NdotH); - float G = BRDF::Vis_SmithJointApprox(roughness, NdotL, NdotV); - float3 F = BRDF::F_Schlick(F0, VdotH); - float3 specular = D * G * F; - return specular * lightColor * NdotL; -#else + float D = BRDF::D_GGX(roughness, NdotH); + float G = BRDF::Vis_SmithJointApprox(roughness, NdotL, NdotV); + float3 F = BRDF::F_Schlick(F0, VdotH); + float3 specular = D * G * F; + return specular * lightColor * NdotL; + } +#endif float shininess = (1.0 - roughness) * 100.f; float HdotN = saturate(dot(H, N)); float lightColorMultiplier = exp2(shininess * log2(HdotN)); return lightColor * lightColorMultiplier.xxx; -#endif } float3 TransformNormal(float3 normal) diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index f1121a5df0..dcae0f91cb 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -194,6 +194,17 @@ namespace SharedData float Strength; // [0, 1.0] The inverse blend weight of the effect }; + struct VanillaFresnelSettings + { + uint Enable; + uint EnableGGX; + uint EnableGGXOnGrass; + uint EnableDynamicCubemapsConversion; + float RoughnessMultiplier; + float CubemapToF0Multiplier; + float3 pad; + }; + cbuffer FeatureData : register(b6) { GrassLightingSettings grassLightingSettings; @@ -209,6 +220,7 @@ namespace SharedData TerrainVariationSettings terrainVariationSettings; IBLSettings iblSettings; ExtendedTranslucencySettings extendedTranslucencySettings; + VanillaFresnelSettings vanillaFresnelSettings; }; Texture2D DepthTexture : register(t17); diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index a0d4ddc596..3bf67ec3d5 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -28,10 +28,6 @@ # define LOD #endif -#if defined(VANILLA_FRESNEL_DL) -# define VANILLA_FRESNEL -#endif - struct VS_INPUT { float4 Position : POSITION0; @@ -681,15 +677,17 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # if defined(SPECULAR) float3 lightColorMultiplier = exp2(shininess * log2(HdotN)); -# if defined(VANILLA_FRESNEL_DL) - float NdotV = saturate(dot(N, V)); - float NdotL = saturate(dot(N, L)); - float NdotH = saturate(dot(N, H)); - float HdotV = saturate(dot(H, V)); - float D = BRDF::D_GGX(roughness, HdotN); - float3 F = BRDF::F_Schlick(F0, HdotV); - float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); - lightColorMultiplier = max(D * G * F * NdotL, 0.0); +# if defined(VANILLA_FRESNEL) + if (SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGX) { + float NdotV = saturate(dot(N, V)); + float NdotL = saturate(dot(N, L)); + float NdotH = saturate(dot(N, H)); + float HdotV = saturate(dot(H, V)); + float D = BRDF::D_GGX(roughness, HdotN); + float3 F = BRDF::F_Schlick(F0, HdotV); + float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); + lightColorMultiplier = max(D * G * F * NdotL, 0.0); + } # endif # elif defined(SPARKLE) float lightColorMultiplier = 0; @@ -2202,7 +2200,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif // TRUE_PBR # if defined(VANILLA_FRESNEL) - float3 F0 = 0.04; + const bool enableVanillaFresnel = SharedData::vanillaFresnelSettings.Enable; + float3 F0 = enableVanillaFresnel ? 0.04 : 0.0; # else float3 F0 = 0.0; # endif @@ -2210,11 +2209,15 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) # if defined(SPECULAR) && !defined(TRUE_PBR) - F0 = saturate(glossiness * SpecularColor.xyz); - roughness = pow(2.0 / (shininess + 2.0), 0.25); + if (enableVanillaFresnel) { + F0 = saturate(glossiness * SpecularColor.xyz); + roughness = pow(2.0 / (shininess + 2.0), 0.25); + } # elif defined(EYE) - F0 = 0.027; - roughness = 0.1; + if (enableVanillaFresnel) { + F0 = 0.027; + roughness = 0.1; + } # endif # endif @@ -2243,7 +2246,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(EMAT) && !defined(VANILLA_FRESNEL) if (envSize.x == 1 && envSize.y == 1 || complexMaterial) { # elif defined(VANILLA_FRESNEL) - if (true) { + if (enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion) { # else if (envSize.x == 1 && envSize.y == 1) { # endif @@ -2315,8 +2318,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # if defined(EYE) && defined(VANILLA_FRESNEL) - F0 = 0.027; - roughness = 0.1; + if (enableVanillaFresnel) { + F0 = 0.027; + roughness = 0.1; + } # endif if (!dynamicCubemap) { @@ -2921,7 +2926,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) reflectance = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, roughness, F0); # endif -# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && !defined(VANILLA_FRESNEL) +# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) +# if defined(VANILLA_FRESNEL) + if (!enableVanillaFresnel) +# endif reflectance *= envMask; # endif } @@ -3110,12 +3118,15 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # endif // MULTI_LAYER_PARALLAX -# if defined(SPECULAR) && !defined(VANILLA_FRESNEL_DL) +# if defined(SPECULAR) # if defined(HAIR) && defined(CS_HAIR) if (!SharedData::hairSpecularSettings.Enabled) # endif +# if defined(VANILLA_FRESNEL) + if (!(enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableGGX)) +# endif # if defined(VANILLA_FRESNEL) && (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) - specularColor = (specularColor * glossiness * MaterialData.yyy) * lerp(SpecularColor.xyz, F0, envMask); + specularColor = (specularColor * glossiness * MaterialData.yyy) * ((enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion) ? lerp(SpecularColor.xyz, F0, envMask) : SpecularColor.xyz); # else specularColor = (specularColor * glossiness * MaterialData.yyy) * SpecularColor.xyz; # endif @@ -3132,9 +3143,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) diffuseColor = reflectionDiffuseColor; -# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) && !defined(VANILLA_FRESNEL) +# if (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) # if defined(DYNAMIC_CUBEMAPS) if (!dynamicCubemap) +# endif +# if defined(VANILLA_FRESNEL) + if (!enableVanillaFresnel) # endif specularColor += envColor * Color::GammaToLinear(diffuseColor); # endif diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index fe0cde296e..59c7582ecc 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -15,10 +15,6 @@ # undef IBL #endif -#if defined(VANILLA_FRESNEL_DL) -# define VANILLA_FRESNEL -#endif - struct VS_INPUT { float4 Position : POSITION0; @@ -767,9 +763,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif specularColor += lightsSpecularColor; -# if !defined(VANILLA_FRESNEL_DL) - specularColor *= specColor.w * SharedData::grassLightingSettings.SpecularStrength; +# if defined(VANILLA_FRESNEL) + if (!SharedData::vanillaFresnelSettings.Enable && !SharedData::vanillaFresnelSettings.EnableGGXOnGrass) # endif + specularColor *= specColor.w * SharedData::grassLightingSettings.SpecularStrength; specularColor = Color::GammaToLinear(specularColor); # endif @@ -796,11 +793,16 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Reflectance = float4(indirectSpecularLobeWeight, 1); # else + float3 reflectance = 0; # if defined(DYNAMIC_CUBEMAPS) && (defined(VANILLA_FRESNEL) || defined(TRUE_PBR)) +# if defined(VANILLA_FRESNEL) + if (SharedData::vanillaFresnelSettings.Enable) { +# endif float2 specularBDRF = DynamicCubemaps::EnvBRDFApprox(roughness, saturate(dot(viewDirection, normalVS))); - float3 reflectance = F0 * specularBDRF.x + specularBDRF.y; -# else - float3 reflectance = 0; + reflectance = F0 * specularBDRF.x + specularBDRF.y; +# if defined(VANILLA_FRESNEL) + } +# endif # endif psout.Reflectance = float4(reflectance, 1); diff --git a/src/Feature.cpp b/src/Feature.cpp index bd19a9f222..2188e586f3 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -25,6 +25,7 @@ #include "Features/TerrainShadows.h" #include "Features/TerrainVariation.h" #include "Features/Upscaling.h" +#include "Features/VanillaFresnel.h" #include "Features/VR.h" #include "Features/VolumetricLighting.h" #include "Features/WaterEffects.h" @@ -217,6 +218,7 @@ const std::vector& Feature::GetFeatureList() &globals::features::skySync, &globals::features::terrainBlending, &globals::features::terrainHelper, + &globals::features::vanillaFresnel, &globals::features::volumetricLighting, &globals::features::lodBlending, &globals::features::inverseSquareLighting, diff --git a/src/FeatureBuffer.cpp b/src/FeatureBuffer.cpp index 745480a847..dea3263446 100644 --- a/src/FeatureBuffer.cpp +++ b/src/FeatureBuffer.cpp @@ -12,6 +12,7 @@ #include "Features/Skylighting.h" #include "Features/TerrainShadows.h" #include "Features/TerrainVariation.h" +#include "Features/VanillaFresnel.h" #include "Features/WetnessEffects.h" #include "TruePBR.h" @@ -47,5 +48,6 @@ std::pair GetFeatureBufferData(bool a_inWorld) globals::features::hairSpecular.settings, globals::features::terrainVariation.settings, globals::features::ibl.settings, - globals::features::extendedTranslucency.GetCommonBufferData()); + globals::features::extendedTranslucency.GetCommonBufferData(), + globals::features::vanillaFresnel.settings); } \ No newline at end of file diff --git a/src/Features/VanillaFresnel.cpp b/src/Features/VanillaFresnel.cpp new file mode 100644 index 0000000000..1fde9e3e3d --- /dev/null +++ b/src/Features/VanillaFresnel.cpp @@ -0,0 +1,36 @@ +#include "VanillaFresnel.h" + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + VanillaFresnel::Settings, + Enable, + EnableGGX, + EnableGGXOnGrass, + EnableDynamicCubemapsConversion, + RoughnessMultiplier, + CubemapToF0Multiplier) + +void VanillaFresnel::RestoreDefaultSettings() +{ + settings = {}; +} + +void VanillaFresnel::LoadSettings(json& o_json) +{ + settings = o_json; +} + +void VanillaFresnel::SaveSettings(json& o_json) +{ + o_json = settings; +} + +void VanillaFresnel::DrawSettings() +{ + ImGui::Checkbox("Enable Vanilla Fresnel", reinterpret_cast(&settings.Enable)); + ImGui::Checkbox("Enable Phong to GGX", reinterpret_cast(&settings.EnableGGX)); + ImGui::Checkbox("Enable Phong to GGX on Grass", reinterpret_cast(&settings.EnableGGXOnGrass)); + ImGui::Checkbox("Enable Auto Cubemaps Conversion", reinterpret_cast(&settings.EnableDynamicCubemapsConversion)); + + ImGui::SliderFloat("Roughness Multiplier", &settings.RoughnessMultiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Cubemap to F0 Multiplier", &settings.CubemapToF0Multiplier, 0.0f, 10.0f, "%.2f"); +} \ No newline at end of file diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h new file mode 100644 index 0000000000..675276b7ef --- /dev/null +++ b/src/Features/VanillaFresnel.h @@ -0,0 +1,45 @@ +#pragma once + +struct VanillaFresnel : public Feature +{ + ////////////////////////////////////////////////// Boilerplate + // Metadata + virtual inline std::string GetName() override { return "Vanilla Fresnel"; } + virtual inline std::string GetShortName() override { return "VanillaFresnel"; } + virtual inline std::string_view GetCategory() const override { return "Lighting"; } + virtual inline std::string GetFeatureModLink() override { return MakeNexusModURL("999999"); } + virtual inline std::pair> GetFeatureSummary() override + { + return { + "Add realistic environmental reflections to vanilla materials.", + { + "Add environmental reflections to all materials", + "Supports vanilla and complex materials", + "Optionally turn vanilla phong specular into GGX", + "Optionally turn static cubemaps into dynamic reflections" + } + }; + } + + // Functionality + virtual bool inline SupportsVR() override { return true; } + virtual inline std::string_view GetShaderDefineName() override { return "VANILLA_FRESNEL"; } + virtual inline bool HasShaderDefine(RE::BSShader::Type t) override { return t == RE::BSShader::Type::Lighting; }; + + // Settings & UI + virtual void RestoreDefaultSettings() override; + virtual void LoadSettings(json& o_json) override; + virtual void SaveSettings(json& o_json) override; + virtual void DrawSettings() override; + + struct alignas(16) Settings + { + uint Enable = true; + uint EnableGGX = false; + uint EnableGGXOnGrass = false; + uint EnableDynamicCubemapsConversion = false; + float RoughnessMultiplier = 1.0f; + float CubemapToF0Multiplier = 1.0f; + float pad[2]; + } settings; +}; \ No newline at end of file diff --git a/src/Globals.cpp b/src/Globals.cpp index 6d2bf8bd51..0eee645a6e 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -24,6 +24,7 @@ #include "Features/TerrainShadows.h" #include "Features/TerrainVariation.h" #include "Features/Upscaling.h" +#include "Features/VanillaFresnel.h" #include "Features/VR.h" #include "Features/VolumetricLighting.h" #include "Features/WaterEffects.h" @@ -67,6 +68,7 @@ namespace globals TerrainBlending terrainBlending{}; TerrainHelper terrainHelper{}; TerrainShadows terrainShadows{}; + VanillaFresnel vanillaFresnel{}; VolumetricLighting volumetricLighting{}; VR vr{}; WaterEffects waterEffects{}; diff --git a/src/Globals.h b/src/Globals.h index 50bc6bd629..c6c6b21905 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -20,6 +20,7 @@ struct SubsurfaceScattering; struct TerrainBlending; struct TerrainHelper; struct TerrainShadows; +struct VanillaFresnel; struct VolumetricLighting; struct VR; struct WaterEffects; @@ -70,6 +71,7 @@ namespace globals extern TerrainBlending terrainBlending; extern TerrainHelper terrainHelper; extern TerrainShadows terrainShadows; + extern VanillaFresnel vanillaFresnel; extern VolumetricLighting volumetricLighting; extern VR vr; extern WaterEffects waterEffects; From bc4483509993035ed684cf5a3646c7f85096c86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Fri, 8 Aug 2025 21:26:20 +0800 Subject: [PATCH 12/33] add ini --- features/Vanilla Fresnel/Shaders/Features/VanillaFresnel.ini | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 features/Vanilla Fresnel/Shaders/Features/VanillaFresnel.ini diff --git a/features/Vanilla Fresnel/Shaders/Features/VanillaFresnel.ini b/features/Vanilla Fresnel/Shaders/Features/VanillaFresnel.ini new file mode 100644 index 0000000000..19f01444dc --- /dev/null +++ b/features/Vanilla Fresnel/Shaders/Features/VanillaFresnel.ini @@ -0,0 +1,2 @@ +[Info] +Version = 1-0-0 \ No newline at end of file From 5d62784411bc106def537862ae1b0d8c287e98b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Fri, 8 Aug 2025 23:09:06 +0800 Subject: [PATCH 13/33] add more control --- package/Shaders/Common/SharedData.hlsli | 3 ++- package/Shaders/Lighting.hlsl | 29 ++++++++++++++++++------- src/Features/VanillaFresnel.cpp | 4 ++++ src/Features/VanillaFresnel.h | 3 ++- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index dcae0f91cb..8bf4bac2d4 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -201,8 +201,9 @@ namespace SharedData uint EnableGGXOnGrass; uint EnableDynamicCubemapsConversion; float RoughnessMultiplier; + float BaseF0Multiplier; + float MinF0; float CubemapToF0Multiplier; - float3 pad; }; cbuffer FeatureData : register(b6) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 3bf67ec3d5..39265c907d 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2219,6 +2219,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) roughness = 0.1; } # endif + F0 = max((enableVanillaFresnel ? SharedData::vanillaFresnelSettings.MinF0 : 0.0), F0 * SharedData::vanillaFresnelSettings.BaseF0Multiplier); + float3 baseF0 = F0; # endif # if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) @@ -2246,7 +2248,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(EMAT) && !defined(VANILLA_FRESNEL) if (envSize.x == 1 && envSize.y == 1 || complexMaterial) { # elif defined(VANILLA_FRESNEL) - if (enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion) { + bool vfStartDynamicCubemapTest = (enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion); +# if defined(EMAT) + vfStartDynamicCubemapTest = complexMaterial || vfStartDynamicCubemapTest; +# endif + if (vfStartDynamicCubemapTest || (envSize.x == 1 && envSize.y == 1)) { # else if (envSize.x == 1 && envSize.y == 1) { # endif @@ -2269,7 +2275,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # if defined(VANILLA_FRESNEL) - dynamicCubemap = true; + dynamicCubemap = dynamicCubemap || (SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion && enableVanillaFresnel); # endif if (dynamicCubemap) { @@ -2281,7 +2287,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) envRoughness = envColorBase.a; } else { # if defined(VANILLA_FRESNEL) - F0 = saturate(Color::GammaToLinear(envColorBase.rgb) * Math::PI); + F0 = saturate(Color::GammaToLinear(envColorBase.rgb) * Math::PI * SharedData::vanillaFresnelSettings.CubemapToF0Multiplier); envRoughness = roughness; # else F0 = 1.0; @@ -2304,12 +2310,16 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) envMask = saturate(envMask); # if defined(VANILLA_FRESNEL) + if (enableVanillaFresnel) { # if defined(SPECULAR) - F0 = max(lerp(glossiness * SpecularColor.xyz, F0, envMask), glossiness * SpecularColor.xyz); + F0 = max(lerp(baseF0, F0, envMask), SharedData::vanillaFresnelSettings.MinF0); # else - F0 = lerp(0.04, F0, envMask); + F0 = lerp(SharedData::vanillaFresnelSettings.MinF0, F0, envMask); # endif - roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); + roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); + } else { + roughness = envRoughness; + } # else roughness = envRoughness; # endif @@ -2317,10 +2327,13 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } # endif -# if defined(EYE) && defined(VANILLA_FRESNEL) +# if defined(VANILLA_FRESNEL) if (enableVanillaFresnel) { +# if defined(EYE) F0 = 0.027; roughness = 0.1; +# endif + roughness = clamp(roughness * SharedData::vanillaFresnelSettings.RoughnessMultiplier, 0.04, 1.0); } # endif @@ -3148,7 +3161,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (!dynamicCubemap) # endif # if defined(VANILLA_FRESNEL) - if (!enableVanillaFresnel) + if (!(enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion)) # endif specularColor += envColor * Color::GammaToLinear(diffuseColor); # endif diff --git a/src/Features/VanillaFresnel.cpp b/src/Features/VanillaFresnel.cpp index 1fde9e3e3d..3829383813 100644 --- a/src/Features/VanillaFresnel.cpp +++ b/src/Features/VanillaFresnel.cpp @@ -7,6 +7,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( EnableGGXOnGrass, EnableDynamicCubemapsConversion, RoughnessMultiplier, + BaseF0Multiplier, + MinF0, CubemapToF0Multiplier) void VanillaFresnel::RestoreDefaultSettings() @@ -32,5 +34,7 @@ void VanillaFresnel::DrawSettings() ImGui::Checkbox("Enable Auto Cubemaps Conversion", reinterpret_cast(&settings.EnableDynamicCubemapsConversion)); ImGui::SliderFloat("Roughness Multiplier", &settings.RoughnessMultiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Base F0 Multiplier", &settings.BaseF0Multiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Min F0", &settings.MinF0, 0.0f, 0.04f, "%.3f"); ImGui::SliderFloat("Cubemap to F0 Multiplier", &settings.CubemapToF0Multiplier, 0.0f, 10.0f, "%.2f"); } \ No newline at end of file diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 675276b7ef..8a2fa396ea 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -39,7 +39,8 @@ struct VanillaFresnel : public Feature uint EnableGGXOnGrass = false; uint EnableDynamicCubemapsConversion = false; float RoughnessMultiplier = 1.0f; + float BaseF0Multiplier = 0.32f; + float MinF0 = 0.02f; float CubemapToF0Multiplier = 1.0f; - float pad[2]; } settings; }; \ No newline at end of file From de91dc8dafa3c7fc2051810dfc12ece4744f364a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 9 Aug 2025 00:19:39 +0800 Subject: [PATCH 14/33] fix cubemap conversion --- package/Shaders/Lighting.hlsl | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 39265c907d..c26cb400a0 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -677,7 +677,13 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float # if defined(SPECULAR) float3 lightColorMultiplier = exp2(shininess * log2(HdotN)); -# if defined(VANILLA_FRESNEL) +# elif defined(SPARKLE) + float3 lightColorMultiplier = 0; +# else + float3 lightColorMultiplier = HdotN; +# endif + +# if defined(VANILLA_FRESNEL) if (SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGX) { float NdotV = saturate(dot(N, V)); float NdotL = saturate(dot(N, L)); @@ -688,11 +694,6 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); lightColorMultiplier = max(D * G * F * NdotL, 0.0); } -# endif -# elif defined(SPARKLE) - float lightColorMultiplier = 0; -# else - float lightColorMultiplier = HdotN; # endif # if defined(ANISO_LIGHTING) @@ -2201,7 +2202,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) const bool enableVanillaFresnel = SharedData::vanillaFresnelSettings.Enable; - float3 F0 = enableVanillaFresnel ? 0.04 : 0.0; + float3 F0 = enableVanillaFresnel ? SharedData::vanillaFresnelSettings.MinF0 : 0.0; # else float3 F0 = 0.0; # endif @@ -2314,9 +2315,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(SPECULAR) F0 = max(lerp(baseF0, F0, envMask), SharedData::vanillaFresnelSettings.MinF0); # else - F0 = lerp(SharedData::vanillaFresnelSettings.MinF0, F0, envMask); + F0 = max(lerp(0, F0, envMask), SharedData::vanillaFresnelSettings.MinF0); # endif - roughness = lerp(roughness, envRoughness, pow(envMask, 0.25)); + roughness = lerp(roughness, envRoughness, envMask); } else { roughness = envRoughness; } @@ -2931,7 +2932,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(DYNAMIC_CUBEMAPS) if (any(F0 > 0.0)) { # if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) +# if defined(VANILLA_FRESNEL) + if (dynamicCubemap || enableVanillaFresnel) +# else if (dynamicCubemap) +# endif # endif # if defined(SKYLIGHTING) reflectance = DynamicCubemaps::GetDynamicCubemap(worldNormal, vertexNormal, viewDirection, roughness, F0, skylightingSH); From 1064e24e03fe24a95e6c994cbdd882de0bb96577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 9 Aug 2025 03:59:19 +0800 Subject: [PATCH 15/33] more on cm --- package/Shaders/Common/SharedData.hlsli | 2 ++ package/Shaders/Lighting.hlsl | 6 ++++++ src/Features/VanillaFresnel.cpp | 4 +++- src/Features/VanillaFresnel.h | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index 8bf4bac2d4..0e8a43fcb7 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -204,6 +204,8 @@ namespace SharedData float BaseF0Multiplier; float MinF0; float CubemapToF0Multiplier; + float ComplexMaterialF0Multiplier; + float3 pad; }; cbuffer FeatureData : register(b6) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index c26cb400a0..470e458dcb 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1902,6 +1902,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) shininess = lerp(shininess, shininess * complexMaterialColor.y, complexMaterial); if (complexMaterial) { complexSpecular = lerp(1.0, baseColor.xyz, complexMaterialColor.z); +# if defined(VANILLA_FRESNEL) + complexSpecular = saturate(complexSpecular * (enableVanillaFresnel ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier : 1.0)); +# endif baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z); } @@ -3172,6 +3175,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # if defined(EMAT_ENVMAP) +# if defined(VANILLA_FRESNEL) + if (!(enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableGGX)) +# endif specularColor *= complexSpecular; # endif // defined (EMAT) && defined(ENVMAP) diff --git a/src/Features/VanillaFresnel.cpp b/src/Features/VanillaFresnel.cpp index 3829383813..ed27e049d9 100644 --- a/src/Features/VanillaFresnel.cpp +++ b/src/Features/VanillaFresnel.cpp @@ -9,7 +9,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( RoughnessMultiplier, BaseF0Multiplier, MinF0, - CubemapToF0Multiplier) + CubemapToF0Multiplier, + ComplexMaterialF0Multiplier) void VanillaFresnel::RestoreDefaultSettings() { @@ -37,4 +38,5 @@ void VanillaFresnel::DrawSettings() ImGui::SliderFloat("Base F0 Multiplier", &settings.BaseF0Multiplier, 0.0f, 10.0f, "%.2f"); ImGui::SliderFloat("Min F0", &settings.MinF0, 0.0f, 0.04f, "%.3f"); ImGui::SliderFloat("Cubemap to F0 Multiplier", &settings.CubemapToF0Multiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Complex Material Env F0 Multiplier", &settings.ComplexMaterialF0Multiplier, 0.0f, 10.0f, "%.2f"); } \ No newline at end of file diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 8a2fa396ea..8e3cd30d07 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -42,5 +42,7 @@ struct VanillaFresnel : public Feature float BaseF0Multiplier = 0.32f; float MinF0 = 0.02f; float CubemapToF0Multiplier = 1.0f; + float ComplexMaterialF0Multiplier = 1.0f; + float pad[3]; } settings; }; \ No newline at end of file From 228ae08fa3731e606912835186050b40735fe6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 9 Aug 2025 13:15:29 +0800 Subject: [PATCH 16/33] fix error --- package/Shaders/Lighting.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 470e458dcb..afe09c925a 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1903,7 +1903,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (complexMaterial) { complexSpecular = lerp(1.0, baseColor.xyz, complexMaterialColor.z); # if defined(VANILLA_FRESNEL) - complexSpecular = saturate(complexSpecular * (enableVanillaFresnel ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier : 1.0)); + complexSpecular = saturate(complexSpecular * (SharedData::vanillaFresnelSettings.Enable ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier : 1.0)); # endif baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z); From 23523dc4b55802da9cbea1a2caadb17b295b9681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Sat, 23 Aug 2025 16:08:35 +0800 Subject: [PATCH 17/33] fix error --- package/Shaders/RunGrass.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 59c7582ecc..6a5126616c 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -798,7 +798,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) if (SharedData::vanillaFresnelSettings.Enable) { # endif - float2 specularBDRF = DynamicCubemaps::EnvBRDFApprox(roughness, saturate(dot(viewDirection, normalVS))); + float2 specularBDRF = BRDF::EnvBRDF(roughness, saturate(dot(viewDirection, normalVS))); reflectance = F0 * specularBDRF.x + specularBDRF.y; # if defined(VANILLA_FRESNEL) } From 3037ff3e93dbfb0186cb79e933c524503ab9c58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Thu, 18 Sep 2025 15:02:28 +0800 Subject: [PATCH 18/33] some tweaks --- .../Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli | 3 ++- features/Hair Specular/Shaders/Hair/Hair.hlsli | 3 ++- package/Shaders/Common/Color.hlsli | 3 ++- package/Shaders/Lighting.hlsl | 4 ++-- package/Shaders/RunGrass.hlsl | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli b/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli index bc8ce85ca5..cbcd8b71de 100644 --- a/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli +++ b/features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli @@ -1,4 +1,5 @@ #include "Common/BRDF.hlsli" +#include "Common/Color.hlsli" namespace GrassLighting { @@ -16,7 +17,7 @@ namespace GrassLighting float G = BRDF::Vis_SmithJointApprox(roughness, NdotL, NdotV); float3 F = BRDF::F_Schlick(F0, VdotH); float3 specular = D * G * F; - return specular * lightColor * NdotL; + return specular * lightColor * NdotL * Color::PBRLightingCompensation; } #endif float shininess = (1.0 - roughness) * 100.f; diff --git a/features/Hair Specular/Shaders/Hair/Hair.hlsli b/features/Hair Specular/Shaders/Hair/Hair.hlsli index 40ec13e532..561abd2d59 100644 --- a/features/Hair Specular/Shaders/Hair/Hair.hlsli +++ b/features/Hair Specular/Shaders/Hair/Hair.hlsli @@ -2,10 +2,11 @@ #define __HAIR_DEPENDENCY_HLSL__ #include "Common/BRDF.hlsli" +#include "Common/Color.hlsli" #include "Common/Game.hlsli" #include "Common/Math.hlsli" -#define HAIR_LIGHTING_MULTIPLIER Math::PI // Compensating to adapt to vanilla lighting model +#define HAIR_LIGHTING_MULTIPLIER Color::PBRLightingCompensation // Compensating to adapt to vanilla lighting model namespace Hair { diff --git a/package/Shaders/Common/Color.hlsli b/package/Shaders/Common/Color.hlsli index 6b74bb92ee..5526c0d10b 100644 --- a/package/Shaders/Common/Color.hlsli +++ b/package/Shaders/Common/Color.hlsli @@ -67,6 +67,7 @@ namespace Color // Attempt to match vanilla materials that are darker than PBR const static float PBRLightingScale = 0.666; + const static float PBRLightingCompensation = Math::PI; // Attempt to normalise reflection brightness against DALC const static float ReflectionNormalisationScale = 0.666; @@ -103,7 +104,7 @@ namespace Color float3 Light(float3 color) { #if defined(TRUE_PBR) - return color * Math::PI; // Compensate for traditional Lambertian diffuse + return color * PBRLightingCompensation; // Compensate for traditional Lambertian diffuse #else return color; #endif diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index afe09c925a..f20f8493cd 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -692,7 +692,7 @@ float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float float D = BRDF::D_GGX(roughness, HdotN); float3 F = BRDF::F_Schlick(F0, HdotV); float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); - lightColorMultiplier = max(D * G * F * NdotL, 0.0); + lightColorMultiplier = max(D * G * F * NdotL, 0.0) * Color::PBRLightingCompensation; } # endif @@ -2214,7 +2214,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) # if defined(SPECULAR) && !defined(TRUE_PBR) if (enableVanillaFresnel) { - F0 = saturate(glossiness * SpecularColor.xyz); + F0 = saturate(glossiness * SpecularColor.xyz / Math::PI); roughness = pow(2.0 / (shininess + 2.0), 0.25); } # elif defined(EYE) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 6a5126616c..c7d17aa438 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -525,7 +525,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) baseColor.xyz *= SharedData::grassLightingSettings.BasicGrassBrightness; # endif // !TRUE_PBR - float3 F0 = specColor.w * SharedData::grassLightingSettings.SpecularStrength; + float3 F0 = saturate(specColor.w * SharedData::grassLightingSettings.SpecularStrength / Math::PI); float roughness = saturate(1.0 - SharedData::grassLightingSettings.Glossiness * 0.01); # if defined(TRUE_PBR) From 1e4180fdc703281707468cd88c0ceae329b82759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Thu, 18 Sep 2025 17:29:22 +0800 Subject: [PATCH 19/33] add spec lod fade --- package/Shaders/Lighting.hlsl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index f20f8493cd..4745699c74 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2956,6 +2956,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } # endif +# if defined(SPECULAR) + reflectance *= MaterialData.yyy; +# endif + float2 screenMotionVector = MotionBlur::GetSSMotionVector(input.WorldPosition, input.PreviousWorldPosition, eyeIndex); # if defined(WETNESS_EFFECTS) @@ -3147,10 +3151,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (!(enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableGGX)) # endif # if defined(VANILLA_FRESNEL) && (defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)) - specularColor = (specularColor * glossiness * MaterialData.yyy) * ((enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion) ? lerp(SpecularColor.xyz, F0, envMask) : SpecularColor.xyz); + specularColor = (specularColor * glossiness) * ((enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion) ? lerp(SpecularColor.xyz, F0, envMask) : SpecularColor.xyz); # else - specularColor = (specularColor * glossiness * MaterialData.yyy) * SpecularColor.xyz; + specularColor = (specularColor * glossiness) * SpecularColor.xyz; # endif + specularColor *= MaterialData.yyy; # elif defined(SPARKLE) specularColor *= glossiness; # endif // SPECULAR From bcd34243c3c0c71b53da30e343dda57d2e8a88ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Thu, 18 Sep 2025 17:42:27 +0800 Subject: [PATCH 20/33] tweak f0 for cm --- package/Shaders/Lighting.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 4745699c74..57ae1d2ee5 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1903,7 +1903,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (complexMaterial) { complexSpecular = lerp(1.0, baseColor.xyz, complexMaterialColor.z); # if defined(VANILLA_FRESNEL) - complexSpecular = saturate(complexSpecular * (SharedData::vanillaFresnelSettings.Enable ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier : 1.0)); + complexSpecular = saturate(complexSpecular * (SharedData::vanillaFresnelSettings.Enable ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier / Math::PI : 1.0)); # endif baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z); From 9b6b62f816deec860d52aef2bfe8abe472d1cd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Thu, 18 Sep 2025 20:10:13 +0800 Subject: [PATCH 21/33] indirect energy conserve for vanilla fresnel --- package/Shaders/Lighting.hlsl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 57ae1d2ee5..6df32fd38d 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -3217,6 +3217,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(TRUE_PBR) outputAlbedo = indirectDiffuseLobeWeight; +# elif defined(VANILLA_FRESNEL) + if (enableVanillaFresnel) + { + outputAlbedo *= 1 - reflectance; + } # endif # if defined(HAIR) && defined(CS_HAIR) From 23d9e74ea5681e0b1598b2d3fe59c807f1417f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=82=B2=E5=98=89?= Date: Fri, 14 Nov 2025 02:02:23 +0800 Subject: [PATCH 22/33] fix grass --- package/Shaders/RunGrass.hlsl | 11 ++++++++--- src/Features/VanillaFresnel.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index c7d17aa438..6286b1504b 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -525,7 +525,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) baseColor.xyz *= SharedData::grassLightingSettings.BasicGrassBrightness; # endif // !TRUE_PBR - float3 F0 = saturate(specColor.w * SharedData::grassLightingSettings.SpecularStrength / Math::PI); +# if defined(VANILLA_FRESNEL) + const bool enableVanillaFresnel = SharedData::vanillaFresnelSettings.Enable; + float3 F0 = enableVanillaFresnel ? max(SharedData::vanillaFresnelSettings.MinF0, saturate(specColor.w * SharedData::grassLightingSettings.SpecularStrength * SharedData::vanillaFresnelSettings.BaseF0Multiplier / Math::PI)) : 0.0; +# else + float3 F0 = 0.0; +# endif float roughness = saturate(1.0 - SharedData::grassLightingSettings.Glossiness * 0.01); # if defined(TRUE_PBR) @@ -764,7 +769,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) specularColor += lightsSpecularColor; # if defined(VANILLA_FRESNEL) - if (!SharedData::vanillaFresnelSettings.Enable && !SharedData::vanillaFresnelSettings.EnableGGXOnGrass) + if (!(SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGXOnGrass)) # endif specularColor *= specColor.w * SharedData::grassLightingSettings.SpecularStrength; specularColor = Color::GammaToLinear(specularColor); @@ -798,7 +803,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) if (SharedData::vanillaFresnelSettings.Enable) { # endif - float2 specularBDRF = BRDF::EnvBRDF(roughness, saturate(dot(viewDirection, normalVS))); + float2 specularBDRF = BRDF::EnvBRDF(roughness, saturate(dot(viewDirection, normal))); reflectance = F0 * specularBDRF.x + specularBDRF.y; # if defined(VANILLA_FRESNEL) } diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 8e3cd30d07..1863bfb0bd 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -24,7 +24,7 @@ struct VanillaFresnel : public Feature // Functionality virtual bool inline SupportsVR() override { return true; } virtual inline std::string_view GetShaderDefineName() override { return "VANILLA_FRESNEL"; } - virtual inline bool HasShaderDefine(RE::BSShader::Type t) override { return t == RE::BSShader::Type::Lighting; }; + virtual inline bool HasShaderDefine(RE::BSShader::Type) override { return true; }; // Settings & UI virtual void RestoreDefaultSettings() override; From ffa802e5d3e49074d5982fe2740cee0a74af9199 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Sun, 14 Dec 2025 11:16:41 +0800 Subject: [PATCH 23/33] fix vf --- package/Shaders/Common/LightingEval.hlsli | 6 +++--- package/Shaders/Lighting.hlsl | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/package/Shaders/Common/LightingEval.hlsli b/package/Shaders/Common/LightingEval.hlsli index 0e3d59e179..0e8d4b3607 100644 --- a/package/Shaders/Common/LightingEval.hlsli +++ b/package/Shaders/Common/LightingEval.hlsli @@ -139,10 +139,10 @@ void EvaluateLighting(DirectContext context, MaterialProperties material, float3 lightingOutput.diffuse += context.lightColor * saturate(-NdotL) * material.backLightColor; # endif -# if defined(VANILLA_SPECULAR) +# if defined(VANILLA_FRESNEL) if (SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGX) { - lightingOutput.specular = MicrofacetSpecular(context, material.F0, material.Roughness) * context.lightColor; + lightingOutput.specular = MicrofacetSpecular(context, material.F0, material.Roughness) * context.lightColor * Color::PBRLightingCompensation * Color::PBRLightingScale; float2 specularBRDF = BRDF::EnvBRDF(material.Roughness, saturate(dot(context.worldNormal, context.viewDir))); lightingOutput.specular *= 1 + material.F0 * (1 / (specularBRDF.x + specularBRDF.y) - 1); @@ -222,7 +222,7 @@ void EvaluateWetnessLighting(float3 wetnessNormal, DirectContext context, float float3 wetnessSpecular = D * G * F * NdotL * lightColor; #if !defined(TRUE_PBR) - wetnessSpecular *= Math::PI * Color::PBRLightingScale; // Compensate for GGX on traditional specular + wetnessSpecular *= Color::PBRLightingCompensation * Color::PBRLightingScale; // Compensate for GGX on traditional specular #endif lightingOutput.diffuse *= 1 - F; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index fa02123e9a..3e7c9a12d2 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1857,7 +1857,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (complexMaterial) { complexSpecular = lerp(1.0, baseColor.xyz, complexMaterialColor.z); # if defined(VANILLA_FRESNEL) - complexSpecular = saturate(complexSpecular * (SharedData::vanillaFresnelSettings.Enable ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier / Math::PI : 1.0)); + complexSpecular = saturate(complexSpecular * (SharedData::vanillaFresnelSettings.Enable ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier : 1.0)); # endif baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z); @@ -2296,6 +2296,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) material.F0 = max(lerp(baseF0, material.F0, envMask), SharedData::vanillaFresnelSettings.MinF0); # else material.F0 = max(lerp(0, material.F0, envMask), SharedData::vanillaFresnelSettings.MinF0); +# endif +# if defined(EMAT) + if (!complexMaterial) # endif material.Roughness = lerp(originRoughness, material.Roughness, envMask); } @@ -2915,6 +2918,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # endif # if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE) +# if defined(VANILLA_FRESNEL) + if (!enableVanillaFresnel) +# endif indirectLobeWeights.specular *= envMask; # endif From de4e90c1b4643ede47ac77992286f5bc0101d231 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Fri, 8 May 2026 00:55:29 +0800 Subject: [PATCH 24/33] feat(VanillaFresnel): add eye special handling and specular roughness blend settings --- package/Shaders/Common/SharedData.hlsli | 4 ++- package/Shaders/Lighting.hlsl | 12 ++++--- src/Features/VanillaFresnel.cpp | 48 +++++++++++++------------ src/Features/VanillaFresnel.h | 32 ++++++++--------- 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index 2f07681b9c..fcfd83b56c 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -269,12 +269,14 @@ namespace SharedData uint EnableGGX; uint EnableGGXOnGrass; uint EnableDynamicCubemapsConversion; + uint EnableEyeSpecialHandling; float RoughnessMultiplier; + float SpecularRoughnessBlend; float BaseF0Multiplier; float MinF0; float CubemapToF0Multiplier; float ComplexMaterialF0Multiplier; - float3 pad; + float pad; }; cbuffer FeatureData : register(b6) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 9b72d7cb96..99da37e855 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2264,14 +2264,16 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) const bool enableVanillaFresnel = SharedData::vanillaFresnelSettings.Enable; material.F0 = enableVanillaFresnel ? SharedData::vanillaFresnelSettings.MinF0 : 0.0; # if defined(EYE) - if (enableVanillaFresnel) { + if (enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) { material.F0 = 0.027; material.Roughness = 0.1; } # elif defined(SPECULAR) if (enableVanillaFresnel) { material.F0 = saturate(glossiness * SpecularColor.xyz / Math::PI); - material.Roughness = ShininessToRoughness(material.Shininess); + float roughnessFromSpecular = (1.0 - glossiness) * (1.0 - glossiness); + float roughnessFromShininess = ShininessToRoughness(material.Shininess); + material.Roughness = lerp(roughnessFromShininess, roughnessFromSpecular, SharedData::vanillaFresnelSettings.SpecularRoughnessBlend * (1.0 - glossiness)); } # endif material.F0 = max((enableVanillaFresnel ? SharedData::vanillaFresnelSettings.MinF0 : 0.0), material.F0 * SharedData::vanillaFresnelSettings.BaseF0Multiplier); @@ -2398,8 +2400,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) && !defined(TRUE_PBR) if (enableVanillaFresnel) { # if defined(EYE) - material.F0 = 0.027; - material.Roughness = 0.1; + if (SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) { + material.F0 = 0.027; + material.Roughness = 0.1; + } # endif material.Roughness = clamp(material.Roughness * SharedData::vanillaFresnelSettings.RoughnessMultiplier, 0.04, 1.0); } diff --git a/src/Features/VanillaFresnel.cpp b/src/Features/VanillaFresnel.cpp index ed27e049d9..133721b81f 100644 --- a/src/Features/VanillaFresnel.cpp +++ b/src/Features/VanillaFresnel.cpp @@ -1,16 +1,18 @@ #include "VanillaFresnel.h" NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( - VanillaFresnel::Settings, - Enable, - EnableGGX, - EnableGGXOnGrass, - EnableDynamicCubemapsConversion, - RoughnessMultiplier, - BaseF0Multiplier, - MinF0, - CubemapToF0Multiplier, - ComplexMaterialF0Multiplier) + VanillaFresnel::Settings, + Enable, + EnableGGX, + EnableGGXOnGrass, + EnableDynamicCubemapsConversion, + EnableEyeSpecialHandling, + RoughnessMultiplier, + SpecularRoughnessBlend, + BaseF0Multiplier, + MinF0, + CubemapToF0Multiplier, + ComplexMaterialF0Multiplier) void VanillaFresnel::RestoreDefaultSettings() { @@ -19,24 +21,26 @@ void VanillaFresnel::RestoreDefaultSettings() void VanillaFresnel::LoadSettings(json& o_json) { - settings = o_json; + settings = o_json; } void VanillaFresnel::SaveSettings(json& o_json) { - o_json = settings; + o_json = settings; } void VanillaFresnel::DrawSettings() { - ImGui::Checkbox("Enable Vanilla Fresnel", reinterpret_cast(&settings.Enable)); - ImGui::Checkbox("Enable Phong to GGX", reinterpret_cast(&settings.EnableGGX)); - ImGui::Checkbox("Enable Phong to GGX on Grass", reinterpret_cast(&settings.EnableGGXOnGrass)); - ImGui::Checkbox("Enable Auto Cubemaps Conversion", reinterpret_cast(&settings.EnableDynamicCubemapsConversion)); + ImGui::Checkbox("Enable Vanilla Fresnel", reinterpret_cast(&settings.Enable)); + ImGui::Checkbox("Enable Phong to GGX", reinterpret_cast(&settings.EnableGGX)); + ImGui::Checkbox("Enable Phong to GGX on Grass", reinterpret_cast(&settings.EnableGGXOnGrass)); + ImGui::Checkbox("Enable Auto Cubemaps Conversion", reinterpret_cast(&settings.EnableDynamicCubemapsConversion)); + ImGui::Checkbox("Enable Eye Special Handling", reinterpret_cast(&settings.EnableEyeSpecialHandling)); - ImGui::SliderFloat("Roughness Multiplier", &settings.RoughnessMultiplier, 0.0f, 10.0f, "%.2f"); - ImGui::SliderFloat("Base F0 Multiplier", &settings.BaseF0Multiplier, 0.0f, 10.0f, "%.2f"); - ImGui::SliderFloat("Min F0", &settings.MinF0, 0.0f, 0.04f, "%.3f"); - ImGui::SliderFloat("Cubemap to F0 Multiplier", &settings.CubemapToF0Multiplier, 0.0f, 10.0f, "%.2f"); - ImGui::SliderFloat("Complex Material Env F0 Multiplier", &settings.ComplexMaterialF0Multiplier, 0.0f, 10.0f, "%.2f"); -} \ No newline at end of file + ImGui::SliderFloat("Roughness Multiplier", &settings.RoughnessMultiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Specular Roughness Blend", &settings.SpecularRoughnessBlend, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat("Base F0 Multiplier", &settings.BaseF0Multiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Min F0", &settings.MinF0, 0.0f, 0.04f, "%.3f"); + ImGui::SliderFloat("Cubemap to F0 Multiplier", &settings.CubemapToF0Multiplier, 0.0f, 10.0f, "%.2f"); + ImGui::SliderFloat("Complex Material Env F0 Multiplier", &settings.ComplexMaterialF0Multiplier, 0.0f, 10.0f, "%.2f"); +} diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 1863bfb0bd..5d60f89c56 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -12,12 +12,10 @@ struct VanillaFresnel : public Feature { return { "Add realistic environmental reflections to vanilla materials.", - { - "Add environmental reflections to all materials", - "Supports vanilla and complex materials", - "Optionally turn vanilla phong specular into GGX", - "Optionally turn static cubemaps into dynamic reflections" - } + { "Add environmental reflections to all materials", + "Supports vanilla and complex materials", + "Optionally turn vanilla phong specular into GGX", + "Optionally turn static cubemaps into dynamic reflections" } }; } @@ -35,14 +33,16 @@ struct VanillaFresnel : public Feature struct alignas(16) Settings { uint Enable = true; - uint EnableGGX = false; - uint EnableGGXOnGrass = false; - uint EnableDynamicCubemapsConversion = false; - float RoughnessMultiplier = 1.0f; - float BaseF0Multiplier = 0.32f; - float MinF0 = 0.02f; - float CubemapToF0Multiplier = 1.0f; - float ComplexMaterialF0Multiplier = 1.0f; - float pad[3]; + uint EnableGGX = false; + uint EnableGGXOnGrass = false; + uint EnableDynamicCubemapsConversion = false; + uint EnableEyeSpecialHandling = true; + float RoughnessMultiplier = 1.0f; + float SpecularRoughnessBlend = 1.0f; + float BaseF0Multiplier = 0.32f; + float MinF0 = 0.02f; + float CubemapToF0Multiplier = 1.0f; + float ComplexMaterialF0Multiplier = 1.0f; + float pad; } settings; -}; \ No newline at end of file +}; From 17bab5cec3e866fc61d113082c7f7ba36674353b Mon Sep 17 00:00:00 2001 From: jiayev Date: Tue, 12 May 2026 21:55:02 +0800 Subject: [PATCH 25/33] Reorder feature settings in FeatureBuffer.cpp --- src/FeatureBuffer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FeatureBuffer.cpp b/src/FeatureBuffer.cpp index 1414072beb..f8e9908dc7 100644 --- a/src/FeatureBuffer.cpp +++ b/src/FeatureBuffer.cpp @@ -50,8 +50,8 @@ std::pair GetFeatureBufferData(bool a_inWorld) globals::features::terrainVariation.settings, globals::features::ibl.GetCommonBufferData(), globals::features::extendedTranslucency.GetCommonBufferData(), - globals::features::vanillaFresnel.settings, globals::features::linearLighting.GetCommonBufferData(), globals::features::terrainBlending.settings, - globals::features::exponentialHeightFog.settings); -} \ No newline at end of file + globals::features::exponentialHeightFog.settings, + globals::features::vanillaFresnel.settings); +} From 224858de5c964c6b3bd32250280fcd266d12a4d5 Mon Sep 17 00:00:00 2001 From: jiayev Date: Tue, 12 May 2026 23:52:07 +0800 Subject: [PATCH 26/33] Update F0 calculation to use SkyrimGammaToLinear --- package/Shaders/Lighting.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 57b351a509..7d9464a904 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2361,7 +2361,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) material.Roughness = envColorBase.a; } else { # if defined(VANILLA_FRESNEL) - material.F0 = saturate(Color::GammaToLinear(envColorBase.rgb) * Math::PI * SharedData::vanillaFresnelSettings.CubemapToF0Multiplier); + material.F0 = saturate(Color::SkyrimGammaToLinear(envColorBase.rgb) * Math::PI * SharedData::vanillaFresnelSettings.CubemapToF0Multiplier); material.Roughness = material.Roughness; # else material.F0 = 1.0; From e7bfd472e80423ac7526c1c29909affed603b89b Mon Sep 17 00:00:00 2001 From: Jiaye Date: Wed, 13 May 2026 12:26:37 +0800 Subject: [PATCH 27/33] move to core --- features/Vanilla Fresnel/CORE | 0 src/Features/VanillaFresnel.h | 1 + 2 files changed, 1 insertion(+) create mode 100644 features/Vanilla Fresnel/CORE diff --git a/features/Vanilla Fresnel/CORE b/features/Vanilla Fresnel/CORE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 5d60f89c56..1401b9dd45 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -21,6 +21,7 @@ struct VanillaFresnel : public Feature // Functionality virtual bool inline SupportsVR() override { return true; } + virtual bool inline IsCore() const override { return true; } virtual inline std::string_view GetShaderDefineName() override { return "VANILLA_FRESNEL"; } virtual inline bool HasShaderDefine(RE::BSShader::Type) override { return true; }; From 3e606eea1c5b5a9250f7334ad0c9d74b4c180174 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Sat, 16 May 2026 16:29:29 +0800 Subject: [PATCH 28/33] fix(VanillaFresnel): remove deprecated GetFeatureModLink method --- src/Features/VanillaFresnel.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 1401b9dd45..04348ad8ff 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -7,7 +7,6 @@ struct VanillaFresnel : public Feature virtual inline std::string GetName() override { return "Vanilla Fresnel"; } virtual inline std::string GetShortName() override { return "VanillaFresnel"; } virtual inline std::string_view GetCategory() const override { return "Lighting"; } - virtual inline std::string GetFeatureModLink() override { return MakeNexusModURL("999999"); } virtual inline std::pair> GetFeatureSummary() override { return { From 247cbc30a3bc3577699fef4e5f4e187da9dd0312 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Wed, 20 May 2026 23:52:07 +0800 Subject: [PATCH 29/33] affect base color for cubemap conversion --- package/Shaders/Lighting.hlsl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index eeac6b732a..410b2778a1 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2397,9 +2397,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) material.F0 = max(lerp(0, material.F0, envMask), SharedData::vanillaFresnelSettings.MinF0); # endif # if defined(EMAT) - if (!complexMaterial) + if (!complexMaterial) { # endif material.Roughness = lerp(originRoughness, material.Roughness, envMask); + material.F0 = saturate(material.F0 + envMask * material.BaseColor); + material.BaseColor = lerp(material.BaseColor, 0, envMask); +# if defined(EMAT) + } +# endif } # endif } From 4281f7ac6793267031c289513fb5a5a83fa9a108 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Mon, 25 May 2026 12:57:39 +0800 Subject: [PATCH 30/33] fix wrong applying to other stuff --- package/Shaders/Lighting.hlsl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 410b2778a1..10f229e1a8 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2361,8 +2361,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (dynamicCubemap) { float4 envColorBase = TexEnvSampler.SampleLevel(SampEnvSampler, float3(1.0, 0.0, 0.0), 15); + bool usingDynamicCubemap = envColorBase.a < 1.0; - if (envColorBase.a < 1.0) { + if (usingDynamicCubemap) { material.F0 = Color::SkyrimGammaToLinear(envColorBase.rgb); material.Roughness = envColorBase.a; } else { @@ -2400,8 +2401,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (!complexMaterial) { # endif material.Roughness = lerp(originRoughness, material.Roughness, envMask); - material.F0 = saturate(material.F0 + envMask * material.BaseColor); - material.BaseColor = lerp(material.BaseColor, 0, envMask); +# if !defined(EYE) + if (!usingDynamicCubemap) { + material.F0 = saturate(material.F0 + envMask * material.BaseColor); + material.BaseColor = lerp(material.BaseColor, 0, envMask); + } +# endif # if defined(EMAT) } # endif From 498fa7d8acbdc9a1557775c8fcea382917678259 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Wed, 27 May 2026 23:45:30 +0800 Subject: [PATCH 31/33] forbid cubemap conversion when not ggx --- src/Features/VanillaFresnel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Features/VanillaFresnel.cpp b/src/Features/VanillaFresnel.cpp index 133721b81f..5cbd239a90 100644 --- a/src/Features/VanillaFresnel.cpp +++ b/src/Features/VanillaFresnel.cpp @@ -34,7 +34,12 @@ void VanillaFresnel::DrawSettings() ImGui::Checkbox("Enable Vanilla Fresnel", reinterpret_cast(&settings.Enable)); ImGui::Checkbox("Enable Phong to GGX", reinterpret_cast(&settings.EnableGGX)); ImGui::Checkbox("Enable Phong to GGX on Grass", reinterpret_cast(&settings.EnableGGXOnGrass)); + if (!settings.EnableGGX) { + settings.EnableDynamicCubemapsConversion = false; + } + ImGui::BeginDisabled(!settings.EnableGGX); ImGui::Checkbox("Enable Auto Cubemaps Conversion", reinterpret_cast(&settings.EnableDynamicCubemapsConversion)); + ImGui::EndDisabled(); ImGui::Checkbox("Enable Eye Special Handling", reinterpret_cast(&settings.EnableEyeSpecialHandling)); ImGui::SliderFloat("Roughness Multiplier", &settings.RoughnessMultiplier, 0.0f, 10.0f, "%.2f"); From 83a10637a0b5eeb4a5a6a91868f80250ac6ea99c Mon Sep 17 00:00:00 2001 From: Jiaye Date: Thu, 28 May 2026 20:16:47 +0800 Subject: [PATCH 32/33] feat: add IsEye flag and update eye material handling in VanillaFresnel --- package/Shaders/Common/Permutation.hlsli | 1 + package/Shaders/Lighting.hlsl | 22 +++---- src/Features/VanillaFresnel.cpp | 76 ++++++++++++++++++++++++ src/Features/VanillaFresnel.h | 1 + src/State.h | 3 +- 5 files changed, 89 insertions(+), 14 deletions(-) diff --git a/package/Shaders/Common/Permutation.hlsli b/package/Shaders/Common/Permutation.hlsli index d3e2005526..41054c5a86 100644 --- a/package/Shaders/Common/Permutation.hlsli +++ b/package/Shaders/Common/Permutation.hlsli @@ -75,6 +75,7 @@ namespace Permutation static const uint GrassSphereNormal = (1 << 3); static const uint IsSun = (1 << 4); static const uint SuppressExternalEmittance = (1 << 5); + static const uint IsEye = (1 << 6); } namespace ExtraFeatureFlags diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index daad9c11f7..f10714a3f8 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2271,20 +2271,20 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) const bool enableVanillaFresnel = SharedData::vanillaFresnelSettings.Enable; + const bool isEyeMaterial = (Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::IsEye) != 0; material.F0 = enableVanillaFresnel ? SharedData::vanillaFresnelSettings.MinF0 : 0.0; -# if defined(EYE) - if (enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) { - material.F0 = 0.027; - material.Roughness = 0.1; - } -# elif defined(SPECULAR) - if (enableVanillaFresnel) { +# if defined(SPECULAR) + if (enableVanillaFresnel && !isEyeMaterial) { material.F0 = saturate(glossiness * SpecularColor.xyz / Math::PI); float roughnessFromSpecular = (1.0 - glossiness) * (1.0 - glossiness); float roughnessFromShininess = ShininessToRoughness(material.Shininess); material.Roughness = lerp(roughnessFromShininess, roughnessFromSpecular, SharedData::vanillaFresnelSettings.SpecularRoughnessBlend * (1.0 - glossiness)); } # endif + if (enableVanillaFresnel && isEyeMaterial && SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) { + material.F0 = 0.027; + material.Roughness = 0.1; + } material.F0 = max((enableVanillaFresnel ? SharedData::vanillaFresnelSettings.MinF0 : 0.0), material.F0 * SharedData::vanillaFresnelSettings.BaseF0Multiplier); const float3 baseF0 = material.F0; # endif // VANILLA_FRESNEL @@ -2401,12 +2401,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) if (!complexMaterial) { # endif material.Roughness = lerp(originRoughness, material.Roughness, envMask); -# if !defined(EYE) - if (!usingDynamicCubemap) { + if (!isEyeMaterial && !usingDynamicCubemap) { material.F0 = saturate(material.F0 + envMask * material.BaseColor); material.BaseColor = lerp(material.BaseColor, 0, envMask); } -# endif # if defined(EMAT) } # endif @@ -2418,12 +2416,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(VANILLA_FRESNEL) && !defined(TRUE_PBR) if (enableVanillaFresnel) { -# if defined(EYE) - if (SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) { + if (isEyeMaterial && SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) { material.F0 = 0.027; material.Roughness = 0.1; } -# endif material.Roughness = clamp(material.Roughness * SharedData::vanillaFresnelSettings.RoughnessMultiplier, 0.04, 1.0); } # endif diff --git a/src/Features/VanillaFresnel.cpp b/src/Features/VanillaFresnel.cpp index 5cbd239a90..0a1cb3dda7 100644 --- a/src/Features/VanillaFresnel.cpp +++ b/src/Features/VanillaFresnel.cpp @@ -1,5 +1,9 @@ #include "VanillaFresnel.h" +#include "Globals.h" +#include "ShaderCache.h" +#include "State.h" + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( VanillaFresnel::Settings, Enable, @@ -14,6 +18,78 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( CubemapToF0Multiplier, ComplexMaterialF0Multiplier) +namespace +{ + constexpr auto IsEyeDescriptor = static_cast(State::ExtraShaderDescriptors::IsEye); + + bool ContainsEye(std::string_view a_name) + { + constexpr std::string_view eye = "eye"; + return std::search( + a_name.begin(), a_name.end(), + eye.begin(), eye.end(), + [](char a_lhs, char a_rhs) { + return static_cast(std::tolower(static_cast(a_lhs))) == a_rhs; + }) != a_name.end(); + } + + bool IsEyePass(const RE::BSLightingShader* a_shader, const RE::BSRenderPass* a_pass) + { + if (a_shader) { + const auto technique = static_cast(0x3F & (a_shader->currentRawTechnique >> 24)); + if (technique == SIE::ShaderCache::LightingShaderTechniques::Eye) { + return true; + } + } + + if (!a_pass || !a_pass->shaderProperty) { + return false; + } + + const auto* lightingProperty = a_pass->shaderProperty->GetRTTI() == globals::rtti::BSLightingShaderPropertyRTTI.get() ? + static_cast(a_pass->shaderProperty) : + nullptr; + if (!lightingProperty || !lightingProperty->material) { + return false; + } + + const auto feature = lightingProperty->material->GetFeature(); + if (feature == RE::BSShaderMaterial::Feature::kEye) { + return true; + } + + return feature == RE::BSShaderMaterial::Feature::kEnvironmentMap && + a_pass->geometry && + ContainsEye(a_pass->geometry->name.c_str()); + } + + void UpdateEyePermutation(const RE::BSLightingShader* a_shader, const RE::BSRenderPass* a_pass) + { + auto& descriptor = globals::state->permutationData.ExtraShaderDescriptor; + descriptor &= ~IsEyeDescriptor; + + if (IsEyePass(a_shader, a_pass)) { + descriptor |= IsEyeDescriptor; + } + } + + struct BSLightingShader_SetupGeometry + { + static void thunk(RE::BSLightingShader* a_shader, RE::BSRenderPass* a_pass, uint32_t a_renderFlags) + { + UpdateEyePermutation(a_shader, a_pass); + func(a_shader, a_pass, a_renderFlags); + } + static inline REL::Relocation func; + }; +} + +void VanillaFresnel::PostPostLoad() +{ + stl::write_vfunc<0x6, BSLightingShader_SetupGeometry>(RE::VTABLE_BSLightingShader[0]); + logger::info("[VanillaFresnel] Installed hooks - BSLightingShader_SetupGeometry"); +} + void VanillaFresnel::RestoreDefaultSettings() { settings = {}; diff --git a/src/Features/VanillaFresnel.h b/src/Features/VanillaFresnel.h index 04348ad8ff..d1a9bbf5f7 100644 --- a/src/Features/VanillaFresnel.h +++ b/src/Features/VanillaFresnel.h @@ -23,6 +23,7 @@ struct VanillaFresnel : public Feature virtual bool inline IsCore() const override { return true; } virtual inline std::string_view GetShaderDefineName() override { return "VANILLA_FRESNEL"; } virtual inline bool HasShaderDefine(RE::BSShader::Type) override { return true; }; + virtual void PostPostLoad() override; // Settings & UI virtual void RestoreDefaultSettings() override; diff --git a/src/State.h b/src/State.h index 2dd811d445..c5318c5437 100644 --- a/src/State.h +++ b/src/State.h @@ -180,7 +180,8 @@ class State IsBeastRace = 1 << 2, GrassSphereNormal = 1 << 3, IsSun = 1 << 4, - SuppressExternalEmittance = 1 << 5 + SuppressExternalEmittance = 1 << 5, + IsEye = 1 << 6 }; enum class ExtraFeatureDescriptors : uint32_t From fdc0e34c0ac4e46185e5042b3d79bfba5f602796 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Tue, 2 Jun 2026 01:28:58 +0800 Subject: [PATCH 33/33] chore: update GrassLighting.ini version to 2-1-0 --- features/Grass Lighting/Shaders/Features/GrassLighting.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/Grass Lighting/Shaders/Features/GrassLighting.ini b/features/Grass Lighting/Shaders/Features/GrassLighting.ini index 140421b6e6..5e77fe691c 100644 --- a/features/Grass Lighting/Shaders/Features/GrassLighting.ini +++ b/features/Grass Lighting/Shaders/Features/GrassLighting.ini @@ -1,2 +1,2 @@ [Info] -Version = 2-0-3 +Version = 2-1-0