86 lines
2.8 KiB
Plaintext
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);
|
||
|
}
|