111
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
#pragma kernel CSMain
|
||||
|
||||
struct InstData
|
||||
{
|
||||
float3 pos;
|
||||
float3 angle;
|
||||
float3 scale;
|
||||
};
|
||||
|
||||
RWStructuredBuffer<InstData> _InstDataBuffer;
|
||||
|
||||
//
|
||||
float4 _FrustumPlanes[6];
|
||||
float3 _BoundMin;
|
||||
float3 _BoundMax;
|
||||
AppendStructuredBuffer<uint> _CullIDsBuffer;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
float4 EularToQuaternion(float3 angle)
|
||||
{
|
||||
float X = angle.x * 0.0174532925 / 2;
|
||||
float Y = angle.y * 0.0174532925 / 2;
|
||||
float Z = angle.z * 0.0174532925 / 2;
|
||||
float x = sin(X) * cos(Y) * cos(Z) + cos(X) * sin(Y) * sin(Z);
|
||||
float y = cos(X) * sin(Y) * cos(Z) - sin(X) * cos(Y) * sin(Z);
|
||||
float z = cos(X) * cos(Y) * sin(Z) - sin(X) * sin(Y) * cos(Z);
|
||||
float w = cos(X) * cos(Y) * cos(Z) + sin(X) * sin(Y) * sin(Z);
|
||||
return float4(x, y, z, w);
|
||||
}
|
||||
|
||||
float4x4 TRSMatrix(float3 position, float4 rotation, float3 scale)
|
||||
{
|
||||
float4x4 m = 0.0;
|
||||
m[0][0] = (1.0 - 2.0 * (rotation.y * rotation.y + rotation.z * rotation.z)) * scale.x;
|
||||
m[1][0] = (rotation.x * rotation.y + rotation.z * rotation.w) * scale.x * 2.0;
|
||||
m[2][0] = (rotation.x * rotation.z - rotation.y * rotation.w) * scale.x * 2.0;
|
||||
m[3][0] = 0.0;
|
||||
|
||||
m[0][1] = (rotation.x * rotation.y - rotation.z * rotation.w) * scale.y * 2.0;
|
||||
m[1][1] = (1.0 - 2.0 * (rotation.x * rotation.x + rotation.z * rotation.z)) * scale.y;
|
||||
m[2][1] = (rotation.y * rotation.z + rotation.x * rotation.w) * scale.y * 2.0;
|
||||
m[3][1] = 0.0;
|
||||
|
||||
m[0][2] = (rotation.x * rotation.z + rotation.y * rotation.w) * scale.z * 2.0;
|
||||
m[1][2] = (rotation.y * rotation.z - rotation.x * rotation.w) * scale.z * 2.0;
|
||||
m[2][2] = (1.0 - 2.0 * (rotation.x * rotation.x + rotation.y * rotation.y)) * scale.z;
|
||||
m[3][2] = 0.0;
|
||||
|
||||
m[0][3] = position.x;
|
||||
m[1][3] = position.y;
|
||||
m[2][3] = position.z;
|
||||
m[3][3] = 1.0;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
bool IsOutsideThePlane(float4 plane, float3 position)
|
||||
{
|
||||
return dot(plane.xyz, position) + plane.w > 0;
|
||||
}
|
||||
|
||||
void FrustumCull(float index)
|
||||
{
|
||||
InstData instData = _InstDataBuffer[index];
|
||||
|
||||
//
|
||||
float4x4 m = TRSMatrix(instData.pos, EularToQuaternion(instData.angle), instData.scale);
|
||||
float4 boundPoints[8];
|
||||
boundPoints[0] = mul(m, float4(_BoundMin, 1));
|
||||
boundPoints[1] = mul(m, float4(_BoundMax, 1));
|
||||
boundPoints[2] = mul(m, float4(_BoundMax.x, _BoundMax.y, _BoundMin.z, 1));
|
||||
boundPoints[3] = mul(m, float4(_BoundMax.x, _BoundMin.y, _BoundMax.z, 1));
|
||||
boundPoints[4] = mul(m, float4(_BoundMax.x, _BoundMin.y, _BoundMin.z, 1));
|
||||
boundPoints[5] = mul(m, float4(_BoundMin.x, _BoundMax.y, _BoundMax.z, 1));
|
||||
boundPoints[6] = mul(m, float4(_BoundMin.x, _BoundMax.y, _BoundMin.z, 1));
|
||||
boundPoints[7] = mul(m, float4(_BoundMin.x, _BoundMin.y, _BoundMax.z, 1));
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
float3 p = boundPoints[j].xyz;
|
||||
if (!IsOutsideThePlane(_FrustumPlanes[i], p))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == 7)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_CullIDsBuffer.Append(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// We used to just be able to use (1, 1, 1) threads for whatever population (not sure the old limit), but a Unity update
|
||||
// imposed a thread limit of 65535. Now, to populations above that, we need to be more granular with our threads.
|
||||
[numthreads(128, 1, 1)]
|
||||
void CSMain(uint3 id : SV_DispatchThreadID)
|
||||
{
|
||||
//Action(id.x);
|
||||
FrustumCull(id.x);
|
||||
}
|
||||
Reference in New Issue
Block a user