Files
ZHGD_Web/Assets/Art/Art Plugins/GPUInstancer/Demos/CustomComputeShader/Resources/GPUIBoids.compute
2025-07-13 23:16:20 +08:00

86 lines
2.8 KiB
Plaintext

// Inspired by https://github.com/keijiro/Boids
#include "../../../Resources/Compute/Include/PlatformDefines.hlsl"
#pragma kernel CSGPUIBoids
RWStructuredBuffer<float4x4> boidsData;
uniform uint bufferSize;
uniform Texture2D<float4> noiseTexture;
uniform SamplerState samplernoiseTexture;
uniform float4x4 controllerTransform;
uniform float controllerVelocity;
uniform float controllerVelocityVariation;
uniform float controllerRotationCoeff;
uniform float controllerNeighborDist;
uniform float time;
uniform float deltaTime;
#include "../../../Resources/Compute/Include/DataModel.hlsl"
#include "../../../Resources/Compute/Include/Matrix.hlsl"
float3 GetSeparationVector(float3 pos, float3 targetPos)
{
float3 diff = pos - targetPos;
float diffLen = length(diff);
float scaler = clamp(1.0f - diffLen / controllerNeighborDist, 0, 1);
return diff * (scaler / diffLen);
}
[numthreads(GPUI_THREADS, 1, 1)]
void CSGPUIBoids(uint3 id : SV_DispatchThreadID)
{
if (id.x >= bufferSize)
return;
float4x4 boid = boidsData[id.x];
float3 currentPosition = boid._14_24_34;
float3 currentDirection = boid._13_23_33;
// Current velocity randomized with noise.
float4 noiseTxt = noiseTexture.SampleLevel(samplernoiseTexture, float2(time / 100.0, (float(id.x) / float(bufferSize))), 0);
float velocity = controllerVelocity * (1.0 + lerp(0, lerp(-1, 1, noiseTxt.r), controllerVelocityVariation));
// Initializes the vectors.
float3 separation = float3(0, 0, 0);
float3 alignment = float3(0, 0, 0);
float3 cohesion = controllerTransform._14_24_34;
uint nearbyCount = 1;
// Accumulates the vectors.
for (uint i = 0; i < bufferSize; i++)
{
if (i == id.x)
continue;
float4x4 checkBoid = boidsData[i];
float3 checkPos = checkBoid._14_24_34;
if (distance(currentPosition, checkPos) <= controllerNeighborDist)
{
separation += GetSeparationVector(currentPosition, checkPos);
alignment += checkBoid._13_23_33;
cohesion += checkPos;
nearbyCount++;
}
}
float avg = 1.0f / nearbyCount;
alignment *= avg;
cohesion *= avg;
cohesion = normalize(cohesion - currentPosition);
// Calculates a rotation from the vectors.
float3 direction = normalize(separation + alignment + cohesion);
// Applys the rotation with interpolation.
float ip = frac(exp(-controllerRotationCoeff * deltaTime) * controllerRotationCoeff / 100);
float4x4 newRotation = SetMatrixRotationWithQuaternion(identityMatrix, FromToRotation(float3(0, 0, 1), lerp(currentDirection, direction, ip)));
// Moves forward.
currentPosition = currentPosition + newRotation._13_23_33 * (velocity * deltaTime);
boidsData[id.x] = TRS(currentPosition, newRotation, vector3One);
}