Added slang shaders for compute nbody sample

This commit is contained in:
Sascha Willems 2025-05-20 19:42:21 +02:00
parent 00378d9760
commit 9ff0f35f24
3 changed files with 164 additions and 0 deletions

View file

@ -0,0 +1,56 @@
/* Copyright (c) 2025, Sascha Willems
*
* SPDX-License-Identifier: MIT
*
*/
struct VSInput
{
float4 Pos;
float4 Vel;
};
struct VSOutput
{
float4 Pos : SV_POSITION;
float PSize : SV_PointSize;
float GradientPos;
float2 CenterPos;
float PointSize;
};
Sampler2D samplerColorMap;
Sampler2D samplerGradientRamp;
struct UBO
{
float4x4 projection;
float4x4 modelview;
float2 screendim;
};
ConstantBuffer<UBO> ubo;
[shader("vertex")]
VSOutput vertexMain(VSInput input)
{
VSOutput output;
const float spriteSize = 0.005 * input.Pos.w; // Point size influenced by mass (stored in input.Pos.w);
float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0));
float4 projectedCorner = mul(ubo.projection, float4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w));
output.PSize = output.PointSize = clamp(ubo.screendim.x * projectedCorner.x / projectedCorner.w, 1.0, 128.0);
output.Pos = mul(ubo.projection, eyePos);
output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * ubo.screendim;
output.GradientPos = input.Vel.w;
return output;
}
[shader("fragment")]
float4 fragmentMain(VSOutput input)
{
float3 color = samplerGradientRamp.Sample(float2(input.GradientPos, 0.0)).rgb;
float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5;
return float4(samplerColorMap.Sample(PointCoord).rgb * color, 1);
}

View file

@ -0,0 +1,77 @@
/* Copyright (c) 2025, Sascha Willems
*
* SPDX-License-Identifier: MIT
*
*/
struct Particle
{
float4 pos;
float4 vel;
};
// Binding 0 : Position storage buffer
RWStructuredBuffer<Particle> particles;
struct UBO
{
float deltaT;
int particleCount;
float gravity;
float power;
float soften;
};
ConstantBuffer<UBO> ubo;
#define MAX_SHARED_DATA_SIZE 1024
[[SpecializationConstant]] const int SHARED_DATA_SIZE = 512;
[[SpecializationConstant]] const float GRAVITY = 0.002;
[[SpecializationConstant]] const float POWER = 0.75;
[[SpecializationConstant]] const float SOFTEN = 0.0075;
// Share data between computer shader invocations to speed up caluclations
groupshared float4 sharedData[MAX_SHARED_DATA_SIZE];
[shader("compute")]
[numthreads(256, 1, 1)]
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID, uint3 LocalInvocationID : SV_GroupThreadID)
{
// Current SSBO index
uint index = GlobalInvocationID.x;
if (index >= ubo.particleCount)
return;
float4 position = particles[index].pos;
float4 velocity = particles[index].vel;
float4 acceleration = float4(0, 0, 0, 0);
for (int i = 0; i < ubo.particleCount; i += SHARED_DATA_SIZE)
{
if (i + LocalInvocationID.x < ubo.particleCount)
{
sharedData[LocalInvocationID.x] = particles[i + LocalInvocationID.x].pos;
}
else
{
sharedData[LocalInvocationID.x] = float4(0, 0, 0, 0);
}
GroupMemoryBarrierWithGroupSync();
for (int j = 0; j < 256; j++)
{
float4 other = sharedData[j];
float3 len = other.xyz - position.xyz;
acceleration.xyz += ubo.gravity * len * other.w / pow(dot(len, len) + ubo.soften, ubo.power);
}
GroupMemoryBarrierWithGroupSync();
}
particles[index].vel.xyz += ubo.deltaT * acceleration.xyz;
// Gradient texture position
particles[index].vel.w += 0.1 * ubo.deltaT;
if (particles[index].vel.w > 1.0) {
particles[index].vel.w -= 1.0;
}
}

View file

@ -0,0 +1,31 @@
/* Copyright (c) 2025, Sascha Willems
*
* SPDX-License-Identifier: MIT
*
*/
struct Particle
{
float4 pos;
float4 vel;
};
// Binding 0 : Position storage buffer
RWStructuredBuffer<Particle> particles;
struct UBO
{
float deltaT;
int particleCount;
};
ConstantBuffer<UBO> ubo;
[shader("compute")]
[numthreads(256, 1, 1)]
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
{
int index = int(GlobalInvocationID.x);
float4 position = particles[index].pos;
float4 velocity = particles[index].vel;
position += ubo.deltaT * velocity;
particles[index].pos = position;
}