Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion features/Grass Lighting/Shaders/Features/GrassLighting.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 2-0-3
Version = 2-1-0
21 changes: 19 additions & 2 deletions features/Grass Lighting/Shaders/GrassLighting/GrassLighting.hlsli
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
#include "Common/BRDF.hlsli"
#include "Common/Color.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)
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);
Comment thread
alandtse marked this conversation as resolved.
float3 specular = D * G * F;
return specular * lightColor * NdotL * Color::PBRLightingCompensation;
}
#endif
float shininess = (1.0 - roughness) * 100.f;
float HdotN = saturate(dot(H, N));
float lightColorMultiplier = exp2(shininess * log2(HdotN));
return lightColor * lightColorMultiplier.xxx;
}
Expand Down
Empty file added features/Vanilla Fresnel/CORE
Empty file.
2 changes: 2 additions & 0 deletions features/Vanilla Fresnel/Shaders/Features/VanillaFresnel.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Info]
Version = 1-0-0
17 changes: 17 additions & 0 deletions package/SKSE/Plugins/CommunityShaders/Translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,23 @@
"feature.upscaling.vr_intermediates_not_created": "VR intermediates not yet created (enter game world)",
"feature.upscaling.vr_perf_upscale_preset": "Upscale preset",
"feature.upscaling.vr_perf_upscaling_header": "Upscaling & Foveation",
"feature.vanilla_fresnel.base_f0_multiplier": "Base F0 Multiplier",
"feature.vanilla_fresnel.complex_material_f0_multiplier": "Complex Material Env F0 Multiplier",
"feature.vanilla_fresnel.cubemap_to_f0_multiplier": "Cubemap to F0 Multiplier",
"feature.vanilla_fresnel.description": "Add realistic environmental reflections to vanilla materials.",
"feature.vanilla_fresnel.enable": "Enable Vanilla Fresnel",
"feature.vanilla_fresnel.enable_dynamic_cubemaps_conversion": "Enable Auto Cubemaps Conversion",
"feature.vanilla_fresnel.enable_eye_special_handling": "Enable Eye Special Handling",
"feature.vanilla_fresnel.enable_ggx": "Enable Phong to GGX",
"feature.vanilla_fresnel.enable_ggx_on_grass": "Enable Phong to GGX on Grass",
"feature.vanilla_fresnel.key_feature_1": "Add environmental reflections to all materials",
"feature.vanilla_fresnel.key_feature_2": "Supports vanilla and complex materials",
"feature.vanilla_fresnel.key_feature_3": "Optionally turn vanilla phong specular into GGX",
"feature.vanilla_fresnel.key_feature_4": "Optionally turn static cubemaps into dynamic reflections",
"feature.vanilla_fresnel.min_f0": "Min F0",
"feature.vanilla_fresnel.name": "Vanilla Fresnel",
"feature.vanilla_fresnel.roughness_multiplier": "Roughness Multiplier",
"feature.vanilla_fresnel.specular_roughness_blend": "Specular Roughness Blend",
"feature.volumetric_lighting.description": "Volumetric Lighting creates realistic light scattering effects through fog, dust, and atmospheric particles.\nThis adds dramatic god rays and atmospheric depth to both interior and exterior environments.",
"feature.volumetric_lighting.enable_exteriors": "Enable Volumetric Lighting in Exteriors",
"feature.volumetric_lighting.enable_exteriors_tooltip": "Volumetric god-rays / fog scattering in exterior cells.",
Expand Down
30 changes: 30 additions & 0 deletions package/Shaders/Common/LightingEval.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,25 @@ float3 VanillaSpecular(DirectContext context, float shininess, float2 uv, float2
return lightColorMultiplier;
}

float3 MicrofacetSpecular(DirectContext context, float3 F0, float roughness)
{
const float3 N = context.worldNormal;
const float3 V = context.viewDir;
const float3 L = context.lightDir;
const float3 H = context.halfVector;

float NdotL = clamp(dot(N, L), EPSILON_DOT_CLAMP, 1);
float NdotV = saturate(abs(dot(N, V)) + EPSILON_DOT_CLAMP);
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, NdotV, NdotL);
float3 F = BRDF::F_Schlick(F0, VdotH);

return D * G * F * NdotL;
}

