新插件
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1a5efd994efb484f84fba5fb64d14f2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35264053cc3c943709456784a9744965
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,648 @@
|
||||
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61f35886a28b64a9eaf8535303f0c79d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
_DecalAlbedo("Decal Albedo", 2DArray) = "white" {}
|
||||
_DecalNormalSAO("Decal Normal SAO", 2DArray) = "bump" {}
|
||||
_DecalSplats("Decal Splats", 2DArray) = "red" {}
|
||||
_DecalControl("Decal Control", 2D) = "black" {}
|
||||
_DecalStaticData("Decal Static Data", 2D) = "black" {}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c54dd670b2904cd68df91f91229e8d3
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:90ab0119788ed4ec6b8fe54dd44f01fa"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cae0fd65af842486e9c5ed21cf82d1d3
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,223 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using JBooth.MicroSplat;
|
||||
|
||||
[CustomEditor (typeof (MicroSplatDecal))]
|
||||
public class MicroSplatDecalEditor : Editor
|
||||
{
|
||||
static GUIContent CDynamic = new GUIContent ("Render Mode", "Static decals are fast to render, but slow to move. Dynamic decals are slow to render, but fast to move");
|
||||
static GUIContent CReceiver = new GUIContent ("Receiver", "Object which decal is applied to");
|
||||
|
||||
static bool firstInit = true;
|
||||
|
||||
enum DrawMode
|
||||
{
|
||||
Static,
|
||||
Dynamic
|
||||
}
|
||||
|
||||
Bounds OnGetFrameBounds ()
|
||||
{
|
||||
MicroSplatDecal d = (MicroSplatDecal)target;
|
||||
Bounds bounds = new Bounds (d.transform.position, d.transform.lossyScale * 0.75f);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
bool HasFrameBounds ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI ()
|
||||
{
|
||||
if (firstInit)
|
||||
{
|
||||
firstInit = false;
|
||||
MicroSplatDecal.gizmoMode = (MicroSplatDecal.GizmoMode)EditorPrefs.GetInt ("MicroSplatDecal_GizmoMode", (int)MicroSplatDecal.gizmoMode);
|
||||
MicroSplatDecal.staticGizmoColor.r = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmocolor-r", MicroSplatDecal.staticGizmoColor.r);
|
||||
MicroSplatDecal.staticGizmoColor.g = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmocolor-g", MicroSplatDecal.staticGizmoColor.g);
|
||||
MicroSplatDecal.staticGizmoColor.b = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmocolor-b", MicroSplatDecal.staticGizmoColor.b);
|
||||
MicroSplatDecal.staticGizmoColor.a = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmocolor-a", MicroSplatDecal.staticGizmoColor.a);
|
||||
MicroSplatDecal.staticGizmoSelectedColor.r = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmoselectedcolor-r", MicroSplatDecal.staticGizmoSelectedColor.r);
|
||||
MicroSplatDecal.staticGizmoSelectedColor.g = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmoselectedcolor-g", MicroSplatDecal.staticGizmoSelectedColor.g);
|
||||
MicroSplatDecal.staticGizmoSelectedColor.b = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmoselectedcolor-b", MicroSplatDecal.staticGizmoSelectedColor.b);
|
||||
MicroSplatDecal.staticGizmoSelectedColor.a = EditorPrefs.GetFloat ("MicroSplatDecal_staticgizmoselectedcolor-a", MicroSplatDecal.staticGizmoSelectedColor.a);
|
||||
MicroSplatDecal.dynamicGizmoColor.r = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmocolor-r", MicroSplatDecal.dynamicGizmoColor.r);
|
||||
MicroSplatDecal.dynamicGizmoColor.g = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmocolor-g", MicroSplatDecal.dynamicGizmoColor.g);
|
||||
MicroSplatDecal.dynamicGizmoColor.b = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmocolor-b", MicroSplatDecal.dynamicGizmoColor.b);
|
||||
MicroSplatDecal.dynamicGizmoColor.a = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmocolor-a", MicroSplatDecal.dynamicGizmoColor.a);
|
||||
MicroSplatDecal.dynamicGizmoSelectedColor.r = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmoselectedcolor-r", MicroSplatDecal.dynamicGizmoSelectedColor.r);
|
||||
MicroSplatDecal.dynamicGizmoSelectedColor.g = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmoselectedcolor-g", MicroSplatDecal.dynamicGizmoSelectedColor.g);
|
||||
MicroSplatDecal.dynamicGizmoSelectedColor.b = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmoselectedcolor-b", MicroSplatDecal.dynamicGizmoSelectedColor.b);
|
||||
MicroSplatDecal.dynamicGizmoSelectedColor.a = EditorPrefs.GetFloat ("MicroSplatDecal_dynamicgizmocselectedolor-a", MicroSplatDecal.dynamicGizmoSelectedColor.a);
|
||||
}
|
||||
EditorGUI.BeginChangeCheck ();
|
||||
MicroSplatDecal d = (MicroSplatDecal)target;
|
||||
|
||||
d.targetObject = EditorGUILayout.ObjectField(CReceiver, d.targetObject, typeof(MicroSplatDecalReceiver), true) as MicroSplatDecalReceiver;
|
||||
if (d.targetObject == null || d.targetObject.msObj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var msObj = d.targetObject.msObj;
|
||||
if (msObj.matInstance != null && msObj.matInstance.HasProperty ("_DecalAlbedo"))
|
||||
{
|
||||
Texture2DArray ta = null;
|
||||
if (!msObj.keywordSO.IsKeywordEnabled ("_DECAL_NOTEXTURES"))
|
||||
{
|
||||
ta = (Texture2DArray)msObj.matInstance.GetTexture ("_DecalAlbedo");
|
||||
if (ta != null)
|
||||
{
|
||||
d.textureIndex = JBooth.MicroSplat.MicroSplatUtilities.DrawTextureSelector (d.textureIndex, ta);
|
||||
}
|
||||
}
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.dynamic = DrawMode.Dynamic == (DrawMode)EditorGUILayout.EnumPopup (CDynamic, d.dynamic == true ? DrawMode.Dynamic : DrawMode.Static);
|
||||
}
|
||||
|
||||
if (!msObj.keywordSO.IsKeywordEnabled ("_DECAL_NOTEXTURES"))
|
||||
{
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.albedoBlend = (MicroSplatDecal.AlbedoBlend)EditorGUILayout.EnumPopup ("Albedo Blend Mode", d.albedoBlend);
|
||||
d.albedoOpacity = EditorGUILayout.Slider ("Albedo Opacity", d.albedoOpacity, 0, 1);
|
||||
if (msObj.keywordSO.IsKeywordEnabled ("_DECAL_TINT"))
|
||||
{
|
||||
d.tint = EditorGUILayout.ColorField ("Tint", d.tint);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.heightBlend = EditorGUILayout.Slider ("Height Blend", d.heightBlend, 0, 1);
|
||||
}
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.normalBlend = (MicroSplatDecal.NormalBlend)EditorGUILayout.EnumPopup ("Normal Blend Mode", d.normalBlend);
|
||||
d.normalOpacity = EditorGUILayout.Slider ("Normal Opacity", d.normalOpacity, 0, 1);
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.smoothnessOpacity = EditorGUILayout.Slider ("Smoothness/AO Opacity", d.smoothnessOpacity, 0, 1);
|
||||
}
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
if (msObj.keywordSO.IsKeywordEnabled ("_DECAL_TESS") && msObj.keywordSO.IsKeywordEnabled ("_TESSDISTANCE"))
|
||||
{
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.tessOpacity = EditorGUILayout.Slider ("Displacement Opacity", d.tessOpacity, 0, 1);
|
||||
d.tessOffset = EditorGUILayout.Slider ("Displacement Offset", d.tessOffset, -1, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (msObj.keywordSO.IsKeywordEnabled ("_DECAL_SPLAT"))
|
||||
{
|
||||
bool on = d.splatOpacity >= 0.01f;
|
||||
bool newOn = EditorGUILayout.Toggle ("Effect Splat Maps", on);
|
||||
if (newOn != on)
|
||||
{
|
||||
d.splatOpacity = newOn == false ? 0 : 0.5f;
|
||||
}
|
||||
if (newOn)
|
||||
{
|
||||
Texture2DArray splatsArray = (Texture2DArray)msObj.templateMaterial.GetTexture ("_DecalSplats");
|
||||
if (splatsArray != null)
|
||||
{
|
||||
d.splatTextureIndex = JBooth.MicroSplat.MicroSplatUtilities.DrawTextureSelector (d.splatTextureIndex, splatsArray);
|
||||
d.splatOpacity = EditorGUILayout.Slider ("Splat Opacity", d.splatOpacity * 2, 0.01f, 2) * 0.5f;
|
||||
d.splatMode = (MicroSplatDecal.SplatMode)EditorGUILayout.EnumPopup ("SplatMode", d.splatMode);
|
||||
|
||||
if (d.splatMode == MicroSplatDecal.SplatMode.SplatMap)
|
||||
{
|
||||
ta = msObj.templateMaterial.GetTexture ("_Diffuse") as Texture2DArray;
|
||||
d.splatIndexes.x = JBooth.MicroSplat.MicroSplatUtilities.DrawTextureSelector ((int)d.splatIndexes.x, ta, true);
|
||||
d.splatIndexes.y = JBooth.MicroSplat.MicroSplatUtilities.DrawTextureSelector ((int)d.splatIndexes.y, ta, true);
|
||||
d.splatIndexes.z = JBooth.MicroSplat.MicroSplatUtilities.DrawTextureSelector ((int)d.splatIndexes.z, ta, true);
|
||||
d.splatIndexes.w = JBooth.MicroSplat.MicroSplatUtilities.DrawTextureSelector ((int)d.splatIndexes.w, ta, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox ("Splat's array is enabled, but not assigned to the material. Please assign", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
d.sortOrder = EditorGUILayout.IntField ("Sort Order", d.sortOrder);
|
||||
}
|
||||
EditorGUILayout.Space ();
|
||||
MicroSplatTerrain mst = d.targetObject.msObj as MicroSplatTerrain;
|
||||
bool terrainExists = mst != null;
|
||||
|
||||
#if __MICROSPLAT_MESHTERRAIN__
|
||||
if ((d.targetObject.msObj as MicroSplatMeshTerrain) != null)
|
||||
terrainExists = true;
|
||||
#endif
|
||||
|
||||
if (terrainExists && GUILayout.Button ("Bake Static Decals"))
|
||||
{
|
||||
d.targetObject.RerenderCacheMap ();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space ();
|
||||
EditorGUILayout.Space ();
|
||||
|
||||
if (JBooth.MicroSplat.MicroSplatUtilities.DrawRollup ("Display Settings", false, false))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck ();
|
||||
MicroSplatDecal.gizmoMode = (MicroSplatDecal.GizmoMode)EditorGUILayout.EnumPopup ("Gizmo Mode", MicroSplatDecal.gizmoMode);
|
||||
if (MicroSplatDecal.gizmoMode != MicroSplatDecal.GizmoMode.Hide)
|
||||
{
|
||||
MicroSplatDecal.staticGizmoColor = EditorGUILayout.ColorField ("Static Gizmo Color", MicroSplatDecal.staticGizmoColor);
|
||||
MicroSplatDecal.staticGizmoSelectedColor = EditorGUILayout.ColorField ("Static Gizmo Selected Color", MicroSplatDecal.staticGizmoSelectedColor);
|
||||
MicroSplatDecal.dynamicGizmoColor = EditorGUILayout.ColorField ("Dynamic Gizmo Color", MicroSplatDecal.dynamicGizmoColor);
|
||||
MicroSplatDecal.dynamicGizmoSelectedColor = EditorGUILayout.ColorField ("Dynamic Gizmo Selected Color", MicroSplatDecal.dynamicGizmoSelectedColor);
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
EditorPrefs.SetInt ("MicroSplatDecal_GizmoMode", (int)MicroSplatDecal.gizmoMode);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmocolor-r", MicroSplatDecal.staticGizmoColor.r);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmocolor-g", MicroSplatDecal.staticGizmoColor.g);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmocolor-b", MicroSplatDecal.staticGizmoColor.b);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmocolor-a", MicroSplatDecal.staticGizmoColor.a);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmoselectedcolor-r", MicroSplatDecal.staticGizmoSelectedColor.r);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmoselectedcolor-g", MicroSplatDecal.staticGizmoSelectedColor.g);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmoselectedcolor-b", MicroSplatDecal.staticGizmoSelectedColor.b);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_staticgizmoselectedcolor-a", MicroSplatDecal.staticGizmoSelectedColor.a);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmocolor-r", MicroSplatDecal.dynamicGizmoColor.r);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmocolor-g", MicroSplatDecal.dynamicGizmoColor.g);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmocolor-b", MicroSplatDecal.dynamicGizmoColor.b);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmocolor-a", MicroSplatDecal.dynamicGizmoColor.a);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmoselectedcolor-r", MicroSplatDecal.dynamicGizmoSelectedColor.r);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmoselectedcolor-g", MicroSplatDecal.dynamicGizmoSelectedColor.g);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmoselectedcolor-b", MicroSplatDecal.dynamicGizmoSelectedColor.b);
|
||||
EditorPrefs.SetFloat ("MicroSplatDecal_dynamicgizmocselectedolor-a", MicroSplatDecal.dynamicGizmoSelectedColor.a);
|
||||
}
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
d.targetObject.RerenderCacheMap ();
|
||||
EditorUtility.SetDirty (d);
|
||||
d.Reset ();
|
||||
}
|
||||
MicroSplatDecalReceiver dr = d.targetObject;
|
||||
if (dr.cacheMask != null && terrainExists)
|
||||
{
|
||||
Rect r = EditorGUILayout.GetControlRect (GUILayout.Width (256), GUILayout.Height (256));
|
||||
EditorGUI.DrawPreviewTexture (r, dr.cacheMask);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e42b48fd1c7664ffba149220b86bcdf6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,438 @@
|
||||
//////////////////////////////////////////////////////
|
||||
// MicroSplat
|
||||
// Copyright (c) Jason Booth
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace JBooth.MicroSplat
|
||||
{
|
||||
#if __MICROSPLAT__
|
||||
[InitializeOnLoad]
|
||||
public class MicroSplatDecalModule : FeatureDescriptor
|
||||
{
|
||||
|
||||
[MenuItem ("Window/MicroSplat/Create Decal")]
|
||||
static void AddEmitter ()
|
||||
{
|
||||
GameObject go = new GameObject ("Decal");
|
||||
go.transform.localScale = new Vector3 (10, 10, 10);
|
||||
go.AddComponent<MicroSplatDecal> ();
|
||||
}
|
||||
|
||||
|
||||
const string sDefine = "__MICROSPLAT_DECAL__";
|
||||
|
||||
static MicroSplatDecalModule()
|
||||
{
|
||||
MicroSplatDefines.InitDefine(sDefine);
|
||||
}
|
||||
[PostProcessSceneAttribute (0)]
|
||||
public static void OnPostprocessScene()
|
||||
{
|
||||
MicroSplatDefines.InitDefine(sDefine);
|
||||
}
|
||||
|
||||
public override string ModuleName()
|
||||
{
|
||||
return "Decal";
|
||||
}
|
||||
|
||||
public override string GetHelpPath ()
|
||||
{
|
||||
return "https://docs.google.com/document/d/1I7kDLojwVQbnTkmtSMfVrFW9yaVQLLQi0ibqFLY960A/edit?usp=sharing";
|
||||
}
|
||||
|
||||
public enum DefineFeature
|
||||
{
|
||||
_DECAL,
|
||||
_DECAL_MAX0,
|
||||
_DECAL_MAX4,
|
||||
_DECAL_MAX8,
|
||||
_DECAL_MAX16,
|
||||
_DECAL_MAX32,
|
||||
_DECAL_MAX64,
|
||||
_DECAL_MAX128,
|
||||
_DECAL_MAX256,
|
||||
|
||||
_DECAL_STATICMAX0,
|
||||
_DECAL_STATICMAX64,
|
||||
_DECAL_STATICMAX128,
|
||||
_DECAL_STATICMAX256,
|
||||
_DECAL_STATICMAX512,
|
||||
_DECAL_STATICMAX1024,
|
||||
_DECAL_STATICMAX2048,
|
||||
|
||||
_DECAL_NOTEXTURES,
|
||||
_DECAL_EMISMETAL,
|
||||
_DECAL_SPLAT,
|
||||
_DECAL_TESS,
|
||||
_DECAL_TINT,
|
||||
kNumFeatures,
|
||||
}
|
||||
|
||||
public enum MaxDecals
|
||||
{
|
||||
None,
|
||||
k4,
|
||||
k8,
|
||||
k16,
|
||||
k32,
|
||||
k64,
|
||||
}
|
||||
|
||||
public enum MaxStaticDecals
|
||||
{
|
||||
None,
|
||||
k64,
|
||||
k128,
|
||||
k256,
|
||||
k512,
|
||||
k1024,
|
||||
k2048,
|
||||
}
|
||||
|
||||
|
||||
public bool decals = false;
|
||||
|
||||
public MaxDecals maxDecals = MaxDecals.k16;
|
||||
public MaxStaticDecals maxStaticDecals = MaxStaticDecals.k512;
|
||||
|
||||
public bool effectTextures = true;
|
||||
public bool effectSplats = false;
|
||||
public bool tint = false;
|
||||
public bool emisMetal = false;
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
public bool effectTess = false;
|
||||
#endif
|
||||
static TextAsset properties;
|
||||
static TextAsset funcs;
|
||||
static TextAsset cbuffer;
|
||||
|
||||
GUIContent CDecals = new GUIContent ("Decals", "Enable decal system");
|
||||
|
||||
GUIContent CEffectTextures = new GUIContent ("Effect Diffuse/Normal", "Should decals modify the albedo and normal data");
|
||||
GUIContent CEffectEmisMetal = new GUIContent ("Support Emissive/Metallic map", "When enabled, you can use an emissive/metallic array with decals");
|
||||
GUIContent CEffectSplats = new GUIContent ("Effect Splat Maps", "Should decals modify the splat map or FX (wetness, puddles, streams, lava) data");
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
GUIContent CAffectTess = new GUIContent ("Effect Displacement", "Should decals modify the displacement when tessellation is enabled");
|
||||
#endif
|
||||
|
||||
GUIContent CMaxDecals = new GUIContent ("Max Dynamic", "Maximum number of dynamic decals allowed on a single object or terrain. Dynamic decals have a runtime GPU cost based on how many decals are on an object");
|
||||
GUIContent CMaxStaticDecals = new GUIContent ("Max Static", "Maximum number of static decals allowed on a single terrain. Static Decals have very small runtime cost, but are CPU intensive when moved or adjusted at runtime");
|
||||
|
||||
GUIContent CAlbedo = new GUIContent ("Albedo Array", "Albedo/alpha for decals");
|
||||
GUIContent CEmisMetal = new GUIContent ("Emissive/Metal Array", "Emissive/Metallic array for decals");
|
||||
GUIContent CNormalSAO = new GUIContent ("Normal SAO Array", "NSAO Array for decals");
|
||||
GUIContent CSplat = new GUIContent ("Splat Map Array", "Array for splat maps, 3 texture weights (RGB) and alpha blend (A)");
|
||||
GUIContent CPerDecalTint = new GUIContent ("Decal Tint", "Allows you to tint each decal");
|
||||
|
||||
static Dictionary<DefineFeature, string> sFeatureNames = new Dictionary<DefineFeature, string>();
|
||||
public static string GetFeatureName(DefineFeature feature)
|
||||
{
|
||||
string ret;
|
||||
if (sFeatureNames.TryGetValue(feature, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
string fn = System.Enum.GetName(typeof(DefineFeature), feature);
|
||||
sFeatureNames[feature] = fn;
|
||||
return fn;
|
||||
}
|
||||
|
||||
public static bool HasFeature(string[] keywords, DefineFeature feature)
|
||||
{
|
||||
string f = GetFeatureName(feature);
|
||||
for (int i = 0; i < keywords.Length; ++i)
|
||||
{
|
||||
if (keywords[i] == f)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public override string GetVersion()
|
||||
{
|
||||
return "3.9";
|
||||
}
|
||||
|
||||
public override void DrawFeatureGUI(MicroSplatKeywords keywords)
|
||||
{
|
||||
decals = EditorGUILayout.Toggle (CDecals, decals);
|
||||
|
||||
if (decals)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
using (new GUILayout.VerticalScope (GUI.skin.box))
|
||||
{
|
||||
maxDecals = (MaxDecals)EditorGUILayout.EnumPopup (CMaxDecals, maxDecals);
|
||||
maxStaticDecals = (MaxStaticDecals)EditorGUILayout.EnumPopup (CMaxStaticDecals, maxStaticDecals);
|
||||
}
|
||||
effectTextures = EditorGUILayout.Toggle (CEffectTextures, effectTextures);
|
||||
emisMetal = EditorGUILayout.Toggle (CEffectEmisMetal, emisMetal);
|
||||
|
||||
effectSplats = EditorGUILayout.Toggle (CEffectSplats, effectSplats);
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
effectTess = EditorGUILayout.Toggle (CAffectTess, effectTess);
|
||||
#endif
|
||||
tint = EditorGUILayout.Toggle (CPerDecalTint, tint);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawShaderGUI(MicroSplatShaderGUI shaderGUI, MicroSplatKeywords keywords, Material mat, MaterialEditor materialEditor, MaterialProperty[] props)
|
||||
{
|
||||
if (decals)
|
||||
{
|
||||
if (MicroSplatUtilities.DrawRollup("Decal") && mat.HasProperty("_DecalAlbedo"))
|
||||
{
|
||||
if (effectTextures)
|
||||
{
|
||||
var albedoMap = shaderGUI.FindProp ("_DecalAlbedo", props);
|
||||
materialEditor.TexturePropertySingleLine (CAlbedo, albedoMap);
|
||||
var normalMap = shaderGUI.FindProp ("_DecalNormalSAO", props);
|
||||
materialEditor.TexturePropertySingleLine (CNormalSAO, normalMap);
|
||||
}
|
||||
if (emisMetal && mat.HasProperty("_DecalEmisMetal"))
|
||||
{
|
||||
var emis = shaderGUI.FindProp ("_DecalEmisMetal", props);
|
||||
materialEditor.TexturePropertySingleLine (CEmisMetal, emis);
|
||||
}
|
||||
if (effectSplats && mat.HasProperty("_DecalSplats"))
|
||||
{
|
||||
var splatsMap = shaderGUI.FindProp ("_DecalSplats", props);
|
||||
materialEditor.TexturePropertySingleLine (CSplat, splatsMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] Pack()
|
||||
{
|
||||
List<string> features = new List<string>();
|
||||
if (decals)
|
||||
{
|
||||
features.Add(GetFeatureName(DefineFeature._DECAL));
|
||||
if (maxDecals == MaxDecals.None)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_MAX0));
|
||||
}
|
||||
else if (maxDecals == MaxDecals.k4)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_MAX4));
|
||||
}
|
||||
else if (maxDecals == MaxDecals.k8)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_MAX8));
|
||||
}
|
||||
else if (maxDecals == MaxDecals.k16)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_MAX16));
|
||||
}
|
||||
else if (maxDecals == MaxDecals.k32)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_MAX32));
|
||||
}
|
||||
else if (maxDecals == MaxDecals.k64)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_MAX64));
|
||||
}
|
||||
if (maxStaticDecals == MaxStaticDecals.None)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX0));
|
||||
}
|
||||
if (maxStaticDecals == MaxStaticDecals.k64)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX64));
|
||||
}
|
||||
else if (maxStaticDecals == MaxStaticDecals.k128)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX128));
|
||||
}
|
||||
else if (maxStaticDecals == MaxStaticDecals.k256)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX256));
|
||||
}
|
||||
else if (maxStaticDecals == MaxStaticDecals.k512)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX512));
|
||||
}
|
||||
else if (maxStaticDecals == MaxStaticDecals.k1024)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX1024));
|
||||
}
|
||||
else if (maxStaticDecals == MaxStaticDecals.k2048)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_STATICMAX2048));
|
||||
}
|
||||
|
||||
if (!effectTextures)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_NOTEXTURES));
|
||||
}
|
||||
|
||||
if (effectSplats)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_SPLAT));
|
||||
}
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
if (effectTess)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_TESS));
|
||||
}
|
||||
#endif
|
||||
if (tint)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_TINT));
|
||||
}
|
||||
if (emisMetal)
|
||||
{
|
||||
features.Add (GetFeatureName (DefineFeature._DECAL_EMISMETAL));
|
||||
}
|
||||
}
|
||||
return features.ToArray();
|
||||
}
|
||||
|
||||
public override void Unpack(string[] keywords)
|
||||
{
|
||||
decals = HasFeature (keywords, DefineFeature._DECAL);
|
||||
maxDecals = MaxDecals.k4;
|
||||
if (HasFeature(keywords, DefineFeature._DECAL_MAX0))
|
||||
{
|
||||
maxDecals = MaxDecals.None;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_MAX8))
|
||||
{
|
||||
maxDecals = MaxDecals.k8;
|
||||
}
|
||||
else if (HasFeature(keywords, DefineFeature._DECAL_MAX16))
|
||||
{
|
||||
maxDecals = MaxDecals.k16;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_MAX32))
|
||||
{
|
||||
maxDecals = MaxDecals.k32;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_MAX64))
|
||||
{
|
||||
maxDecals = MaxDecals.k64;
|
||||
}
|
||||
|
||||
maxStaticDecals = MaxStaticDecals.k512;
|
||||
if (HasFeature(keywords, DefineFeature._DECAL_STATICMAX0))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.None;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_STATICMAX64))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.k64;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_STATICMAX128))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.k128;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_STATICMAX256))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.k256;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_STATICMAX512))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.k512;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_STATICMAX1024))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.k1024;
|
||||
}
|
||||
else if (HasFeature (keywords, DefineFeature._DECAL_STATICMAX2048))
|
||||
{
|
||||
maxStaticDecals = MaxStaticDecals.k2048;
|
||||
}
|
||||
|
||||
effectTextures = !HasFeature (keywords, DefineFeature._DECAL_NOTEXTURES);
|
||||
emisMetal = HasFeature (keywords, DefineFeature._DECAL_EMISMETAL);
|
||||
effectSplats = HasFeature (keywords, DefineFeature._DECAL_SPLAT);
|
||||
tint = HasFeature (keywords, DefineFeature._DECAL_TINT);
|
||||
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
effectTess = HasFeature (keywords, DefineFeature._DECAL_TESS);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
public override void InitCompiler(string[] paths)
|
||||
{
|
||||
for (int i = 0; i < paths.Length; ++i)
|
||||
{
|
||||
string p = paths[i];
|
||||
if (p.EndsWith("microsplat_properties_decal.txt"))
|
||||
{
|
||||
properties = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
|
||||
}
|
||||
if (p.EndsWith("microsplat_func_decal.txt"))
|
||||
{
|
||||
funcs = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
|
||||
}
|
||||
if (p.EndsWith ("microsplat_cbuffer_decal.txt"))
|
||||
{
|
||||
cbuffer = AssetDatabase.LoadAssetAtPath<TextAsset> (p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteProperties(string[] features, System.Text.StringBuilder sb)
|
||||
{
|
||||
if (decals)
|
||||
{
|
||||
sb.Append(properties.text);
|
||||
if (emisMetal)
|
||||
{
|
||||
sb.AppendLine ("_DecalEmisMetal(\"Decal Emissive Metal\", 2DArray) = \"black\" {}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteFunctions(string [] features, System.Text.StringBuilder sb)
|
||||
{
|
||||
if (decals)
|
||||
{
|
||||
sb.Append(funcs.text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void WritePerMaterialCBuffer (string[] features, System.Text.StringBuilder sb)
|
||||
{
|
||||
if (decals)
|
||||
{
|
||||
sb.Append(cbuffer.text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ComputeSampleCounts(string[] features, ref int arraySampleCount, ref int textureSampleCount, ref int maxSamples, ref int tessellationSamples, ref int depTexReadLevel)
|
||||
{
|
||||
if (decals)
|
||||
{
|
||||
// this is rather arbitrary, could do some approximation based on static vs. dynamic counts, but wouldn't be any more or less
|
||||
// correct than this..
|
||||
arraySampleCount += 8;
|
||||
}
|
||||
#if __MICROSPLAT_TESSELLATION__
|
||||
if (effectTess)
|
||||
{
|
||||
tessellationSamples += 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b34a7e6c2739b4c6b921cf77a41dda6a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using JBooth.MicroSplat;
|
||||
|
||||
[CustomEditor (typeof (MicroSplatDecalReceiver))]
|
||||
public class MicroSplatDecalReceiverEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI ()
|
||||
{
|
||||
MicroSplatDecalReceiver dr = (MicroSplatDecalReceiver)target;
|
||||
if (dr.GetComponent<MicroSplatTerrain> () != null
|
||||
#if __MICROSPLAT_MESHTERRAIN__
|
||||
|| dr.GetComponent<MicroSplatMeshTerrain>() != null
|
||||
#endif
|
||||
)
|
||||
{
|
||||
serializedObject.Update ();
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generateCacheOnLoad"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("staticCacheSize"));
|
||||
|
||||
serializedObject.ApplyModifiedProperties ();
|
||||
|
||||
|
||||
EditorGUILayout.Space ();
|
||||
EditorGUILayout.Space ();
|
||||
EditorGUILayout.LabelField ("Dynamic Count: " + dr.dynamicCount);
|
||||
|
||||
EditorGUILayout.LabelField ("Static Count: " + dr.staticCount);
|
||||
|
||||
|
||||
if (dr.cacheMask != null)
|
||||
{
|
||||
Rect r = EditorGUILayout.GetControlRect (GUILayout.Width (256), GUILayout.Height (256));
|
||||
EditorGUI.DrawPreviewTexture (r, dr.cacheMask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.LabelField ("Dynamic Count: " + dr.dynamicCount);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b767abc50fc1340eebeea34f28bd2a9e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user