Unity Web Shader IDE
Full source <URP>/ShaderLibrary/SixWayLighting.hlsl HLSL 179 lines 72 symbols 7 includes Hide source Show source
SixWayLighting.hlsl <URP>/ShaderLibrary/SixWayLighting.hlsl
Language
HLSL
Lines
179
Symbols
72
Includes
7
Open IDE root

<URP>/ShaderLibrary/SixWayLighting.hlsl full source

#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] * kInvClampedCosine1, diffuseGIData[i].xyz);
        diffuseGIData[i].w = apvSample.L0[i];
    }
}
#endif

void GatherDiffuseGIData(float3 positionWS, float3 normalWS, float4 tangentWS, inout half4 diffuseGIData0, inout half4 diffuseGIData1, inout half4 diffuseGIData2)
{
    #if defined(LIGHTMAP_ON)
    //Do nothing
    #else
        half4 diffuseGIData[] = {diffuseGIData0, diffuseGIData1, diffuseGIData2};
        float crossSign = (tangentWS.w > 0.0 ? 1.0 : -1.0) * GetOddNegativeScale();
        float3 bitangentWS = crossSign * cross(normalWS, tangentWS.xyz);
        float3x3 tbn = float3x3(tangentWS.xyz, bitangentWS, -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] * kInvClampedCosine1, 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[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_CLUSTER_LIGHT_LOOP
    for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
    {
        CLUSTER_LIGHT_LOOP_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