void EvaluateLighting(DirectContext context, MaterialProperties material, float3x3 tbnTr, float2 uv, float2 uv_ddx, float2 uv_ddy, out DirectLightingOutput lightingOutput)
{
lightingOutput = (DirectLightingOutput)0;
Expand Down Expand Up @@ -145,6 +164,17 @@ void EvaluateLighting(DirectContext context, MaterialProperties material, float3
# if defined(BACK_LIGHTING)
lightingOutput.diffuse += softLightColor * saturate(-NdotL) * material.backLightColor * Color::VanillaNormalization();
# endif

# if defined(VANILLA_FRESNEL)
if (SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGX) {
lightingOutput.specular = diffuseLightColor * MicrofacetSpecular(context, material.F0, material.Roughness) * 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);
return;
}
# endif

lightingOutput.specular = VanillaSpecular(context, material.Shininess, uv, uv_ddx, uv_ddy) * material.SpecularColor * material.Glossiness * diffuseLightColor * Color::VanillaNormalization();
#endif
}
Expand Down
1 change: 1 addition & 0 deletions package/Shaders/Common/Permutation.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,22 @@ namespace SharedData
float4 wetParams;
};

struct VanillaFresnelSettings
{
uint Enable;
uint EnableGGX;
uint EnableGGXOnGrass;
uint EnableDynamicCubemapsConversion;
uint EnableEyeSpecialHandling;
float RoughnessMultiplier;
float SpecularRoughnessBlend;
float BaseF0Multiplier;
float MinF0;
float CubemapToF0Multiplier;
float ComplexMaterialF0Multiplier;
float pad;
};

cbuffer FeatureData : register(b6)
{
GrassLightingSettings grassLightingSettings;
Expand All @@ -355,6 +371,7 @@ namespace SharedData
ExponentialHeightFogSettings exponentialHeightFogSettings;
TruePBRSettings truePBRSettings;
SkinData skinData;
VanillaFresnelSettings vanillaFresnelSettings;
};

Texture2D<float4> DepthTexture : register(t17);
Expand Down
95 changes: 88 additions & 7 deletions package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -1943,6 +1943,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 * (SharedData::vanillaFresnelSettings.Enable ? SharedData::vanillaFresnelSettings.ComplexMaterialF0Multiplier : 1.0));
# endif
baseColor.xyz = lerp(baseColor.xyz, 0.0, complexMaterialColor.z);
}
# endif // defined (EMAT) && defined(ENVMAP)
Expand Down Expand Up @@ -2342,7 +2345,27 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
# if defined(BACK_LIGHTING)
material.backLightColor = backLightColor.xyz;
# endif
# endif // TRUE_PBR

# 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(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
# endif // TRUE_PBR

# if defined(SKIN) && defined(CS_SKIN)
const float ExtraRoughness = BRDF::F_Schlick(0.04, saturate(dot(worldNormal.xyz, viewDirection))) * SharedData::skinData.fuzzParams.w;
Expand Down Expand Up @@ -2411,10 +2434,16 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
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)
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) {
if (envSize.x == 1 && envSize.y == 1) {
# endif

dynamicCubemap = true;
Expand All @@ -2434,15 +2463,26 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
}
# endif

# if defined(VANILLA_FRESNEL)
dynamicCubemap = dynamicCubemap || (SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion && enableVanillaFresnel);
const float originRoughness = material.Roughness;
# endif

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 {
# if defined(VANILLA_FRESNEL)
material.F0 = saturate(Color::SkyrimGammaToLinear(envColorBase.rgb) * Math::PI * SharedData::vanillaFresnelSettings.CubemapToF0Multiplier);
material.Roughness = material.Roughness;
# else
material.F0 = 1.0;
material.Roughness = 1.0 / 7.0;
# endif
}

# if defined(CREATOR)
Expand All @@ -2457,10 +2497,42 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
material.Roughness = lerp(material.Roughness, complexMaterialRoughness, complexMaterial);
material.F0 = lerp(material.F0, complexSpecular, complexMaterial);
# endif

envMask = saturate(envMask);
# if defined(VANILLA_FRESNEL)
if (enableVanillaFresnel) {
# if defined(SPECULAR)
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);
if (!isEyeMaterial && !usingDynamicCubemap) {
material.F0 = saturate(material.F0 + envMask * material.BaseColor);
material.BaseColor = lerp(material.BaseColor, 0, envMask);
}
# if defined(EMAT)
}
# endif
}
# endif
}
}
# endif

# if defined(VANILLA_FRESNEL) && !defined(TRUE_PBR)
if (enableVanillaFresnel) {
if (isEyeMaterial && SharedData::vanillaFresnelSettings.EnableEyeSpecialHandling) {
material.F0 = 0.027;
material.Roughness = 0.1;
}
material.Roughness = clamp(material.Roughness * SharedData::vanillaFresnelSettings.RoughnessMultiplier, 0.04, 1.0);
}
# endif

