629 lines
19 KiB
HLSL
629 lines
19 KiB
HLSL
#ifndef ALLIN13DSHADER_HELPER_URP_INCLUDED
|
|
#define ALLIN13DSHADER_HELPER_URP_INCLUDED
|
|
|
|
#define NUM_ADDITIONAL_LIGHTS GetNumAdditionalLights();
|
|
|
|
#define OBJECT_TO_WORLD_MATRIX GetObjectToWorldMatrix()
|
|
|
|
#if defined(ALLIN1_DECALS_SUPPORT) && defined(_DBUFFER)
|
|
#define ALLIN1_DECALS_READY_TO_USE
|
|
|
|
#if defined(_DBUFFER_MRT1) || defined(_DBUFFER_MRT2) || defined(_DBUFFER_MRT3)
|
|
#define ALLIN1_DECAL_MODE_DBUFFER
|
|
#else
|
|
#define ALLIN1_DECAL_MODE_SCREEN_SPACE
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef REQUIRE_SCENE_DEPTH
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
|
|
|
float GetRawDepth(float4 projPos)
|
|
{
|
|
float res = SampleSceneDepth(projPos.xy / projPos.w);
|
|
return res;
|
|
}
|
|
|
|
float GetLinearDepth01(float4 projPos)
|
|
{
|
|
float rawDepth = GetRawDepth(projPos);
|
|
float res = Linear01Depth (rawDepth, _ZBufferParams);
|
|
|
|
return res;
|
|
}
|
|
|
|
float GetSceneDepthDiff(float4 projPos)
|
|
{
|
|
float rawDepth = GetRawDepth(projPos);
|
|
float res = LinearEyeDepth(rawDepth, _ZBufferParams) - projPos.z;
|
|
|
|
return res;
|
|
}
|
|
|
|
#endif
|
|
|
|
float3 GetNormalWS(float3 normalOS)
|
|
{
|
|
float3 normalWS = TransformObjectToWorldNormal(normalOS);
|
|
return normalWS;
|
|
}
|
|
|
|
float3 GetViewDirWS(float3 vertexWS)
|
|
{
|
|
float3 res = GetWorldSpaceViewDir(vertexWS);
|
|
return res;
|
|
}
|
|
|
|
float3 GetPositionVS(float3 positionOS)
|
|
{
|
|
float3 res = TransformWorldToView(positionOS);
|
|
return res;
|
|
}
|
|
|
|
float3 GetPositionWS(float4 positionOS)
|
|
{
|
|
return TransformObjectToWorld(positionOS.xyz);
|
|
}
|
|
|
|
float3 GetPositionOS(float4 positionWS)
|
|
{
|
|
return TransformWorldToObject(positionWS.xyz);
|
|
|
|
}
|
|
|
|
float3 GetDirWS(float4 dirOS)
|
|
{
|
|
return TransformObjectToWorldDir(dirOS.xyz);
|
|
}
|
|
|
|
float3 GetDirOSFloat3(float3 dirOS)
|
|
{
|
|
return TransformObjectToWorldDir(dirOS.xyz);
|
|
}
|
|
|
|
float3 GetDirOS(float4 dirOS)
|
|
{
|
|
return GetDirOSFloat3(dirOS.xyz);
|
|
}
|
|
|
|
float3 GetMainLightDir(float3 vertexWS)
|
|
{
|
|
#ifdef _LIGHTMODEL_FASTLIGHTING
|
|
float3 res = global_lightDirection;
|
|
#else
|
|
float3 res = GetMainLight().direction;
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
float3 GetMainLightColorRGB()
|
|
{
|
|
#ifdef _LIGHTMODEL_FASTLIGHTING
|
|
float3 res = global_lightColor.rgb;
|
|
#else
|
|
float3 res = GetMainLight().color;
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
float2 GetSSAO(float2 normalizedScreenSpaceUV, float alpha)
|
|
{
|
|
AmbientOcclusionFactor aoFactorURP = GetScreenSpaceAmbientOcclusion(normalizedScreenSpaceUV);
|
|
|
|
#if defined(_ALLIN13D_SURFACE_TRANSPARENT)
|
|
float2 res = float2(1, 1);
|
|
#else
|
|
float2 res = float2(aoFactorURP.directAmbientOcclusion, aoFactorURP.indirectAmbientOcclusion);
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
//normalWS needed for the equivalent method in BIRP
|
|
//effectsData needed for the equivalent method in BIRP
|
|
AllIn1LightData GetPointLightData(int index, float3 vertexWS, float3 normalWS, EffectsData effectsData, AllIn1GI gi)
|
|
{
|
|
AllIn1LightData lightData;
|
|
|
|
Light additionalLight = GetAdditionalLight(index, vertexWS, gi.shadowMask);
|
|
lightData.lightColor = additionalLight.color;
|
|
lightData.lightDir = additionalLight.direction;
|
|
|
|
#ifdef _CLUSTER_LIGHT_LOOP
|
|
int lightIndex = index;
|
|
#else
|
|
int lightIndex = GetPerObjectLightIndex(index);
|
|
#endif
|
|
|
|
#if defined(_LIGHT_COOKIES)
|
|
float3 cookieColor = SampleAdditionalLightCookie(lightIndex, effectsData.vertexWS);
|
|
lightData.lightColor *= cookieColor;
|
|
#endif
|
|
|
|
#ifdef _RECEIVE_SHADOWS_ON
|
|
lightData.realtimeShadow = additionalLight.shadowAttenuation;
|
|
#else
|
|
lightData.realtimeShadow = 1.0;
|
|
#endif
|
|
|
|
lightData.distanceAttenuation = additionalLight.distanceAttenuation;
|
|
lightData.shadowColor = lightData.realtimeShadow;
|
|
lightData.layerMask = additionalLight.layerMask;
|
|
|
|
return lightData;
|
|
}
|
|
|
|
AllIn1LightData GetMainLightData(float3 vertexWS, EffectsData effectsData, AllIn1GI gi)
|
|
{
|
|
AllIn1LightData lightData;
|
|
|
|
#if defined(_LIGHTMODEL_NONE)
|
|
lightData.lightColor = float3(1.0, 1.0, 1.0);
|
|
lightData.lightDir = float3(0.0, 1.0, 0.0);
|
|
lightData.distanceAttenuation = 1.0;
|
|
lightData.shadowColor = 1.0;
|
|
lightData.realtimeShadow = 1.0;
|
|
lightData.layerMask = 1;
|
|
#elif defined(_LIGHTMODEL_FASTLIGHTING)
|
|
lightData.lightColor = global_lightColor;
|
|
lightData.lightDir = global_lightDirection;
|
|
lightData.distanceAttenuation = 1.0;
|
|
lightData.shadowColor = 1.0;
|
|
lightData.realtimeShadow = 1.0;
|
|
lightData.layerMask = 1;
|
|
#else
|
|
Light mainLight = GetMainLight();
|
|
lightData.lightColor = mainLight.color;
|
|
lightData.lightDir = mainLight.direction;
|
|
|
|
lightData.distanceAttenuation = mainLight.distanceAttenuation;
|
|
|
|
float4 shadowCoords = TransformWorldToShadowCoord(vertexWS);
|
|
#ifdef _RECEIVE_SHADOWS_ON
|
|
lightData.realtimeShadow = MainLightRealtimeShadow(shadowCoords);
|
|
#if defined(_RECEIVEDSHADOWSTYPE_STYLIZED)
|
|
lightData.realtimeShadow = AntiAliasing(lightData.realtimeShadow, ACCESS_PROP_FLOAT(_ShadowCutoff));
|
|
#endif
|
|
|
|
float shadowFade = GetMainLightShadowFade(effectsData.vertexWS);
|
|
float shadowMask = 1.0;
|
|
#if defined(SHADOWS_SHADOWMASK)
|
|
shadowMask = gi.shadowMask.r;
|
|
#endif
|
|
lightData.realtimeShadow = lerp(lightData.realtimeShadow, shadowMask, shadowFade);
|
|
#else
|
|
lightData.realtimeShadow = 1.0;
|
|
#endif
|
|
|
|
lightData.shadowColor = lightData.realtimeShadow;
|
|
lightData.layerMask = mainLight.layerMask;
|
|
|
|
#if defined(_LIGHT_COOKIES)
|
|
float3 cookieColor = SampleMainLightCookie(effectsData.vertexWS);
|
|
lightData.lightColor *= cookieColor;
|
|
#endif
|
|
#endif
|
|
|
|
return lightData;
|
|
}
|
|
|
|
int GetNumAdditionalLights()
|
|
{
|
|
return GetAdditionalLightsCount();
|
|
}
|
|
|
|
/*Needed for URP shadow caster pass*/
|
|
float3 _LightDirection;
|
|
float3 _LightPosition;
|
|
/************/
|
|
FragmentDataShadowCaster GetClipPosShadowCaster(VertexData v, FragmentDataShadowCaster input)
|
|
{
|
|
float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
|
|
float3 normalWS = TransformObjectToWorldNormal(v.normal);
|
|
|
|
#if _CASTING_PUNCTUAL_LIGHT_SHADOW
|
|
float3 lightDirectionWS = normalize(_LightPosition - positionWS);
|
|
#else
|
|
float3 lightDirectionWS = _LightDirection;
|
|
#endif
|
|
|
|
float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS));
|
|
|
|
#if UNITY_REVERSED_Z
|
|
positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE);
|
|
#else
|
|
positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE);
|
|
#endif
|
|
|
|
input.pos = positionCS;
|
|
return input;
|
|
}
|
|
|
|
ShadowCoordStruct GetShadowCoords(VertexData v, float4 clipPos, float3 vertexWS, float2 uvLightmap)
|
|
{
|
|
ShadowCoordStruct res;
|
|
|
|
res._ShadowCoord = 0;
|
|
res.pos = clipPos;
|
|
|
|
return res;
|
|
}
|
|
|
|
float GetShadowAttenuation(EffectsData data)
|
|
{
|
|
float res = 1.0;
|
|
|
|
#if !defined(_LIGHTMODEL_FASTLIGHTING)
|
|
|
|
float4 shadowCoords = TransformWorldToShadowCoord(data.vertexWS);
|
|
|
|
float mainLightShadow = MainLightRealtimeShadow(shadowCoords);
|
|
|
|
//int numAdditionalLights = NUM_ADDITIONAL_LIGHTS;
|
|
//float additionalLightsShadows = 1.0;
|
|
res = mainLightShadow;
|
|
//for(int lightIndex = 0; lightIndex < numAdditionalLights; lightIndex++)
|
|
//{
|
|
// Light additionalLight = GetAdditionalLight(lightIndex, vertexWS);
|
|
// float additionalLightShadow = AdditionalLightRealtimeShadow(lightIndex, vertexWS/*, additionalLight.direction*/) * additionalLight.distanceAttenuation;
|
|
|
|
// res *= additionalLightShadow;
|
|
//}
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
//float GetShadowAttenuation(float3 vertexWS)
|
|
//{
|
|
// float4 shadowCoords = TransformWorldToShadowCoord(vertexWS);
|
|
// float mainLightShadow = MainLightRealtimeShadow(shadowCoords);
|
|
|
|
// float res = mainLightShadow;
|
|
// int numAdditionalLights = NUM_ADDITIONAL_LIGHTS;
|
|
// for(int lightIndex = 0; lightIndex < numAdditionalLights; lightIndex++)
|
|
// {
|
|
// Light additionalLight = GetAdditionalLight(lightIndex, vertexWS);
|
|
// float additionalLightShadow = AdditionalLightRealtimeShadow(lightIndex, vertexWS) * additionalLight.distanceAttenuation;
|
|
|
|
// res += additionalLightShadow;
|
|
// }
|
|
|
|
// res = 1.0;
|
|
// return res;
|
|
//}
|
|
|
|
float3 GetLightmap(float2 uvLightmap, EffectsData data)
|
|
{
|
|
float3 res = 0.0;
|
|
|
|
#if defined(_AFFECTED_BY_LIGHTMAPS_ON) && defined(LIGHTMAP_ON)
|
|
res = SampleLightmap(uvLightmap, data.normalWS);
|
|
#ifdef SUBTRACTIVE_LIGHTING
|
|
AllIn1LightData mainLight = GetMainLightData(data.vertexWS, data);
|
|
float attenuation = mainLight.realtimeShadow;
|
|
float ndotl = saturate(dot(data.normalWS, mainLight.lightDir));
|
|
float3 shadowedLightEstimate =
|
|
ndotl * (1 - attenuation) * mainLight.lightColor.rgb;
|
|
float3 subtractedLight = res - shadowedLightEstimate;
|
|
subtractedLight = max(subtractedLight, _SubtractiveShadowColor.xyz);
|
|
subtractedLight = lerp(subtractedLight, res, attenuation);
|
|
|
|
res = subtractedLight;
|
|
#endif
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
uint AllIn1GetMeshRenderingLayer()
|
|
{
|
|
uint res;
|
|
#if UNITY_VERSION >= 202230
|
|
res = GetMeshRenderingLayer();
|
|
#else
|
|
res = GetMeshRenderingLightLayer();
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
float3 GetAmbientColor(EffectsData data)
|
|
{
|
|
float3 res = float3(0, 0, 0);
|
|
#if !defined(LIGHTMAP_ON)
|
|
#if defined(_CUSTOM_AMBIENT_LIGHT_ON)
|
|
res = ACCESS_PROP_FLOAT4(_CustomAmbientColor).rgb;
|
|
#else
|
|
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
|
|
half3 bakedGI;
|
|
float4 probeOcclusion;
|
|
EvaluateAdaptiveProbeVolume(data.vertexWS.xyz, data.normalWS.xyz, data.viewDirWS.xyz,
|
|
data.projPos.xy, AllIn1GetMeshRenderingLayer(),
|
|
bakedGI, probeOcclusion);
|
|
res = bakedGI;
|
|
#else
|
|
res = SampleSH(data.normalWS);
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
AllIn1GI CalculateGI(float2 uvLightmap, EffectsData data)
|
|
{
|
|
AllIn1GI res;
|
|
INIT_GI(res);
|
|
|
|
#if defined(LIGHTMAP_ON)
|
|
res.diffuse = GetLightmap(uvLightmap, data);
|
|
#else
|
|
res.diffuse = GetAmbientColor(data);
|
|
#endif
|
|
|
|
#if defined(SHADOWS_SHADOWMASK)
|
|
res.shadowMask = SAMPLE_TEXTURE2D(unity_ShadowMask, samplerunity_ShadowMask, uvLightmap);
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
float GetFogFactor(float4 clipPos)
|
|
{
|
|
float res = 0;
|
|
|
|
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
|
|
res = ComputeFogFactor(clipPos.z);
|
|
#endif
|
|
|
|
return res;
|
|
}
|
|
|
|
#if defined(FOG_ENABLED)
|
|
float4 CustomMixFog(float fogFactor, float4 col)
|
|
{
|
|
float4 res = col;
|
|
res.rgb = MixFog(res.rgb, fogFactor);
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
void ConfigureDecalData(inout AllIn1DecalData allIn1Decal, float4 positionCS)
|
|
{
|
|
#if defined(_DBUFFER)
|
|
FETCH_DBUFFER(DBuffer, _DBufferTexture, int2(positionCS.xy));
|
|
|
|
DecalSurfaceData decalSurfaceData;
|
|
DECODE_FROM_DBUFFER(DBuffer, decalSurfaceData);
|
|
|
|
allIn1Decal.baseColor = decalSurfaceData.baseColor;
|
|
allIn1Decal.emissive = decalSurfaceData.emissive;
|
|
allIn1Decal.mask = step(0.1, allIn1Decal.baseColor.a);
|
|
allIn1Decal.mask = saturate(allIn1Decal.mask + decalSurfaceData.normalWS.w);
|
|
allIn1Decal.MAOSAlpha = decalSurfaceData.MAOSAlpha;
|
|
allIn1Decal.smoothness = decalSurfaceData.smoothness;
|
|
allIn1Decal.metallic = decalSurfaceData.metallic;
|
|
|
|
float4 normalTS = decalSurfaceData.normalWS; //Even if it's called normalWS, the content is a sampled normal map in tangent space
|
|
|
|
allIn1Decal.normalTS = lerp(normalTS, DEFAULT_NORMAL_MAP_VALUE, allIn1Decal.mask);
|
|
allIn1Decal.unpackedNormal = UnpackNormal(allIn1Decal.normalTS);
|
|
#endif
|
|
}
|
|
|
|
#ifdef REFLECTIONS_ON
|
|
|
|
float3 BoxProjection (
|
|
float3 direction, float3 position,
|
|
float4 cubemapPosition, float3 boxMin, float3 boxMax
|
|
) {
|
|
#if UNITY_SPECCUBE_BOX_PROJECTION
|
|
UNITY_BRANCH
|
|
if (cubemapPosition.w > 0) {
|
|
float3 factors =
|
|
((direction > 0 ? boxMax : boxMin) - position) / direction;
|
|
float scalar = min(min(factors.x, factors.y), factors.z);
|
|
direction = direction * scalar + (position - cubemapPosition.xyz);
|
|
}
|
|
#endif
|
|
return direction;
|
|
}
|
|
|
|
float3 GetReflectionsSimple(float3 worldRefl, float cubeLod, float3 positionWS)
|
|
{
|
|
half probe0Volume = CalculateProbeVolumeSqrMagnitude(unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
|
|
half probe1Volume = CalculateProbeVolumeSqrMagnitude(unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
|
|
|
|
half volumeDiff = probe0Volume - probe1Volume;
|
|
float importanceSign = unity_SpecCube1_BoxMin.w;
|
|
|
|
float desiredWeightProbe0 = CalculateProbeWeight(positionWS, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
|
|
float desiredWeightProbe1 = CalculateProbeWeight(positionWS, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
|
|
|
|
// A probe is dominant if its importance is higher
|
|
// Or have equal importance but smaller volume
|
|
bool probe0Dominant = importanceSign > 0.0f || (importanceSign == 0.0f && volumeDiff < -0.0001h);
|
|
bool probe1Dominant = importanceSign < 0.0f || (importanceSign == 0.0f && volumeDiff > 0.0001h);
|
|
|
|
float weightProbe0 = probe1Dominant ? min(desiredWeightProbe0, 1.0f - desiredWeightProbe1) : desiredWeightProbe0;
|
|
float weightProbe1 = probe0Dominant ? min(desiredWeightProbe1, 1.0f - desiredWeightProbe0) : desiredWeightProbe1;
|
|
|
|
float totalWeight = weightProbe0 + weightProbe1;
|
|
|
|
// If either probe 0 or probe 1 is dominant the sum of weights is guaranteed to be 1.
|
|
// If neither is dominant this is not guaranteed - only normalize weights if totalweight exceeds 1.
|
|
weightProbe0 /= max(totalWeight, 1.0f);
|
|
weightProbe1 /= max(totalWeight, 1.0f);
|
|
|
|
float3 res = 0;
|
|
if(weightProbe0 > 0.01)
|
|
{
|
|
float3 reflUV0 = BoxProjection(worldRefl, positionWS, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin.xyz, unity_SpecCube0_BoxMax.xyz);
|
|
float4 probe0HDR = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflUV0, cubeLod);
|
|
float3 probe0 = DecodeHDREnvironment(probe0HDR, unity_SpecCube0_HDR);
|
|
|
|
res += weightProbe0 * probe0;
|
|
}
|
|
if(weightProbe1 > 0.01f)
|
|
{
|
|
float3 reflUV1 = BoxProjection(worldRefl, positionWS, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin.xyz, unity_SpecCube1_BoxMax.xyz);
|
|
float4 probe1HDR = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube1, samplerunity_SpecCube0, reflUV1, cubeLod);
|
|
float3 probe1 = DecodeHDREnvironment(probe1HDR, unity_SpecCube1_HDR);
|
|
|
|
res += weightProbe1 * probe1;
|
|
}
|
|
if(totalWeight < 0.99)
|
|
{
|
|
float4 glossyEnvironmentHDR = SAMPLE_TEXTURECUBE_LOD(_GlossyEnvironmentCubeMap, sampler_GlossyEnvironmentCubeMap, worldRefl, cubeLod);
|
|
float3 glossyEnvironment = DecodeHDREnvironment(glossyEnvironmentHDR, _GlossyEnvironmentCubeMap_HDR);
|
|
|
|
res += (1.0f - totalWeight) * glossyEnvironment;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
float3 GetReflectionsCluster(float3 positionWS, float2 normalizedScreenSpaceUV, float3 worldRefl, float cubeLod)
|
|
{
|
|
float3 res = 0;
|
|
float3 irradiance = float3(0, 0, 0);
|
|
float mip = cubeLod;
|
|
#if USE_CLUSTER_LIGHT_LOOP && CLUSTER_HAS_REFLECTION_PROBES
|
|
float totalWeight = 0.0f;
|
|
uint probeIndex;
|
|
ClusterIterator it = ClusterInit(normalizedScreenSpaceUV, positionWS, 1);
|
|
[loop] while (ClusterNext(it, probeIndex) && totalWeight < 0.99f)
|
|
{
|
|
probeIndex -= URP_FP_PROBES_BEGIN;
|
|
|
|
float weight = CalculateProbeWeight(positionWS, urp_ReflProbes_BoxMin[probeIndex], urp_ReflProbes_BoxMax[probeIndex]);
|
|
weight = min(weight, 1.0f - totalWeight);
|
|
|
|
half3 sampleVector = worldRefl;
|
|
#ifdef _REFLECTION_PROBE_BOX_PROJECTION
|
|
sampleVector = BoxProjectedCubemapDirection(worldRefl, positionWS, urp_ReflProbes_ProbePosition[probeIndex], urp_ReflProbes_BoxMin[probeIndex], urp_ReflProbes_BoxMax[probeIndex]);
|
|
#endif // _REFLECTION_PROBE_BOX_PROJECTION
|
|
|
|
uint maxMip = (uint)abs(urp_ReflProbes_ProbePosition[probeIndex].w) - 1;
|
|
half probeMip = min(mip, maxMip);
|
|
float2 uv = saturate(PackNormalOctQuadEncode(sampleVector) * 0.5 + 0.5);
|
|
|
|
float mip0 = floor(probeMip);
|
|
float mip1 = mip0 + 1;
|
|
float mipBlend = probeMip - mip0;
|
|
float4 scaleOffset0 = urp_ReflProbes_MipScaleOffset[probeIndex * 7 + (uint)mip0];
|
|
float4 scaleOffset1 = urp_ReflProbes_MipScaleOffset[probeIndex * 7 + (uint)mip1];
|
|
|
|
half3 irradiance0 = half4(SAMPLE_TEXTURE2D_LOD(urp_ReflProbes_Atlas, sampler_LinearClamp, uv * scaleOffset0.xy + scaleOffset0.zw, 0.0)).rgb;
|
|
half3 irradiance1 = half4(SAMPLE_TEXTURE2D_LOD(urp_ReflProbes_Atlas, sampler_LinearClamp, uv * scaleOffset1.xy + scaleOffset1.zw, 0.0)).rgb;
|
|
res += weight * lerp(irradiance0, irradiance1, mipBlend);
|
|
totalWeight += weight;
|
|
}
|
|
#else
|
|
half probe0Volume = CalculateProbeVolumeSqrMagnitude(unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
|
|
half probe1Volume = CalculateProbeVolumeSqrMagnitude(unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
|
|
|
|
half volumeDiff = probe0Volume - probe1Volume;
|
|
float importanceSign = unity_SpecCube1_BoxMin.w;
|
|
|
|
// A probe is dominant if its importance is higher
|
|
// Or have equal importance but smaller volume
|
|
bool probe0Dominant = importanceSign > 0.0f || (importanceSign == 0.0f && volumeDiff < -0.0001h);
|
|
bool probe1Dominant = importanceSign < 0.0f || (importanceSign == 0.0f && volumeDiff > 0.0001h);
|
|
|
|
float desiredWeightProbe0 = CalculateProbeWeight(positionWS, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
|
|
float desiredWeightProbe1 = CalculateProbeWeight(positionWS, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
|
|
|
|
// Subject the probes weight if the other probe is dominant
|
|
float weightProbe0 = probe1Dominant ? min(desiredWeightProbe0, 1.0f - desiredWeightProbe1) : desiredWeightProbe0;
|
|
float weightProbe1 = probe0Dominant ? min(desiredWeightProbe1, 1.0f - desiredWeightProbe0) : desiredWeightProbe1;
|
|
|
|
float totalWeight = weightProbe0 + weightProbe1;
|
|
|
|
// If either probe 0 or probe 1 is dominant the sum of weights is guaranteed to be 1.
|
|
// If neither is dominant this is not guaranteed - only normalize weights if totalweight exceeds 1.
|
|
weightProbe0 /= max(totalWeight, 1.0f);
|
|
weightProbe1 /= max(totalWeight, 1.0f);
|
|
|
|
// Sample the first reflection probe
|
|
if (weightProbe0 > 0.01f)
|
|
{
|
|
half3 reflectVector0 = worldRefl;
|
|
#ifdef _REFLECTION_PROBE_BOX_PROJECTION
|
|
reflectVector0 = BoxProjectedCubemapDirection(worldRefl, positionWS, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
|
|
#endif // _REFLECTION_PROBE_BOX_PROJECTION
|
|
|
|
half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector0, mip));
|
|
|
|
irradiance += weightProbe0 * DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
|
|
}
|
|
|
|
// Sample the second reflection probe
|
|
if (weightProbe1 > 0.01f)
|
|
{
|
|
half3 reflectVector1 = worldRefl;
|
|
#ifdef _REFLECTION_PROBE_BOX_PROJECTION
|
|
worldRefl = BoxProjectedCubemapDirection(worldRefl, positionWS, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
|
|
#endif // _REFLECTION_PROBE_BOX_PROJECTION
|
|
half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube1, samplerunity_SpecCube1, worldRefl, mip));
|
|
|
|
irradiance += weightProbe1 * DecodeHDREnvironment(encodedIrradiance, unity_SpecCube1_HDR);
|
|
}
|
|
|
|
res = irradiance;
|
|
#endif
|
|
|
|
// Use any remaining weight to blend to environment reflection cube map
|
|
if (totalWeight < 0.99f)
|
|
{
|
|
half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(_GlossyEnvironmentCubeMap, sampler_GlossyEnvironmentCubeMap, worldRefl, mip));
|
|
|
|
res += (1.0f - totalWeight) * DecodeHDREnvironment(encodedIrradiance, _GlossyEnvironmentCubeMap_HDR);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
float3 GetSkyColor(float3 positionWS, float2 normalizedScreenSpaceUV, float3 normalWS, float3 viewDirWS, float cubeLod)
|
|
{
|
|
float3 worldRefl = normalize(reflect(-viewDirWS, normalWS));
|
|
float4 skyData = 0;
|
|
float3 res = 0;
|
|
|
|
#ifdef _REFLECTION_PROBE_BLENDING
|
|
#if USE_CLUSTER_LIGHT_LOOP && CLUSTER_HAS_REFLECTION_PROBES
|
|
res = GetReflectionsCluster(positionWS, normalizedScreenSpaceUV, worldRefl, cubeLod);
|
|
#else
|
|
res = GetReflectionsSimple(worldRefl, cubeLod, positionWS);
|
|
#endif
|
|
#else
|
|
res = GetReflectionsSimple(worldRefl, cubeLod, positionWS);
|
|
#endif
|
|
|
|
#ifdef _REFLECTIONS_TOON
|
|
float posterizationLevel = lerp(2, 20, ACCESS_PROP_FLOAT(_ToonFactor));
|
|
res = floor(res * posterizationLevel) / posterizationLevel;
|
|
#endif
|
|
|
|
res *= ACCESS_PROP_FLOAT(_ReflectionsAtten);
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
float3 ShadeSH(float4 normalWS)
|
|
{
|
|
float3 res = SampleSH(normalWS.xyz);
|
|
return res;
|
|
}
|
|
|
|
#define OBJECT_TO_CLIP_SPACE(v) TransformObjectToHClip(v.vertex.xyz)
|
|
#define OBJECT_TO_CLIP_SPACE_FLOAT4(pos) TransformObjectToHClip(pos.xyz)
|
|
#define ALLIN1_APPLY_CROSSFADE(input) LODFadeCrossFade(input.pos);
|
|
|
|
#endif |