580 lines
23 KiB
Plaintext
580 lines
23 KiB
Plaintext
|
|
TEXTURE2D(_ProcTexCurves);
|
|
TEXTURE2D(_ProcTexParams);
|
|
TEXTURE2D(_ProcTexNoise);
|
|
TEXTURE2D(_ProcTexBiomeMask);
|
|
TEXTURE2D(_ProcTexBiomeMask2);
|
|
TEXTURE2D(_CavityMap); // g = cavity, a = erosion
|
|
|
|
|
|
float ComputeMipLevel(float2 dx, float2 dy, float4 textureSize)
|
|
{
|
|
float2 dx_vtc = dx * textureSize.zw;
|
|
float2 dy_vtc = dy * textureSize.zw;
|
|
float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
|
|
return 0.5 * log2(delta_max_sqr);
|
|
}
|
|
|
|
|
|
// ONLY use LOD samplers is here, compute lod from ddx
|
|
|
|
half PCFilter(int index, float height, float slope, float cavity, float erosion, float3 worldPos, float2 uv, half4 bMask, half4 bMask2, out int texIndex, half3 pN,
|
|
float2 dx, float2 dy, float3 wdx, float3 wdy)
|
|
{
|
|
// params0 are rgba (noise scale, min, max, offset)
|
|
// params1 are rg (weight, index)
|
|
float2 noiseUV = uv;
|
|
|
|
float offset = 1.0 / 32.0;
|
|
float halfOff = 1.0 / 64.0;
|
|
float y = (index * offset) + halfOff;
|
|
|
|
half h0 = SAMPLE_TEXTURE2D_LOD(_ProcTexCurves, shared_linear_clamp_sampler, float2(height, y), 0).r;
|
|
half s0 = SAMPLE_TEXTURE2D_LOD(_ProcTexCurves, shared_linear_clamp_sampler, float2(slope, y), 0).g;
|
|
half c0 = 1;
|
|
half e0 = 1;
|
|
#if _PCCAVITY || _PCUSECOMBINEDAO
|
|
c0 = SAMPLE_TEXTURE2D_LOD(_ProcTexCurves, shared_linear_clamp_sampler, float2(cavity, y), 0).b;
|
|
#endif
|
|
#if _PCFLOW
|
|
e0 = SAMPLE_TEXTURE2D_LOD(_ProcTexCurves, shared_linear_clamp_sampler, float2(erosion, y), 0).a;
|
|
#endif
|
|
|
|
// 4 texels, so 1/4 spacing + 1/2 spacing in X
|
|
half4 params0 = SAMPLE_TEXTURE2D_LOD(_ProcTexParams, shared_linear_clamp_sampler, float2(0.125, y), 0);
|
|
half4 params1 = SAMPLE_TEXTURE2D_LOD(_ProcTexParams, shared_linear_clamp_sampler, float2(0.375, y), 0);
|
|
half4 params2 = half4(1,1,1,1);
|
|
half4 params3 = half4(1,1,1,1);
|
|
#if _PCBIOMEMASK || _PCBIOMEMASK16
|
|
params2 = SAMPLE_TEXTURE2D_LOD(_ProcTexParams, shared_linear_clamp_sampler, float2(0.625, y), 0);
|
|
bMask = smoothstep(0.5 - _ProcBiomeCurveWeight, 0.5 + _ProcBiomeCurveWeight, bMask);
|
|
#endif
|
|
#if _PCBIOMEMASK2
|
|
params3 = SAMPLE_TEXTURE2D_LOD(_ProcTexParams, shared_linear_clamp_sampler, float2(0.875, y), 0);
|
|
bMask2 = smoothstep(0.5 - _ProcBiomeCurveWeight, 0.5 + _ProcBiomeCurveWeight, bMask2);
|
|
#endif
|
|
|
|
|
|
|
|
half4 noise = 0;
|
|
UNITY_BRANCH
|
|
if (abs(params0.y - params0.z) > 0)
|
|
{
|
|
#if _PCNOISEPROCEDURAL
|
|
noise = FBM3D(worldPos * 0.002 * params0.r + params0.a);
|
|
#else
|
|
// WOW, this is odd. So if we do triplanar or world space, the actual UVs which are set on the config.uv end up 0
|
|
// However, if we use those UVs to sample a texture and then multiply the saturate(result+1) (which is basically always 1)
|
|
// into the noise it works around the bug- which must be something in the compiler.
|
|
float lod = ComputeMipLevel(dx * params0.r, dy * params0.r, _ProcTexNoise_TexelSize);
|
|
noise = SAMPLE_TEXTURE2D_LOD(_ProcTexNoise, sampler_Diffuse, float2(noiseUV * params0.r + params0.a), lod);
|
|
#if _PCNOISETRIPLANAR
|
|
float lod0 = ComputeMipLevel(wdx.zy * 0.002 * params0.r, wdy.zy * 0.002 * params0.r, _ProcTexNoise_TexelSize);
|
|
float lod1 = ComputeMipLevel(wdx.xz * 0.002 * params0.r, wdy.xz * 0.002 * params0.r, _ProcTexNoise_TexelSize);
|
|
float lod2 = ComputeMipLevel(wdx.xy * 0.002 * params0.r, wdy.xy * 0.002 * params0.r, _ProcTexNoise_TexelSize);
|
|
half4 noise0 = SAMPLE_TEXTURE2D_LOD(_ProcTexNoise, sampler_Diffuse, float2(worldPos.zy * 0.002 * params0.r + params0.a), lod0);
|
|
half4 noise1 = SAMPLE_TEXTURE2D_LOD(_ProcTexNoise, sampler_Diffuse, float2(worldPos.xz * 0.002 * params0.r + params0.a + 0.31), lod1);
|
|
half4 noise2 = SAMPLE_TEXTURE2D_LOD(_ProcTexNoise, sampler_Diffuse, float2(worldPos.xy * 0.002 * params0.r + params0.a + 0.71), lod2);
|
|
noise = saturate(noise + 1) * noise0 * pN.x + noise1 * pN.y + noise2 * pN.z;
|
|
#elif !_PCNOISEUV
|
|
float2 pcNoiseUV = float2(worldPos.xz * 0.002 * params0.r + params0.a);
|
|
float lodX = ComputeMipLevel(wdx.xz * 0.002 * params0.r, wdy.xz * 0.002 * params0.r, _ProcTexNoise_TexelSize);
|
|
noise = saturate(SAMPLE_TEXTURE2D_LOD(_ProcTexNoise, sampler_Diffuse, pcNoiseUV, lodX));
|
|
#endif
|
|
noise = noise * 2 - 1;
|
|
#endif // !_PCNOISEPROCEDURAL
|
|
|
|
|
|
|
|
h0 *= 1.0 + lerp(params0.y, params0.z, noise.r);
|
|
s0 *= 1.0 + lerp(params0.y, params0.z, noise.g);
|
|
c0 *= 1.0 + lerp(params0.y, params0.z, noise.b);
|
|
e0 *= 1.0 + lerp(params0.y, params0.z, noise.a);
|
|
}
|
|
|
|
half bWeight = 1;
|
|
half bWeight2 = 0;
|
|
#if _PCBIOMEMASK
|
|
bMask *= params2;
|
|
bWeight = max(max(max(bMask.x, bMask.y), bMask.z), bMask.w);
|
|
#elif _PCBIOMEMASK16
|
|
bMask.x = 1 - abs(bMask.x - params2.x);
|
|
bMask.y = 1 - abs(bMask.y - params2.y);
|
|
bMask.z = 1 - abs(bMask.z - params2.z);
|
|
bMask.w = 1 - abs(bMask.w - params2.w);
|
|
bWeight = bMask.x * bMask.y * bMask.z * bMask.w;
|
|
#endif
|
|
#if _PCBIOMEMASK2
|
|
bMask2 *= params3;
|
|
bWeight2 = max(max(max(bMask2.x, bMask2.y), bMask2.z), bMask2.w);
|
|
#endif
|
|
|
|
|
|
texIndex = params1.g;
|
|
return saturate(h0 * s0 * c0 * e0 * params1.x * saturate(bWeight + bWeight2));
|
|
}
|
|
|
|
void PCProcessLayer(inout half4 weights, inout int4 indexes, inout float totalWeight, int curIdx,
|
|
float height, float slope, float cavity, float erosion, float3 worldPos, float2 uv, half4 biomeMask, half4 biomeMask2, half3 pN,
|
|
float2 dx, float2 dy, float3 wdx, float3 wdy)
|
|
{
|
|
|
|
int texIndex = 0;
|
|
half w = PCFilter(curIdx, height, slope, cavity, erosion, worldPos, uv, biomeMask, biomeMask2, texIndex, pN, dx, dy, wdx, wdy);
|
|
w = min(totalWeight, w);
|
|
totalWeight -= w;
|
|
|
|
// sort
|
|
if (w > weights.x)
|
|
{
|
|
weights.w = weights.z;
|
|
weights.z = weights.y;
|
|
weights.y = weights.x;
|
|
indexes.w = indexes.z;
|
|
indexes.z = indexes.y;
|
|
indexes.y = indexes.x;
|
|
weights.x = w;
|
|
indexes.x = texIndex;
|
|
}
|
|
else if (w > weights.y)
|
|
{
|
|
weights.w = weights.z;
|
|
weights.z = weights.y;
|
|
indexes.w = indexes.z;
|
|
indexes.z = indexes.y;
|
|
weights.y = w;
|
|
indexes.y = texIndex;
|
|
}
|
|
else if (w > weights.z)
|
|
{
|
|
weights.w = weights.z;
|
|
indexes.w = indexes.z;
|
|
weights.z = w;
|
|
indexes.z = texIndex;
|
|
}
|
|
else if (w > weights.w)
|
|
{
|
|
weights.w = w;
|
|
indexes.w = texIndex;
|
|
}
|
|
}
|
|
|
|
void ProceduralSetup(Input i, float3 worldPos, float worldHeight, float3 worldNormal, float3 up, inout half4 weights, float2 uv, inout Config config,
|
|
float2 dx, float2 dy, float3 wdx, float3 wdy, DecalOutput decalOutput)
|
|
{
|
|
#if _PROCEDURALBLENDSPLATS
|
|
|
|
#if !_PCPRESERVEINDEXES
|
|
// true = 1, so any index being used will work.
|
|
float brch = (config.uv0.z == _PCShowProceduralIndex) + (config.uv1.z == _PCShowProceduralIndex) + (config.uv2.z == _PCShowProceduralIndex) + (config.uv3.z == _PCShowProceduralIndex);
|
|
UNITY_BRANCH
|
|
if (brch == 0)
|
|
{
|
|
return; // early exit on places where there is no procedural texturing
|
|
}
|
|
#endif
|
|
|
|
|
|
Config origConfig = config;
|
|
half4 origWeights = weights;
|
|
half4 origIndexes = half4(config.uv0.z, config.uv1.z, config.uv2.z, config.uv3.z);
|
|
#endif
|
|
|
|
weights = 0;
|
|
|
|
|
|
#if defined(SHADER_STAGE_VERTEX) && (_TESSDISTANCE || _TESSEDGE)
|
|
#if _PCUSECOMBINEDHEIGHT || _PCUSECOMBINEDAO
|
|
#if _MESHCOMBINEDPACKEDMAP
|
|
half4 packedMap = SAMPLE_TEXTURE2D_LOD(_StandardPackedMap, sampler_StandardDiffuse, uv, 0);
|
|
#else
|
|
half4 packedMap = half4(0,0,0,0);
|
|
packedMap.b = SAMPLE_TEXTURE2D_LOD(_StandardHeight, sampler_StandardDiffuse, uv, _TessData1.b).g;
|
|
packedMap.a = SAMPLE_TEXTURE2D_LOD(_StandardOcclusion, sampler_StandardDiffuse, uv, _TessData1.b).g;
|
|
#endif
|
|
#endif
|
|
|
|
// height
|
|
#if _PCUSECOMBINEDHEIGHT
|
|
worldHeight = packedMap.b;
|
|
float height = worldHeight;
|
|
#else
|
|
float height = saturate((worldHeight - _WorldHeightRange.x) / max(0.1, (_WorldHeightRange.y - _WorldHeightRange.x)));
|
|
#endif
|
|
|
|
// slope
|
|
#if _PCUSECOMBINEDNORMAL
|
|
half3 tangentNormal = UnpackNormal(SAMPLE_TEXTURE2D_LOD(_StandardNormal, sampler_StandardDiffuse, uv, 0));
|
|
worldNormal = WorldNormalVector(i, tangentNormal);
|
|
#endif
|
|
|
|
float slope = 1.0 - saturate(dot(worldNormal, up) * 0.5 + 0.49);
|
|
|
|
// cavity and erosion
|
|
float cavity = 0.5;
|
|
float erosion = 0.5;
|
|
#if _PCFLOW || (_PCCAVITY && !_PCUSECOMBINEDAO)
|
|
half4 cavityData = SAMPLE_TEXTURE2D_LOD(_CavityMap, sampler_Diffuse, uv, _TessData1.b);
|
|
cavity = cavityData.g;
|
|
erosion = cavityData.a;
|
|
#endif
|
|
half4 biomeMask = half4(1,1,1,1);
|
|
half4 biomeMask2 = half4(1,1,1,1);
|
|
#if _PCBIOMEMASK || _PCBIOMEMASK16
|
|
biomeMask = SAMPLE_TEXTURE2D_LOD(_ProcTexBiomeMask, shared_linear_clamp_sampler, uv, 0);
|
|
#endif
|
|
#if _PCBIOMEMASK2
|
|
biomeMask2 = SAMPLE_TEXTURE2D_LOD(_ProcTexBiomeMask2, shared_linear_clamp_sampler, uv, 0);
|
|
#endif
|
|
#else // not vertex
|
|
#if _PCUSECOMBINEDHEIGHT || _PCUSECOMBINEDAO
|
|
#if _MESHCOMBINEDPACKEDMAP
|
|
half4 packedMap = SAMPLE_TEXTURE2D_GRAD(_StandardPackedMap, sampler_StandardDiffuse, uv, dx, dy);
|
|
#else
|
|
half4 packedMap = half4(0,0,0,0);
|
|
packedMap.b = SAMPLE_TEXTURE2D_GRAD(_StandardHeight, sampler_StandardDiffuse, uv, dx, dy).g;
|
|
packedMap.a = SAMPLE_TEXTURE2D_GRAD(_StandardOcclusion, sampler_StandardDiffuse, uv, dx, dy).g;
|
|
#endif
|
|
#endif
|
|
|
|
// height
|
|
#if _PCUSECOMBINEDHEIGHT
|
|
worldHeight = packedMap.b;
|
|
float height = worldHeight;
|
|
#else
|
|
float height = saturate((worldHeight - _WorldHeightRange.x) / max(0.1, (_WorldHeightRange.y - _WorldHeightRange.x)));
|
|
#endif
|
|
|
|
// slope
|
|
#if _PCUSECOMBINEDNORMAL
|
|
half3 tangentNormal = UnpackNormal(SAMPLE_TEXTURE2D_GRAD(_StandardNormal, sampler_StandardDiffuse, uv, dx, dy));
|
|
worldNormal = WorldNormalVector(i, tangentNormal);
|
|
#endif
|
|
|
|
float slope = 1.0 - saturate(dot(worldNormal, up) * 0.5 + 0.49);
|
|
|
|
// cavity and erosion
|
|
float cavity = 0.5;
|
|
float erosion = 0.5;
|
|
#if _PCFLOW || (_PCCAVITY && !_PCUSECOMBINEDAO)
|
|
half4 cavityData = SAMPLE_TEXTURE2D_GRAD(_CavityMap, shared_linear_clamp_sampler, uv, dx, dy);
|
|
cavity = cavityData.g;
|
|
erosion = cavityData.a;
|
|
#endif
|
|
half4 biomeMask = half4(1,1,1,1);
|
|
half4 biomeMask2 = half4(1,1,1,1);
|
|
#if _PCBIOMEMASK || _PCBIOMEMASK16
|
|
biomeMask = SAMPLE_TEXTURE2D_GRAD(_ProcTexBiomeMask, shared_linear_clamp_sampler, uv, dx, dy);
|
|
#endif
|
|
#if _PCBIOMEMASK2
|
|
biomeMask2 = SAMPLE_TEXTURE2D_GRAD(_ProcTexBiomeMask2, shared_linear_clamp_sampler, uv, dx, dy);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if _PCUSECOMBINEDAO
|
|
cavity = packedMap.a * packedMap.a * packedMap.a;
|
|
#endif
|
|
|
|
// find 4 highest weights and indexes
|
|
int4 indexes = int4(0, 1, 2, 3);
|
|
float totalWeight = 1.0;
|
|
|
|
|
|
|
|
half3 pN = 0;
|
|
#if _PCNOISETRIPLANAR
|
|
pN = pow(abs(worldNormal), 4);
|
|
pN = pN / (pN.x + pN.y + pN.z);
|
|
#endif
|
|
int j = 0;
|
|
for (j = 0; j < _PCLayerCount; ++j)
|
|
{
|
|
COUNTPROCLAYER
|
|
PCProcessLayer(weights, indexes, totalWeight, j, height, slope, cavity, erosion, worldPos, uv, biomeMask, biomeMask2, pN, dx, dy, wdx, wdy);
|
|
UNITY_BRANCH
|
|
if (totalWeight <= 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if _MAX2LAYER
|
|
weights.zw = 0;
|
|
weights.xy *= (1.0 / (weights.x + weights.y));
|
|
#elif _MAX3LAYER
|
|
weights.w = 0;
|
|
weights.xyz *= (1.0 / (weights.x + weights.y + weights.z));
|
|
#else
|
|
weights *= (1.0 / (weights.x + weights.y + weights.z + weights.w));
|
|
#endif
|
|
|
|
// when blending is enabled, we need to resort the weights/indexes between a list of 8
|
|
#if _PROCEDURALBLENDSPLATS
|
|
#if _PCPRESERVEINDEXES
|
|
if (origIndexes.x == _PCPreserveIndexes.x ||
|
|
origIndexes.x == _PCPreserveIndexes.y ||
|
|
origIndexes.x == _PCPreserveIndexes.z ||
|
|
origIndexes.x == _PCPreserveIndexes.w)
|
|
{
|
|
weights *= 1.0 - origWeights.x;
|
|
}
|
|
else
|
|
{
|
|
origWeights.x = 0;
|
|
}
|
|
if (origIndexes.y == _PCPreserveIndexes.x ||
|
|
origIndexes.y == _PCPreserveIndexes.y ||
|
|
origIndexes.y == _PCPreserveIndexes.z ||
|
|
origIndexes.y == _PCPreserveIndexes.w)
|
|
{
|
|
weights *= 1.0 - origWeights.y;
|
|
}
|
|
else
|
|
{
|
|
origWeights.y = 0;
|
|
}
|
|
if (origIndexes.z == _PCPreserveIndexes.x ||
|
|
origIndexes.z == _PCPreserveIndexes.y ||
|
|
origIndexes.z == _PCPreserveIndexes.z ||
|
|
origIndexes.z == _PCPreserveIndexes.w)
|
|
{
|
|
weights *= 1.0 - origWeights.z;
|
|
}
|
|
else
|
|
{
|
|
origWeights.z = 0;
|
|
}
|
|
if (origIndexes.w == _PCPreserveIndexes.x ||
|
|
origIndexes.w == _PCPreserveIndexes.y ||
|
|
origIndexes.w == _PCPreserveIndexes.z ||
|
|
origIndexes.w == _PCPreserveIndexes.w)
|
|
{
|
|
weights *= 1.0 - origWeights.w;
|
|
}
|
|
else
|
|
{
|
|
origWeights.w = 0;
|
|
}
|
|
#else
|
|
// first, adjust procedural weights by splat weights
|
|
if (origIndexes.x == _PCShowProceduralIndex)
|
|
{
|
|
weights *= origWeights.x;
|
|
origWeights *= 1 - origWeights.x;
|
|
origWeights.x = 0;
|
|
}
|
|
else if (origIndexes.y == _PCShowProceduralIndex)
|
|
{
|
|
weights *= origWeights.y;
|
|
origWeights *= 1 - origWeights.y;
|
|
origWeights.y = 0;
|
|
}
|
|
else if (origIndexes.z == _PCShowProceduralIndex)
|
|
{
|
|
weights *= origWeights.z;
|
|
origWeights *= 1 - origWeights.z;
|
|
origWeights.z = 0;
|
|
|
|
}
|
|
else if (origIndexes.w == _PCShowProceduralIndex)
|
|
{
|
|
weights *= origWeights.w;
|
|
origWeights *= 1 - origWeights.w;
|
|
origWeights.w = 0;
|
|
}
|
|
#endif
|
|
// now merge and resort
|
|
fixed splats[8];
|
|
fixed totalIndexes[8];
|
|
splats[0] = origWeights.x;
|
|
splats[1] = origWeights.y;
|
|
splats[2] = origWeights.z;
|
|
splats[3] = origWeights.w;
|
|
splats[4] = weights.x;
|
|
splats[5] = weights.y;
|
|
splats[6] = weights.z;
|
|
splats[7] = weights.w;
|
|
|
|
totalIndexes[0] = origIndexes.x;
|
|
totalIndexes[1] = origIndexes.y;
|
|
totalIndexes[2] = origIndexes.z;
|
|
totalIndexes[3] = origIndexes.w;
|
|
totalIndexes[4] = indexes.x;
|
|
totalIndexes[5] = indexes.y;
|
|
totalIndexes[6] = indexes.z;
|
|
totalIndexes[7] = indexes.w;
|
|
|
|
half4 mergeIndexes = 0;
|
|
half4 mergeWeights = 0;
|
|
|
|
j = 0;
|
|
for (j = 0; j < 8; ++j)
|
|
{
|
|
fixed w = splats[j];
|
|
if (w >= mergeWeights[0])
|
|
{
|
|
mergeWeights[3] = mergeWeights[2];
|
|
mergeIndexes[3] = mergeIndexes[2];
|
|
mergeWeights[2] = mergeWeights[1];
|
|
mergeIndexes[2] = mergeIndexes[1];
|
|
mergeWeights[1] = mergeWeights[0];
|
|
mergeIndexes[1] = mergeIndexes[0];
|
|
mergeWeights[0] = w;
|
|
mergeIndexes[0] = totalIndexes[j];
|
|
}
|
|
else if (w >= mergeWeights[1])
|
|
{
|
|
mergeWeights[3] = mergeWeights[2];
|
|
mergeIndexes[3] = mergeIndexes[2];
|
|
mergeWeights[2] = mergeWeights[1];
|
|
mergeIndexes[2] = mergeIndexes[1];
|
|
mergeWeights[1] = w;
|
|
mergeIndexes[1] = totalIndexes[j];
|
|
}
|
|
else if (w >= mergeWeights[2])
|
|
{
|
|
mergeWeights[3] = mergeWeights[2];
|
|
mergeIndexes[3] = mergeIndexes[2];
|
|
mergeWeights[2] = w;
|
|
mergeIndexes[2] = totalIndexes[j];
|
|
}
|
|
else if (w >= mergeWeights[3])
|
|
{
|
|
mergeWeights[3] = w;
|
|
mergeIndexes[3] = totalIndexes[j];
|
|
}
|
|
}
|
|
|
|
// clamp and renormalize
|
|
#if _MAX2LAYER
|
|
mergeWeights.zw = 0;
|
|
mergeWeights.xy = TotalOne(mergeWeights.xy);
|
|
#elif _MAX3LAYER
|
|
mergeWeights.w = 0;
|
|
mergeWeights.xyz = TotalOne(mergeWeights.xyz);
|
|
#else
|
|
mergeWeights = TotalOne(mergeWeights);
|
|
#endif
|
|
|
|
weights = mergeWeights;
|
|
indexes = mergeIndexes;
|
|
#endif
|
|
|
|
#if _DECAL_SPLAT
|
|
DoMergeDecalSplats(decalOutput.Weights, decalOutput.Indexes, weights, indexes);
|
|
#endif
|
|
|
|
#if !_PROCEDURALBLENDSPLATS
|
|
#if _WORLDUV
|
|
uv = worldPos.xz;
|
|
#endif
|
|
float2 scaledUV = uv * _UVScale.xy + _UVScale.zw;
|
|
config.uv0 = float3(scaledUV, indexes.x);
|
|
config.uv1 = float3(scaledUV, indexes.y);
|
|
config.uv2 = float3(scaledUV, indexes.z);
|
|
config.uv3 = float3(scaledUV, indexes.w);
|
|
#else
|
|
config.uv0.z = indexes.x;
|
|
config.uv1.z = indexes.y;
|
|
config.uv2.z = indexes.z;
|
|
config.uv3.z = indexes.w;
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void PCUnpackWeight(int index, int splatIndex, half weight, inout half4 o)
|
|
{
|
|
if (index == splatIndex*4)
|
|
{
|
|
o.x += weight;
|
|
}
|
|
else if (index == splatIndex*4+1)
|
|
{
|
|
o.y += weight;
|
|
}
|
|
else if (index == splatIndex*4+2)
|
|
{
|
|
o.z += weight;
|
|
}
|
|
else if (index == splatIndex*4+3)
|
|
{
|
|
o.w += weight;
|
|
}
|
|
}
|
|
|
|
void DebugPCSplatOutput(inout MicroSplatLayer l, half4 weights, int4 indexes, int splatIndex)
|
|
{
|
|
l.Normal = half3(0,0,1);
|
|
l.Occlusion = 1;
|
|
l.Smoothness = 0;
|
|
l.Emission = 0;
|
|
// indexes (2, 1, 0, 3)
|
|
// weights (0.8, 0.2, 0, 0)
|
|
// result (0, .2, 0.8, 0)
|
|
|
|
half4 o = 0;
|
|
PCUnpackWeight(indexes.x, splatIndex, weights.x, o);
|
|
PCUnpackWeight(indexes.y, splatIndex, weights.y, o);
|
|
PCUnpackWeight(indexes.z, splatIndex, weights.z, o);
|
|
PCUnpackWeight(indexes.w, splatIndex, weights.w, o);
|
|
|
|
l.Albedo = o.xyz;
|
|
l.Alpha = o.w;
|
|
|
|
// this has to be in here or the windows compiler will throw errors
|
|
// it will strip the texture, but not the sampler for _Diffuse, and not compile.
|
|
// On OSX in OpenGL or metal this is all fine.
|
|
l.Albedo *= saturate(SAMPLE_TEXTURE2D_ARRAY_LOD(_Diffuse, sampler_Diffuse, float2(0,0), 0, 11).r + 2);
|
|
l.Alpha *= saturate(SAMPLE_TEXTURE2D_ARRAY_LOD(_Diffuse, sampler_Diffuse, float2(0,0), 0, 11).r + 2);
|
|
l.Albedo *= saturate(SAMPLE_TEXTURE2D_ARRAY_LOD(_NormalSAO, sampler_NormalSAO, float2(0,0), 0, 11).r + 2);
|
|
l.Alpha *= saturate(SAMPLE_TEXTURE2D_ARRAY_LOD(_NormalSAO, sampler_NormalSAO, float2(0,0), 0, 11).r + 2);
|
|
}
|
|
|
|
void ProceduralTextureDebugOutput(inout MicroSplatLayer l, half4 weights, Config config)
|
|
{
|
|
int4 outIndexes = int4(config.uv0.z, config.uv1.z, config.uv2.z, config.uv3.z);
|
|
#if _DEBUG_OUTPUT_SPLAT0
|
|
DebugPCSplatOutput(l, weights, outIndexes, 0);
|
|
#elif _DEBUG_OUTPUT_SPLAT1
|
|
DebugPCSplatOutput(l, weights, outIndexes, 1);
|
|
#elif _DEBUG_OUTPUT_SPLAT2
|
|
DebugPCSplatOutput(l, weights, outIndexes, 2);
|
|
#elif _DEBUG_OUTPUT_SPLAT3
|
|
DebugPCSplatOutput(l, weights, outIndexes, 3);
|
|
#elif _DEBUG_OUTPUT_SPLAT4
|
|
DebugPCSplatOutput(l, weights, outIndexes, 4);
|
|
#elif _DEBUG_OUTPUT_SPLAT5
|
|
DebugPCSplatOutput(l, weights, outIndexes, 5);
|
|
#elif _DEBUG_OUTPUT_SPLAT6
|
|
DebugPCSplatOutput(l, weights, outIndexes, 6);
|
|
#elif _DEBUG_OUTPUT_SPLAT7
|
|
DebugPCSplatOutput(l, weights, outIndexes, 7);
|
|
#elif _DEBUG_OUTPUT_SPLAT0A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 0);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT1A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 1);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT2A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 2);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT3A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 3);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT4A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 4);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT5A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 5);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT6A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 6);
|
|
l.Albedo = l.Alpha;
|
|
#elif _DEBUG_OUTPUT_SPLAT7A
|
|
DebugPCSplatOutput(l, weights, outIndexes, 7);
|
|
l.Albedo = l.Alpha;
|
|
#endif
|
|
}
|
|
|