res-avatar-unity/Assets/_PoiyomiShaders/Shaders/7.3/Patreon/VoxelCubed/Includes/PoiGeom.cginc
2023-07-15 19:51:23 -07:00

240 lines
9.1 KiB
HLSL
Executable file

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]);
}
*/
}