UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/ShaderLibrary/SixWayLighting.hlsl

178 lines
6.3 KiB
HLSL
Raw Permalink Normal View History

2024-10-27 10:53:47 +03:00
#ifndef SIXWAY_LIGHTING_INCLUDED
#define SIXWAY_LIGHTING_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging3D.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/GlobalIllumination.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/AmbientOcclusion.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SixWayLighting.hlsl"
struct SixWaySurfaceData
{
half3 rightTopBack;
half3 leftBottomFront;
half3 emission;
half4 diffuseGIData0;
half4 diffuseGIData1;
half4 diffuseGIData2;
half3 baseColor;
half alpha;
half occlusion;
half absorptionRange;
};
LightingData CreateLightingData(SixWaySurfaceData surfaceData)
{
LightingData lightingData;
ZERO_INITIALIZE( LightingData, lightingData);
lightingData.emissionColor = surfaceData.emission;
lightingData.mainLightColor = 0;
lightingData.additionalLightsColor = 0;
return lightingData;
}
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
void SampleAPVSixWay(APVSample apvSample, half3x3 tbn, out half4 diffuseGIData[3])
{
[unroll]
for (int i = 0; i<3; i++)
{
EvaluateAPVL1(apvSample, tbn[i], diffuseGIData[i].xyz);
diffuseGIData[i].w = apvSample.L0[i];
}
}
#endif
void GatherDiffuseGIData(float3 positionWS, float3 normalWS, float3 tangentWS, inout half4 diffuseGIData0, inout half4 diffuseGIData1, inout half4 diffuseGIData2)
{
#if defined(LIGHTMAP_ON)
//Do nothing
#else
half4 diffuseGIData[] = {diffuseGIData0, diffuseGIData1, diffuseGIData2};
float3x3 tbn = float3x3(tangentWS, cross(-normalWS, tangentWS), -normalWS);
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
APVSample apvSample = SampleAPV(positionWS, normalWS, 0xFFFFFFFF, 0);
if (apvSample.status != APV_SAMPLE_STATUS_INVALID)
{
apvSample.Decode();
SampleAPVSixWay(apvSample, tbn, diffuseGIData);
}
#else
half3 L0 = half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
for (int i = 0; i<3; i++)
{
diffuseGIData[i].xyz = SHEvalLinearL1(tbn[i], unity_SHAr.xyz, unity_SHAg.xyz, unity_SHAb.xyz);
diffuseGIData[i].w = L0[i];
}
#endif
diffuseGIData0 = diffuseGIData[0];
diffuseGIData1 = diffuseGIData[1];
diffuseGIData2 = diffuseGIData[2];
#endif
}
half3 ComputeGIColor(SixWaySurfaceData surfaceData)
{
half4 diffuseGIData0 = surfaceData.diffuseGIData0;
half4 diffuseGIData1 = surfaceData.diffuseGIData1;
half4 diffuseGIData2 = surfaceData.diffuseGIData2;
const half3 L0 = half3(diffuseGIData0.w, diffuseGIData1.w, diffuseGIData2.w);
const real3 diffuseGIData[3] = {diffuseGIData0.xyz, diffuseGIData1.xyz, diffuseGIData2.xyz};
#if defined(_BLENDMODE_PREMULTIPLY)
bool alphaPremultipled = true;
#else
bool alphaPremultipled = false;
#endif
half3 giColor = GetSixWayDiffuseContributions(surfaceData.rightTopBack, surfaceData.leftBottomFront,
half4(surfaceData.baseColor, surfaceData.alpha), L0, diffuseGIData,
surfaceData.absorptionRange, alphaPremultipled);
giColor *= surfaceData.occlusion;
return giColor;
}
half3 SixWayLightBlend(SixWaySurfaceData surfaceData, Light light, half3x3 tangentToWorld)
{
half3x3 localFrame = tangentToWorld;
localFrame[1] *= -1;
localFrame[2] *= -1;
half3 dir = mul(localFrame, light.direction);
half3 weights = dir >= 0 ? surfaceData.rightTopBack.xyz : surfaceData.leftBottomFront.xyz;
half3 sqrDir = dir*dir;
half transmission = dot(sqrDir, weights);
#if defined(_BLENDMODE_PREMULTIPLY)
bool alphaPremultipled = true;
#else
bool alphaPremultipled = false;
#endif
half3 cbsdf_R = GetTransmissionWithAbsorption(transmission, half4(surfaceData.baseColor, surfaceData.alpha), surfaceData.absorptionRange, alphaPremultipled);
half3 radiance = light.color * light.distanceAttenuation * light.shadowAttenuation;
return PI * cbsdf_R * radiance; // *PI because URP doesn't multiply by the Lambert term in its Lit implementation
}
half4 UniversalFragmentSixWay(InputData inputData, SixWaySurfaceData surfaceData)
{
if(surfaceData.alpha == 0)
return half4(0,0,0,0);
half4 shadowMask = CalculateShadowMask(inputData);
uint meshRenderingLayers = GetMeshRenderingLayer();
AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData.normalizedScreenSpaceUV, 1.0f);
Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);
LightingData lightingData = CreateLightingData(surfaceData);
lightingData.giColor = ComputeGIColor(surfaceData);
#ifdef _LIGHT_LAYERS
if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
#endif
{
lightingData.mainLightColor = SixWayLightBlend(surfaceData, mainLight, inputData.tangentToWorld);
}
#if defined(_ADDITIONAL_LIGHTS)
uint pixelLightCount = GetAdditionalLightsCount();
#if USE_FORWARD_PLUS
for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
{
FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
#ifdef _LIGHT_LAYERS
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
{
lightingData.additionalLightsColor += SixWayLightBlend(surfaceData, light, inputData.tangentToWorld);
}
}
#endif
LIGHT_LOOP_BEGIN(pixelLightCount)
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
#ifdef _LIGHT_LAYERS
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
{
lightingData.additionalLightsColor += SixWayLightBlend(surfaceData, light, inputData.tangentToWorld);
}
LIGHT_LOOP_END
#endif
return CalculateFinalColor(lightingData, surfaceData.alpha);
}
#endif