Files
beyond/Assets/ThirdParty/Lux URP Essentials/Shader Graphs/Includes/Lux_Lighting_CharlieSheen.hlsl
2024-11-20 15:21:28 +01:00

285 lines
10 KiB
HLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if !defined(SHADERGRAPH_PREVIEW) || defined(LIGHTWEIGHT_LIGHTING_INCLUDED)
// As we do not have access to the vertex lights we will make the shader always sample add lights per pixel
#if defined(_ADDITIONAL_LIGHTS_VERTEX)
#undef _ADDITIONAL_LIGHTS_VERTEX
#define _ADDITIONAL_LIGHTS
#endif
#if defined(LIGHTWEIGHT_LIGHTING_INCLUDED) || defined(UNIVERSAL_LIGHTING_INCLUDED)
// Ref: https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
real D_CharlieNoPI_Lux(real NdotH, real roughness)
{
float invR = rcp(roughness);
float cos2h = NdotH * NdotH;
float sin2h = 1.0 - cos2h;
// Note: We have sin^2 so multiply by 0.5 to cancel it
return (2.0 + invR) * PositivePow(sin2h, invR * 0.5) / 2.0;
}
real D_Charlie_Lux(real NdotH, real roughness)
{
return INV_PI * D_CharlieNoPI_Lux(NdotH, roughness);
}
// We use V_Ashikhmin instead of V_Charlie in practice for game due to the cost of V_Charlie
real V_Ashikhmin_Lux(real NdotL, real NdotV)
{
// Use soft visibility term introduce in: Crafting a Next-Gen Material Pipeline for The Order : 1886
return 1.0 / (4.0 * (NdotL + NdotV - NdotL * NdotV));
}
// A diffuse term use with fabric done by tech artist - empirical
real FabricLambertNoPI_Lux(real roughness)
{
return lerp(1.0, 0.5, roughness);
}
real FabricLambert_Lux(real roughness)
{
return INV_PI * FabricLambertNoPI_Lux(roughness);
}
struct AdditionalData {
half3 sheenColor;
};
half3 DirectBDRF_LuxCharlieSheen(BRDFData brdfData, AdditionalData addData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
float NoH = saturate(dot(normalWS, halfDir));
half LoH = saturate(dot(lightDirectionWS, halfDir));
half NdotV = saturate(dot(normalWS, viewDirectionWS ));
// Charlie Sheen
// NOTE: We use the noPI version here!!!!!!
float D = D_CharlieNoPI_Lux(NoH, brdfData.roughness);
// Unity: V_Charlie is expensive, use approx with V_Ashikhmin instead
// Unity: float Vis = V_Charlie(NdotL, NdotV, bsdfData.roughness);
float Vis = V_Ashikhmin_Lux(NdotL, NdotV);
// Unity: Fabrics are dieletric but we simulate forward scattering effect with colored specular (fuzz tint term)
// Unity: We don't use Fresnel term for CharlieD
// SheenColor seemed way too dark (compared to HDRP) so i multiply it with PI which looked ok and somehow matched HDRP
// Therefore we use the noPI charlie version. As PI is a constant factor the artists can tweak the look by adjusting the sheen color.
float3 F = addData.sheenColor; // * PI;
half3 specularLighting = F * Vis * D;
// Unity: Note: diffuseLighting originally is multiply by color in PostEvaluateBSDF
// So we do it here :)
// Using saturate to get rid of artifacts around the borders.
return saturate(specularLighting) + brdfData.diffuse * FabricLambert_Lux(brdfData.roughness);
#else
return brdfData.diffuse;
#endif
}
half3 LightingPhysicallyBased_LuxCharlieSheen(BRDFData brdfData, AdditionalData addData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS, half NdotL)
{
//half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = lightColor * (lightAttenuation * NdotL);
return DirectBDRF_LuxCharlieSheen(brdfData, addData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance;
}
half3 LightingPhysicallyBased_LuxCharlieSheen(BRDFData brdfData, AdditionalData addData, Light light, half3 normalWS, half3 viewDirectionWS, half NdotL)
{
return LightingPhysicallyBased_LuxCharlieSheen(brdfData, addData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS, NdotL);
}
#endif
#endif
void Lighting_half(
// Base inputs
float3 positionWS,
half3 viewDirectionWS,
// Normal inputs
half3 normalWS,
half3 tangentWS,
half3 bitangentWS,
bool enableNormalMapping,
half3 normalTS,
// Surface description
half3 albedo,
half metallic,
half3 specular,
half smoothness,
half occlusion,
half alpha,
// Lighting specific inputs
half3 sheenColor,
bool enableTransmission,
half transmissionStrength,
half transmissionPower,
half transmissionDistortion,
half transmissionShadowstrength,
// Lightmapping
float2 lightMapUV,
// Final lit color
out half3 MetaAlbedo,
out half3 FinalLighting,
out half3 MetaSpecular
)
{
#if defined(SHADERGRAPH_PREVIEW) || ( !defined(LIGHTWEIGHT_LIGHTING_INCLUDED) && !defined(UNIVERSAL_LIGHTING_INCLUDED) )
FinalLighting = albedo;
MetaAlbedo = half3(0,0,0);
MetaSpecular = half3(0,0,0);
#else
// Real Lighting ----------
// Charlie Sheen specific:
smoothness = lerp(0.0h, 0.6h, smoothness);
if (enableNormalMapping) {
normalWS = TransformTangentToWorld(normalTS, half3x3(tangentWS.xyz, bitangentWS.xyz, normalWS.xyz));
}
normalWS = NormalizeNormalPerPixel(normalWS);
viewDirectionWS = SafeNormalize(viewDirectionWS);
// GI Lighting
half3 bakedGI;
#ifdef LIGHTMAP_ON
lightMapUV = lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;
bakedGI = SAMPLE_GI(lightMapUV, half3(0,0,0), normalWS);
#else
bakedGI = SampleSH(normalWS);
#endif
BRDFData brdfData;
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
// Do not apply energy conservation
brdfData.diffuse = albedo;
brdfData.specular = specular;
AdditionalData addData;
//addData.tangentWS = tangentWS;
//addData.bitangentWS = bitangentWS;
// Charlie Sheen
//addData.partLambdaV = 0.0h;
//addData.anisoReflectionNormal = normalWS;
float NdotV = dot(normalWS, viewDirectionWS);
addData.sheenColor = sheenColor;
// Get Shadow Sampling Coords / Unfortunately per pixel...
#if SHADOWS_SCREEN
float4 clipPos = TransformWorldToHClip(positionWS);
float4 shadowCoord = ComputeScreenPos(clipPos);
#else
float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
#endif
Light mainLight = GetMainLight(shadowCoord);
MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0));
// GI
FinalLighting = GlobalIllumination(brdfData, bakedGI, occlusion, normalWS, viewDirectionWS);
// Main Light
half NdotL = saturate(dot(normalWS, mainLight.direction));
FinalLighting += LightingPhysicallyBased_LuxCharlieSheen(brdfData, addData, mainLight, normalWS, viewDirectionWS, NdotL);
// transmission
if (enableTransmission) {
half3 transLightDir = mainLight.direction + normalWS * transmissionDistortion;
half transDot = dot( transLightDir, -viewDirectionWS );
transDot = exp2(saturate(transDot) * transmissionPower - transmissionPower);
FinalLighting += brdfData.diffuse * transDot * (1.0h - NdotL) * mainLight.color * lerp(1.0h, mainLight.shadowAttenuation, transmissionShadowstrength) * transmissionStrength * 4;
}
// Handle additional lights
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint i = 0u; i < pixelLightCount; ++i) {
Light light = GetAdditionalLight(i, positionWS);
NdotL = saturate(dot(normalWS, light.direction ));
FinalLighting += LightingPhysicallyBased_LuxCharlieSheen(brdfData, addData, light, normalWS, viewDirectionWS, NdotL);
// transmission
if (enableTransmission) {
half3 transLightDir = light.direction + normalWS * transmissionDistortion;
half transDot = dot( transLightDir, -viewDirectionWS );
transDot = exp2(saturate(transDot) * transmissionPower - transmissionPower);
NdotL = saturate(dot(normalWS, light.direction));
FinalLighting += brdfData.diffuse * transDot * (1.0h - NdotL) * light.color * lerp(1.0h, light.shadowAttenuation, transmissionShadowstrength) * light.distanceAttenuation * transmissionStrength * 4;
}
}
#endif
// Set Albedo for meta pass
#if defined(LIGHTWEIGHT_META_PASS_INCLUDED) || defined(UNIVERSAL_META_PASS_INCLUDED)
FinalLighting = half3(0,0,0);
MetaAlbedo = albedo;
MetaSpecular = specular;
#else
MetaAlbedo = half3(0,0,0);
MetaSpecular = half3(0,0,0);
#endif
// End Real Lighting ----------
#endif
}
// Unity 2019.1. needs a float version
void Lighting_float(
// Base inputs
float3 positionWS,
half3 viewDirectionWS,
// Normal inputs
half3 normalWS,
half3 tangentWS,
half3 bitangentWS,
bool enableNormalMapping,
half3 normalTS,
// Surface description
half3 albedo,
half metallic,
half3 specular,
half smoothness,
half occlusion,
half alpha,
// Lighting specific inputs
half3 sheenColor,
bool enableTransmission,
half transmissionStrength,
half transmissionPower,
half transmissionDistortion,
half transmissionShadowstrength,
// Lightmapping
float2 lightMapUV,
// Final lit color
out half3 MetaAlbedo,
out half3 FinalLighting,
out half3 MetaSpecular
)
{
Lighting_half(
positionWS, viewDirectionWS, normalWS, tangentWS, bitangentWS, enableNormalMapping, normalTS,
albedo, metallic, specular, smoothness, occlusion, alpha,
sheenColor, enableTransmission, transmissionStrength, transmissionPower, transmissionDistortion, transmissionShadowstrength,
lightMapUV, MetaAlbedo, FinalLighting, MetaSpecular);
}