if (!dynamicCubemap) {
float3 envColorBase = Color::SkyrimGammaToLinear(TexEnvSampler.Sample(SampEnvSampler, envSamplingPoint).xyz);
envColor = envColorBase.xyz * envMask;
Expand Down Expand Up @@ -3226,7 +3298,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
# endif
# endif
# if defined(ENVMAP) || defined(MULTI_LAYER_PARALLAX) || defined(EYE)
indirectLobeWeights.specular *= envMask;
# if defined(VANILLA_FRESNEL)
if (!enableVanillaFresnel)
# endif
indirectLobeWeights.specular *= envMask;
# endif

# if defined(SPECULAR) && !defined(TRUE_PBR)
Expand Down Expand Up @@ -3291,12 +3366,18 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
# if defined(DYNAMIC_CUBEMAPS)
if (!dynamicCubemap)
# endif
specularColor += envColor * Color::IrradianceToLinear(diffuseColor);
# if defined(VANILLA_FRESNEL)
if (!(enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableDynamicCubemapsConversion))
# endif
specularColor += envColor * Color::IrradianceToLinear(diffuseColor);
indirectLobeWeights.diffuse += envColor;
# endif

# if defined(EMAT_ENVMAP)
specularColor *= complexSpecular;
# if defined(VANILLA_FRESNEL)
if (!(enableVanillaFresnel && SharedData::vanillaFresnelSettings.EnableGGX))
# endif
specularColor *= complexSpecular;
# endif // defined (EMAT) && defined(ENVMAP)

# if defined(LOD_LAND_BLEND) && defined(TRUE_PBR)
Expand Down
37 changes: 30 additions & 7 deletions package/Shaders/RunGrass.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,10 @@ 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;
float4 Masks2: SV_Target7;
# endif // RENDER_DEPTH
# endif // RENDER_DEPTH
};
#else
struct PS_OUTPUT
Expand Down Expand Up @@ -558,6 +556,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
baseColor.xyz *= SharedData::grassLightingSettings.BasicGrassBrightness;
# endif // !TRUE_PBR

# 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)
float4 rawRMAOS = TexRMAOSSampler.SampleBias(SampRMAOSSampler, input.TexCoord.xy, SharedData::MipBias) * float4(PBRParams1.x, 1, 1, PBRParams1.y);

Expand Down Expand Up @@ -657,7 +663,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
float3 subsurfaceColor = dirLightColor * dirDetailedShadow * (GetSoftLightMultiplier(dirLightAngle, softLightRolloff)) * Color::VanillaNormalization();

if (complex)
lightsSpecularColor += dirDetailedShadow * GrassLighting::GetLightSpecularInput(SharedData::DirLightDirection.xyz, viewDirection, normal, dirLightColor, SharedData::grassLightingSettings.Glossiness) * Color::VanillaNormalization();
lightsSpecularColor += dirDetailedShadow * GrassLighting::GetLightSpecularInput(SharedData::DirLightDirection.xyz, viewDirection, normal, dirLightColor, roughness, F0) * Color::VanillaNormalization();
# endif

# if defined(LIGHT_LIMIT_FIX)
Expand Down Expand Up @@ -733,7 +739,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
lightsDiffuseColor += lightDiffuseColor * Color::VanillaNormalization();

if (complex)
lightsSpecularColor += GrassLighting::GetLightSpecularInput(normalizedLightDirection, viewDirection, normal, lightColor, SharedData::grassLightingSettings.Glossiness) * Color::VanillaNormalization();
lightsSpecularColor += GrassLighting::GetLightSpecularInput(normalizedLightDirection, viewDirection, normal, lightColor, roughness, F0) * Color::VanillaNormalization();
# endif
}
}
Expand Down Expand Up @@ -780,7 +786,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
# endif

specularColor += lightsSpecularColor;
specularColor *= specColor.w * SharedData::grassLightingSettings.SpecularStrength;
# if defined(VANILLA_FRESNEL)
if (!(SharedData::vanillaFresnelSettings.Enable && SharedData::vanillaFresnelSettings.EnableGGXOnGrass))
# endif
specularColor *= specColor.w * SharedData::grassLightingSettings.SpecularStrength;
# endif

# if defined(LIGHT_LIMIT_FIX) && defined(LLFDEBUG)
Expand All @@ -805,8 +814,22 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
psout.NormalGlossiness = float4(GBuffer::EncodeNormal(normalVS), 1 - pbrSurfaceProperties.Roughness, 1);
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 = BRDF::EnvBRDF(roughness, saturate(dot(viewDirection, normal)));
reflectance = F0 * specularBDRF.x + specularBDRF.y;
# if defined(VANILLA_FRESNEL)
}
# endif
# 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);
Expand Down
Loading
Loading