178 lines
6.3 KiB
HLSL
178 lines
6.3 KiB
HLSL
#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
|