240 lines
9.1 KiB
HLSL
240 lines
9.1 KiB
HLSL
|
struct Cube
|
||
|
{
|
||
|
float3 min;
|
||
|
float3 max;
|
||
|
};
|
||
|
|
||
|
float random(in float3 st)
|
||
|
{
|
||
|
return frac(cos(dot(st.xyz, float3(12.9898, 78.233, 123.691))) * 43758.5453123);
|
||
|
}
|
||
|
|
||
|
float _TriToCube;
|
||
|
float _SpawnAlpha;
|
||
|
float3 _LocalSpawnOffset;
|
||
|
float3 _WorldSpawnOffset;
|
||
|
float _Pieces;
|
||
|
int _AssemblyMode;
|
||
|
float3 _AssemblyBegin;
|
||
|
float3 _AssemblyEnd;
|
||
|
int _ExplodeMode;
|
||
|
float _ExplodeFadeDistance;
|
||
|
|
||
|
void assembleVert(float3 newPos, v2f i, float2 newUV, float alpha, inout v2f o)
|
||
|
{
|
||
|
float3 worldPos = lerp(i.worldPos, newPos, alpha);
|
||
|
o.uv = lerp(i.uv, newUV, _TriToCube);
|
||
|
o.pos = UnityWorldToClipPos(float4(worldPos, 1));
|
||
|
o.worldPos = float4(worldPos, 1);
|
||
|
}
|
||
|
|
||
|
[maxvertexcount(18)]
|
||
|
void geom(triangle v2f IN[3], inout TriangleStream < v2f > tristream)
|
||
|
{
|
||
|
float3 edgeA = IN[1].localPos - IN[0].localPos;
|
||
|
float3 edgeB = IN[2].localPos - IN[0].localPos;
|
||
|
float3 c = cross(edgeA, edgeB);
|
||
|
float3 outDir = normalize(c);
|
||
|
|
||
|
float4 center = (IN[0].worldPos + IN[1].worldPos + IN[2].worldPos) / 3;
|
||
|
float2 uv = (IN[0].uv + IN[1].uv + IN[2].uv) / 3;
|
||
|
Cube cube;
|
||
|
v2f o;
|
||
|
|
||
|
float rando = random(float3(IN[0].vertexId, IN[1].vertexId, IN[2].vertexId));
|
||
|
//center += rando/50;
|
||
|
// Calculate Cube Bounds
|
||
|
cube.min = IN[0].worldPos;
|
||
|
cube.max = IN[0].worldPos;
|
||
|
for (int i = 1; i < 3; i ++)
|
||
|
{
|
||
|
cube.min = float3(min(IN[i].worldPos.x, cube.min.x), min(IN[i].worldPos.y, cube.min.y), min(IN[i].worldPos.z, cube.min.z));
|
||
|
cube.max = float3(max(IN[i].worldPos.x, cube.max.x), max(IN[i].worldPos.y, cube.max.y), max(IN[i].worldPos.z, cube.max.z));
|
||
|
}
|
||
|
cube.min = lerp(cube.min, center, rando / 20);
|
||
|
cube.max = lerp(cube.max, center, rando / 20);
|
||
|
float4 offset = 0;
|
||
|
if (_ExplodeMode == 0)
|
||
|
{
|
||
|
offset = float4(_WorldSpawnOffset, 0) + mul(unity_ObjectToWorld, _LocalSpawnOffset);
|
||
|
}
|
||
|
else if(_ExplodeMode == 1)
|
||
|
{
|
||
|
offset = float4(outDir * _ExplodeFadeDistance, 0);
|
||
|
}
|
||
|
|
||
|
float4 cameraExplodeOffset = 0;
|
||
|
|
||
|
float spawnAlpha = 0;
|
||
|
|
||
|
if(_AssemblyMode == 0) // Random
|
||
|
{
|
||
|
spawnAlpha = saturate((-rando) * _Pieces + (_SpawnAlpha * (_Pieces + 1)));
|
||
|
}
|
||
|
else if (_AssemblyMode == 1) // Building Blocks
|
||
|
{
|
||
|
float lineMagnitude = distance(_AssemblyBegin, _AssemblyEnd);
|
||
|
float3 constructionLine = (_AssemblyEnd - _AssemblyBegin);
|
||
|
float3 objectLine = (mul(unity_WorldToObject, center) - _AssemblyBegin);
|
||
|
float progress = -1 + saturate(dot(constructionLine, objectLine) / (lineMagnitude * lineMagnitude));
|
||
|
|
||
|
IN[0].localPos.z = progress;
|
||
|
IN[1].localPos.z = progress;
|
||
|
IN[2].localPos.z = progress;
|
||
|
|
||
|
spawnAlpha = saturate((progress) * _Pieces + (_SpawnAlpha * (_Pieces + 1)));
|
||
|
}
|
||
|
|
||
|
cube.min = lerp(cube.min, center + offset, spawnAlpha);
|
||
|
cube.max = lerp(cube.max, center + offset, spawnAlpha);
|
||
|
|
||
|
// Construct Cubes
|
||
|
float3 normal = float3(0, 0, 1);
|
||
|
o = IN[0];
|
||
|
o.uv = lerp(o.uv, uv, _TriToCube);
|
||
|
|
||
|
IN[0].worldPos = lerp(IN[0].worldPos, center + offset, spawnAlpha);
|
||
|
IN[1].worldPos = lerp(IN[1].worldPos, center + offset, spawnAlpha);
|
||
|
IN[2].worldPos = lerp(IN[2].worldPos, center + offset, spawnAlpha);
|
||
|
|
||
|
|
||
|
if (_TriToCube == 0)
|
||
|
{
|
||
|
for (int i = 0; i < 3; i ++)
|
||
|
{
|
||
|
IN[i].pos = UnityWorldToClipPos(IN[i].worldPos);
|
||
|
tristream.Append(IN[i]);
|
||
|
}
|
||
|
tristream.RestartStrip();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float3 viewDirection = normalize(center - getCameraPosition());
|
||
|
|
||
|
//Front
|
||
|
o.normal = float3(0, 0, 1);
|
||
|
if (dot(viewDirection, o.normal) < 0)
|
||
|
{
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.max.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.max.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.max.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.max.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.max.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.max.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
}
|
||
|
|
||
|
//Back
|
||
|
o.normal = float3(0, 0, -1);
|
||
|
if (dot(viewDirection, o.normal) < 0)
|
||
|
{
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.min.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.min.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.min.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.min.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.min.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.min.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
}
|
||
|
|
||
|
//-x
|
||
|
o.normal = float3(1, 0, 0);
|
||
|
if (dot(viewDirection, o.normal) < 0)
|
||
|
{
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.min.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.max.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.min.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.max.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.min.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.max.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
}
|
||
|
|
||
|
//+x
|
||
|
o.normal = float3(-1, 0, 0);
|
||
|
if (dot(viewDirection, o.normal) < 0)
|
||
|
{
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.min.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.max.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.min.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.max.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.min.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.max.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
}
|
||
|
|
||
|
//up
|
||
|
o.normal = float3(0, 1, 0);
|
||
|
if (dot(viewDirection, o.normal) < 0)
|
||
|
{
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.max.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.min.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.min.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.min.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.max.y, cube.max.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.max.y, cube.max.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
}
|
||
|
|
||
|
//down
|
||
|
o.normal = float3(0, -1, 0);
|
||
|
if (dot(viewDirection, o.normal) < 0)
|
||
|
{
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.min.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.min.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.max.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.max.z), IN[0], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.min.x, cube.min.y, cube.max.z), IN[1], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
assembleVert(float3(cube.max.x, cube.min.y, cube.min.z), IN[2], uv, _TriToCube, o);
|
||
|
tristream.Append(o);
|
||
|
tristream.RestartStrip();
|
||
|
}
|
||
|
/*
|
||
|
for (int i = 0; i < 3; i ++)
|
||
|
{
|
||
|
IN[i].uv = uv;
|
||
|
tristream.Append(IN[i]);
|
||
|
}
|
||
|
*/
|
||
|
}
|