285 lines
10 KiB
HLSL
285 lines
10 KiB
HLSL
#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);
|
||
} |