649 lines
21 KiB
Plaintext
649 lines
21 KiB
Plaintext
|
|
#if _DECAL_MAX0
|
|
#define _DECALMAX 1
|
|
#elif _DECAL_MAX4
|
|
#define _DECALMAX 4
|
|
#elif _DECAL_MAX8
|
|
#define _DECALMAX 8
|
|
#elif _DECAL_MAX16
|
|
#define _DECALMAX 16
|
|
#elif _DECAL_MAX32
|
|
#define _DECALMAX 32
|
|
#elif _DECAL_MAX64
|
|
#define _DECALMAX 64
|
|
#elif _DECAL_MAX128
|
|
#define _DECALMAX 128
|
|
#elif _DECAL_MAX256
|
|
#define _DECALMAX 256
|
|
#else
|
|
#define _DECALMAX 1
|
|
#endif
|
|
|
|
#if _DECAL_STATICMAX0
|
|
#define _STATICDECALMAX 1
|
|
#elif _DECAL_STATICMAX64
|
|
#define _STATICDECALMAX 64
|
|
#elif _DECAL_STATICMAX128
|
|
#define _STATICDECALMAX 128
|
|
#elif _DECAL_STATICMAX256
|
|
#define _STATICDECALMAX 256
|
|
#elif _DECAL_STATICMAX512
|
|
#define _STATICDECALMAX 512
|
|
#elif _DECAL_STATICMAX1024
|
|
#define _STATICDECALMAX 1024
|
|
#elif _DECAL_STATICMAX2048
|
|
#define _STATICDECALMAX 2048
|
|
#else
|
|
#define _STATICDECALMAX 1
|
|
#endif
|
|
|
|
TEXTURE2D_ARRAY(_DecalAlbedo);
|
|
TEXTURE2D_ARRAY(_DecalNormalSAO);
|
|
|
|
#if _DECAL_EMISMETAL
|
|
TEXTURE2D_ARRAY(_DecalEmisMetal);
|
|
#endif
|
|
|
|
|
|
#if _DECAL_SPLAT
|
|
TEXTURE2D_ARRAY(_DecalSplats);
|
|
#endif
|
|
|
|
|
|
int _MSDecalCount;
|
|
|
|
|
|
TEXTURE2D(_DecalCullData);
|
|
float4 _DecalCullData_TexelSize;
|
|
|
|
UNITY_DECLARE_TEX2D(_DecalControl);
|
|
float4 _DecalControl_TexelSize;
|
|
TEXTURE2D(_DecalStaticData);
|
|
float4 _DecalStaticData_TexelSize;
|
|
TEXTURE2D(_DecalDynamicData);
|
|
float4 _DecalDynamicData_TexelSize;
|
|
|
|
|
|
#define DECALDATA1 4
|
|
#define DECALDATA2 5
|
|
#define DECALSPLATS 6
|
|
#define DECALTINT 7
|
|
|
|
float4 GetDecalStaticData(float index, float y)
|
|
{
|
|
float2 uv = float2(index + 0.5, y + 0.5) * _DecalStaticData_TexelSize.xy;
|
|
return SAMPLE_TEXTURE2D_LOD(_DecalStaticData, sampler_DecalControl, uv, 0);
|
|
}
|
|
|
|
float4x4 GetDecalStaticMtx(float index)
|
|
{
|
|
float4x4 mtx;
|
|
float sz = _DecalStaticData_TexelSize.y;
|
|
float u = index * _DecalStaticData_TexelSize.x;
|
|
mtx._m00_m01_m02_m03 = SAMPLE_TEXTURE2D_LOD(_DecalStaticData, sampler_DecalControl, float2(u, 0), 0);
|
|
mtx._m10_m11_m12_m13 = SAMPLE_TEXTURE2D_LOD(_DecalStaticData, sampler_DecalControl, float2(u, 1*sz), 0);
|
|
mtx._m20_m21_m22_m23 = SAMPLE_TEXTURE2D_LOD(_DecalStaticData, sampler_DecalControl, float2(u, 2*sz), 0);
|
|
mtx._m30_m31_m32_m33 = SAMPLE_TEXTURE2D_LOD(_DecalStaticData, sampler_DecalControl, float2(u, 3*sz), 0);
|
|
return mtx;
|
|
}
|
|
|
|
float4 GetDecalDynamicData(float index, float y)
|
|
{
|
|
float2 uv = float2(index + 0.5, y + 0.5) * _DecalDynamicData_TexelSize.xy;
|
|
return SAMPLE_TEXTURE2D_LOD(_DecalDynamicData, sampler_DecalControl, uv, 0);
|
|
}
|
|
|
|
float4x4 GetDecalDynamicMtx(float index)
|
|
{
|
|
float4x4 mtx;
|
|
float sz = _DecalDynamicData_TexelSize.y;
|
|
float u = index * _DecalDynamicData_TexelSize.x;
|
|
mtx._m00_m01_m02_m03 = SAMPLE_TEXTURE2D_LOD(_DecalDynamicData, sampler_DecalControl, float2(u, 0), 0);
|
|
mtx._m10_m11_m12_m13 = SAMPLE_TEXTURE2D_LOD(_DecalDynamicData, sampler_DecalControl, float2(u, 1*sz), 0);
|
|
mtx._m20_m21_m22_m23 = SAMPLE_TEXTURE2D_LOD(_DecalDynamicData, sampler_DecalControl, float2(u, 2*sz), 0);
|
|
mtx._m30_m31_m32_m33 = SAMPLE_TEXTURE2D_LOD(_DecalDynamicData, sampler_DecalControl, float2(u, 3*sz), 0);
|
|
return mtx;
|
|
}
|
|
|
|
|
|
DecalLayer InitDecalLayer()
|
|
{
|
|
DecalLayer o = (DecalLayer)0;
|
|
o.uv = float3(0,0,-1);
|
|
o.dx = float2(0,0);
|
|
o.dy = float2(0,0);
|
|
o.dynamic = 0;
|
|
o.decalIndex = 0;
|
|
|
|
return o;
|
|
}
|
|
|
|
DecalOutput InitDecalOutput()
|
|
{
|
|
DecalOutput o = (DecalOutput)0;
|
|
o.l0 = InitDecalLayer();
|
|
o.l1 = InitDecalLayer();
|
|
o.l2 = InitDecalLayer();
|
|
o.l3 = InitDecalLayer();
|
|
|
|
o.Weights = half4(0,0,0,0);
|
|
o.Indexes = half4(0,1,2,3);
|
|
o.fxLevels = half4(0,0,0,0);
|
|
return o;
|
|
}
|
|
|
|
|
|
|
|
|
|
// we are drawn from highest to the lowest
|
|
void DecalInsert(inout DecalOutput o, DecalLayer l)
|
|
{
|
|
if (o.l0.uv.z < 0)
|
|
{
|
|
o.l0 = l;
|
|
}
|
|
else if (o.l1.uv.z < 0)
|
|
{
|
|
o.l1 = o.l0;
|
|
o.l0 = l;
|
|
}
|
|
else if (o.l2.uv.z < 0)
|
|
{
|
|
o.l2 = o.l1;
|
|
o.l1 = o.l0;
|
|
o.l0 = l;
|
|
}
|
|
else
|
|
{
|
|
o.l3 = o.l2;
|
|
o.l2 = o.l1;
|
|
o.l1 = o.l0;
|
|
o.l0 = l;
|
|
}
|
|
}
|
|
|
|
|
|
void DrawDecal(int decalIndex, inout DecalOutput o, float4 data, bool dynamic, float2 uv, float2 dx, float2 dy)
|
|
{
|
|
#if !_DECAL_NOTEXTURES || _DECAL_EMISMETAL
|
|
int texIndex = data.x - floor(data.x * 0.01);
|
|
DecalLayer l = InitDecalLayer();
|
|
l.uv = float3(uv, texIndex);
|
|
l.dx = ddx(uv); //recalculate derivative to reduce artifacts
|
|
l.dy = ddy(uv);
|
|
l.dynamic = dynamic;
|
|
l.decalIndex = decalIndex;
|
|
DecalInsert(o, l);
|
|
#endif
|
|
|
|
|
|
#if _DECAL_SPLAT
|
|
int splatTexIndex = floor(data.x * 0.01);
|
|
half4 splats = SAMPLE_TEXTURE2D_GRAD(_DecalSplats, shared_linear_clamp_sampler, float3(uv.xy, splatTexIndex), dx, dy);
|
|
|
|
float4 splatIndexes = 0;
|
|
UNITY_BRANCH
|
|
if (dynamic)
|
|
{
|
|
splatIndexes = GetDecalDynamicData(decalIndex, DECALSPLATS);
|
|
}
|
|
else
|
|
{
|
|
splatIndexes = GetDecalStaticData(decalIndex, DECALSPLATS);
|
|
}
|
|
|
|
float splatOpacity = abs(data.z) - 1;
|
|
float splatMode = data.z > 0 ? 1 : 0;
|
|
|
|
splats *= splatOpacity * 2;
|
|
UNITY_BRANCH
|
|
if (splatMode > 0.5)
|
|
{
|
|
// Another odity, splat index 0 won't register..
|
|
DoMergeDecalSplats(splats, splatIndexes, o.Weights, o.Indexes);
|
|
}
|
|
else
|
|
{
|
|
o.fxLevels = max(o.fxLevels, splats);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void CullDrawStaticDecal(int i, float3 worldPos, float3 localPos, inout DecalOutput o, float2 dx, float2 dy)
|
|
{
|
|
i = min(_STATICDECALMAX-1, i);
|
|
|
|
float3 localProj = mul(GetDecalStaticMtx(i), float4(localPos, 1)).xyz;
|
|
|
|
float2 uv = localProj.xz + 0.5;
|
|
|
|
float4 decalData1 = GetDecalStaticData(i, DECALDATA1);
|
|
|
|
float scaleY = decalData1.y;
|
|
|
|
float clipPos = (localProj.y + 0.5) - 1.0/max(scaleY, 0.001);
|
|
|
|
bool clipBounds = (uv.x == saturate(uv.x) && uv.y == saturate(uv.y) && clipPos == saturate(clipPos));
|
|
UNITY_BRANCH
|
|
if (clipBounds)
|
|
{
|
|
DrawDecal(i, o, decalData1, false, uv, dx, dy);
|
|
}
|
|
}
|
|
|
|
void CullDrawDynamicDecal(int i, float3 worldPos, float3 localPos, inout DecalOutput o)
|
|
{
|
|
float3 localProj = mul(GetDecalDynamicMtx(i), float4(localPos, 1)).xyz;
|
|
|
|
float2 uv = localProj.xz + 0.5;
|
|
float2 dx = ddx(uv);
|
|
float2 dy = ddy(uv);
|
|
float4 decalData1 = GetDecalDynamicData(i, DECALDATA1);
|
|
float scaleY = decalData1.y;
|
|
float clipPos = (localProj.y + 0.5) - 1.0/max(scaleY, 0.001);
|
|
|
|
bool clipBounds = (uv.x == saturate(uv.x) && uv.y == saturate(uv.y) && clipPos == saturate(clipPos));
|
|
UNITY_BRANCH
|
|
if (clipBounds)
|
|
{
|
|
DrawDecal(i, o, decalData1, true, uv, dx, dy);
|
|
}
|
|
}
|
|
|
|
void CullDrawDynamicDecalTess(int i, float3 worldPos, float3 localPos, inout DecalOutput o)
|
|
{
|
|
float3 localProj = mul(GetDecalDynamicMtx(i), float4(localPos, 1)).xyz;
|
|
|
|
float2 uv = localProj.xz + 0.5;
|
|
float2 dx = 0;
|
|
float2 dy = 0;
|
|
float4 decalData1 = GetDecalDynamicData(i, DECALDATA1);
|
|
float scaleY = decalData1.y;
|
|
float clipPos = (localProj.y + 0.5) - 1.0/max(scaleY, 0.001);
|
|
|
|
bool clipBounds = (uv.x == saturate(uv.x) && uv.y == saturate(uv.y) && clipPos == saturate(clipPos));
|
|
UNITY_BRANCH
|
|
if (clipBounds)
|
|
{
|
|
DrawDecal(i, o, decalData1, true, uv, dx, dy);
|
|
}
|
|
}
|
|
|
|
|
|
// Distance based culling
|
|
void RoughCullDynamicDecal(int i, float3 worldPos, float3 localPos, inout DecalOutput o)
|
|
{
|
|
float4 cullData = SAMPLE_TEXTURE2D_LOD(_DecalCullData, sampler_DecalControl, float2((i+0.5) * _DecalCullData_TexelSize.x, 0.5), 0);
|
|
float3 lv = worldPos - cullData.xyz;
|
|
float dist = lv.x * lv.x + lv.y * lv.y + lv.z * lv.z;
|
|
|
|
UNITY_BRANCH
|
|
if (dist < cullData.w)
|
|
{
|
|
CullDrawDynamicDecal(i, worldPos, localPos, o);
|
|
}
|
|
}
|
|
|
|
// Distance based culling
|
|
void RoughCullDynamicDecalTess(int i, float3 worldPos, float3 localPos, inout DecalOutput o)
|
|
{
|
|
float4 cullData = SAMPLE_TEXTURE2D_LOD(_DecalCullData, sampler_DecalControl, float2((i+0.5) * _DecalCullData_TexelSize.x, 0.5), 0);
|
|
float3 lv = worldPos - cullData.xyz;
|
|
float dist = lv.x * lv.x + lv.y * lv.y + lv.z * lv.z;
|
|
|
|
UNITY_BRANCH
|
|
if (dist < cullData.w)
|
|
{
|
|
CullDrawDynamicDecalTess(i, worldPos, localPos, o);
|
|
}
|
|
}
|
|
|
|
|
|
DecalOutput DoDecals(float2 uv, float3 worldPos, float camDist, float3 worldNormalVertex)
|
|
{
|
|
DecalOutput o = InitDecalOutput();
|
|
|
|
// Terrain matrix's lie, so in terrain mode, we just use worldPos
|
|
float3 localPos = worldPos;
|
|
|
|
#if !_DECAL_STATICMAX0
|
|
// Static
|
|
float2 cuv = uv;
|
|
|
|
half4 c0 = SAMPLE_TEXTURE2D_LOD(_DecalControl, sampler_DecalControl, uv, 0);
|
|
c0 -= 1;
|
|
|
|
|
|
// OK, I don't quite understand this, and expect it to break, but haven't so far.
|
|
// The issue is that we get derivative lines when we have overlapping decals. This is
|
|
// because the index map may report (2,1,0,0) on one pixel, and (1,0,0,0) on the next when
|
|
// one decal ends. Thus, when mip map data is shared and the indexes change, you get derivative issues.
|
|
//
|
|
// For regular UV scale blending, I just average the derivatives of all texels being used. But
|
|
// here we can't do that. So while testing, I just transformed the first decal in the list into
|
|
// decal space and used it's derivatives for all decals. But this can't possibly work right!? Right?
|
|
|
|
int initialIdx = max(c0.r, 0);
|
|
|
|
float3 localProj = mul(GetDecalStaticMtx(initialIdx), float4(localPos, 1)).xyz;
|
|
float2 xuv = localProj.xy + 0.5;
|
|
float2 dx = ddx(xuv);
|
|
float2 dy = ddy(xuv);
|
|
|
|
|
|
UNITY_BRANCH
|
|
if (c0.r >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.r, worldPos, localPos, o, dx, dy);
|
|
UNITY_BRANCH
|
|
if (c0.g >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.g, worldPos, localPos, o, dx, dy);
|
|
UNITY_BRANCH
|
|
if (c0.b >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.b, worldPos, localPos, o, dx, dy);
|
|
UNITY_BRANCH
|
|
if (c0.a >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.a, worldPos, localPos, o, dx, dy);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !_DECAL_MAX0
|
|
// dynamic
|
|
int count = _MSDecalCount;
|
|
if (count > _DECALMAX)
|
|
count = _DECALMAX;
|
|
|
|
[loop] for (int i = 0; i < count; i++)
|
|
{
|
|
RoughCullDynamicDecal(i, worldPos, localPos, o);
|
|
}
|
|
#endif //!_DECAL_MAX0
|
|
|
|
return o;
|
|
}
|
|
|
|
#if (_TESSDISTANCE || _TESSEDGE) && _DECAL_TESS
|
|
DecalOutput DoDecalsTess(float2 uv, float3 worldPos, float camDist, float3 worldNormalVertex)
|
|
{
|
|
DecalOutput o = InitDecalOutput();
|
|
|
|
// Terrain matrix's lie, so in terrain mode, we just use worldPos
|
|
float3 localPos = worldPos;
|
|
|
|
#if !_DECAL_STATICMAX0
|
|
// Static
|
|
// texture must be clamped, but we want to share samplers, so floor
|
|
float2 cuv = uv;
|
|
|
|
half4 c0 = SAMPLE_TEXTURE2D_LOD(_DecalControl, sampler_DecalControl, uv, 0);
|
|
c0 -= 1;
|
|
|
|
|
|
// OK, I don't quite understand this, and expect it to break, but haven't so far.
|
|
// The issue is that we get derivative lines when we have overlapping decals. This is
|
|
// because the index map may report (2,1,0,0) on one pixel, and (1,0,0,0) on the next when
|
|
// one decal ends. Thus, when mip map data is shared and the indexes change, you get derivative issues.
|
|
//
|
|
// For regular UV scale blending, I just average the derivatives of all texels being used. But
|
|
// here we can't do that. So while testing, I just transformed the first decal in the list into
|
|
// decal space and used it's derivatives for all decals. But this can't possibly work right!? Right?
|
|
|
|
|
|
|
|
UNITY_BRANCH
|
|
if (c0.r >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.r, worldPos, localPos, o, 0, 0);
|
|
UNITY_BRANCH
|
|
if (c0.g >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.g, worldPos, localPos, o, 0, 0);
|
|
UNITY_BRANCH
|
|
if (c0.b >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.b, worldPos, localPos, o, 0, 0);
|
|
UNITY_BRANCH
|
|
if (c0.a >= 0)
|
|
{
|
|
CullDrawStaticDecal((int)c0.a, worldPos, localPos, o, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !_DECAL_MAX0
|
|
// dynamic
|
|
int count = _MSDecalCount;
|
|
if (count > _DECALMAX)
|
|
count = _DECALMAX;
|
|
|
|
[loop] for (int i = 0; i < count; i++)
|
|
{
|
|
RoughCullDynamicDecalTess(i, worldPos, localPos, o);
|
|
}
|
|
#endif //!_DECAL_MAX0
|
|
|
|
return o;
|
|
}
|
|
#endif
|
|
|
|
// mode is encoded in sign
|
|
float BlendDecalNormal(half2 src, inout half2 dest, float opacity)
|
|
{
|
|
if (opacity < 0)
|
|
{
|
|
dest = BlendNormal2(src, dest);
|
|
}
|
|
|
|
half alpha = abs(opacity)-1;
|
|
return alpha;
|
|
}
|
|
|
|
void SampleDecalTexLayer(DecalLayer l, inout half4 albedo, inout half4 normalSAO, inout half3 surf, inout half4 emisMetal)
|
|
{
|
|
int texIndex = l.uv.z;
|
|
int decalIndex = l.decalIndex;
|
|
float4 data1;
|
|
float4 data2;
|
|
fixed3 tint = fixed3(1,1,1);
|
|
|
|
UNITY_BRANCH
|
|
if (l.dynamic)
|
|
{
|
|
data1 = GetDecalDynamicData(decalIndex, DECALDATA1);
|
|
data2 = GetDecalDynamicData(decalIndex, DECALDATA2);
|
|
#if _DECAL_TINT
|
|
tint = GetDecalDynamicData(decalIndex, DECALTINT);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
data1 = GetDecalStaticData(decalIndex, DECALDATA1);
|
|
data2 = GetDecalStaticData(decalIndex, DECALDATA2);
|
|
#if _DECAL_TINT
|
|
tint = GetDecalStaticData(decalIndex, DECALTINT);
|
|
#endif
|
|
}
|
|
|
|
float albedoOpacity = abs(data2.x) - 1;
|
|
float normalOpacity = data2.y;
|
|
float smoothnessOpacity = data2.z;
|
|
float heightBlend = data2.w;
|
|
|
|
|
|
|
|
half4 dalbedo = SAMPLE_TEXTURE2D_GRAD(_DecalAlbedo, sampler_Diffuse, l.uv, l.dx, l.dy);
|
|
COUNTSAMPLE
|
|
half4 dnsao = SAMPLE_TEXTURE2D_GRAD(_DecalNormalSAO, sampler_NormalSAO, l.uv, l.dx, l.dy).agrb;
|
|
COUNTSAMPLE
|
|
dnsao.xy *= 2;
|
|
dnsao.xy -= 1;
|
|
|
|
half alpha = dnsao.a;
|
|
|
|
#if _DECAL_TINT
|
|
dalbedo.rgb *= tint;
|
|
#endif
|
|
|
|
// reconstruct ao
|
|
dnsao.a = 1 - (dnsao.x * dnsao.y);
|
|
|
|
half hb = lerp(alpha, HeightBlend(albedo.a, dalbedo.a, alpha, _Contrast), heightBlend);
|
|
if (data2.x < 0)
|
|
{
|
|
dalbedo.rgb = BlendMult2X(albedo.rgb, dalbedo.rgb);
|
|
}
|
|
albedo = lerp(albedo, dalbedo, albedoOpacity * hb);
|
|
|
|
#if _SURFACENORMALS
|
|
half3 surfN = ConvertNormal2ToGradient(dnsao.xy);
|
|
#endif
|
|
|
|
|
|
float alpha0 = BlendDecalNormal(normalSAO.xy, dnsao.xy, normalOpacity);
|
|
normalSAO.xy = lerp(normalSAO.xy, dnsao.xy, alpha0 * hb);
|
|
normalSAO.zw = lerp(normalSAO.zw, dnsao.zw, smoothnessOpacity * hb);
|
|
|
|
#if _SURFACENORMALS
|
|
if (normalOpacity < 0)
|
|
surf += surfN * alpha0 * hb;
|
|
else
|
|
surf = lerp(surf, surfN, alpha * hb);
|
|
#endif
|
|
|
|
|
|
#if _DECAL_EMISMETAL
|
|
half4 demisMetal = SAMPLE_TEXTURE2D_GRAD(_DecalEmisMetal, sampler_Diffuse, l.uv, l.dx, l.dy);
|
|
COUNTSAMPLE
|
|
emisMetal.w = lerp(emisMetal.w, demisMetal.w, heightBlend);
|
|
emisMetal.rgb += demisMetal.rgb;
|
|
#endif
|
|
}
|
|
|
|
void DoDecalBlend(DecalOutput i, inout half4 albedo, inout half4 normalSAO, inout half3 surf, inout half4 emisMetal, float2 uv)
|
|
{
|
|
#if !_DECAL_NOTEXTURES
|
|
|
|
UNITY_BRANCH
|
|
if (i.l0.uv.z >= 0)
|
|
{
|
|
SampleDecalTexLayer(i.l0, albedo, normalSAO, surf, emisMetal);
|
|
#if _DEBUG_DECAL_STATIC
|
|
albedo.r += 0.5;
|
|
#endif
|
|
UNITY_BRANCH
|
|
if (i.l1.uv.z >= 0)
|
|
{
|
|
#if _DEBUG_DECAL_STATIC
|
|
albedo.g += 0.5;
|
|
#endif
|
|
SampleDecalTexLayer(i.l1, albedo, normalSAO, surf, emisMetal);
|
|
UNITY_BRANCH
|
|
if (i.l2.uv.z >= 0)
|
|
{
|
|
#if _DEBUG_DECAL_STATIC
|
|
albedo.b += 0.5;
|
|
#endif
|
|
SampleDecalTexLayer(i.l2, albedo, normalSAO, surf, emisMetal);
|
|
UNITY_BRANCH
|
|
if (i.l3.uv.z >= 0)
|
|
{
|
|
SampleDecalTexLayer(i.l3, albedo, normalSAO, surf, emisMetal);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
float2 cuv = uv;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
#if (_TESSDISTANCE || _TESSEDGE) && _DECAL_TESS
|
|
void SampleDecalTexLayerTess(DecalLayer l, inout half h0, inout half h1, inout half h2, inout half h3, float mipLevel)
|
|
{
|
|
int texIndex = l.uv.z;
|
|
int decalIndex = l.decalIndex;
|
|
float4 data1;
|
|
float4 data2;
|
|
|
|
if (l.dynamic)
|
|
{
|
|
data1 = GetDecalDynamicData(decalIndex, DECALDATA1);
|
|
data2 = GetDecalDynamicData(decalIndex, DECALDATA2);
|
|
}
|
|
else
|
|
{
|
|
data1 = GetDecalStaticData(decalIndex, DECALDATA1);
|
|
data2 = GetDecalStaticData(decalIndex, DECALDATA2);
|
|
}
|
|
|
|
float tessOpacity = data1.w;
|
|
float heightBlend = data2.w;
|
|
|
|
|
|
half4 dalbedo = SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalAlbedo, sampler_Diffuse, l.uv.xy, l.uv.z, mipLevel);
|
|
half4 dnsao = SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalNormalSAO, sampler_Diffuse, l.uv.xy, l.uv.z, mipLevel).agrb;
|
|
half alpha = dnsao.a;
|
|
|
|
const float dec = 1.0 / 0.95;
|
|
float alphaOp = frac(tessOpacity) * dec;
|
|
float offset = floor(tessOpacity) / 256;
|
|
|
|
half height = (dalbedo.a - 0.5 + offset);
|
|
|
|
half blend = alpha * alphaOp;
|
|
|
|
h0 = lerp(h0, HeightBlend(h0, height, heightBlend, _Contrast), blend);
|
|
h1 = lerp(h1, HeightBlend(h1, height, heightBlend, _Contrast), blend);
|
|
h2 = lerp(h2, HeightBlend(h2, height, heightBlend, _Contrast), blend);
|
|
h3 = lerp(h3, HeightBlend(h3, height, heightBlend, _Contrast), blend);
|
|
|
|
}
|
|
|
|
|
|
void DoDecalBlendTess(DecalOutput i, inout half h0, inout half h1, inout half h2, inout half h3, float mipLevel)
|
|
{
|
|
|
|
#if !_DECAL_NOTEXTURES && _DECAL_TESS
|
|
|
|
UNITY_BRANCH
|
|
if (i.l0.uv.z >= 0)
|
|
{
|
|
SampleDecalTexLayerTess(i.l0, h0, h1, h2, h3, mipLevel);
|
|
UNITY_BRANCH
|
|
if (i.l1.uv.z >= 0)
|
|
{
|
|
SampleDecalTexLayerTess(i.l1, h0, h1, h2, h3, mipLevel);
|
|
UNITY_BRANCH
|
|
if (i.l2.uv.z >= 0)
|
|
{
|
|
SampleDecalTexLayerTess(i.l2, h0, h1, h2, h3, mipLevel);
|
|
UNITY_BRANCH
|
|
if (i.l3.uv.z >= 0)
|
|
{
|
|
SampleDecalTexLayerTess(i.l3, h0, h1, h2, h3, mipLevel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|