ComputeParticlesTest: Improve test to actually use Nazara logo
This commit is contained in:
parent
0c6ca52af0
commit
1d3190ac24
|
|
@ -22,7 +22,7 @@ fn main(input: Input)
|
||||||
|
|
||||||
let outputColor = vec4[f32]
|
let outputColor = vec4[f32]
|
||||||
(
|
(
|
||||||
(pow(1.0 - length(uv), 10.0)).xxx,
|
(pow(1.0 - length(uv), 14.0)).xxx,
|
||||||
1.0
|
1.0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ struct Particle
|
||||||
{
|
{
|
||||||
color: vec3[f32],
|
color: vec3[f32],
|
||||||
position: vec2[f32],
|
position: vec2[f32],
|
||||||
|
targetPosition: vec2[f32],
|
||||||
velocity: vec2[f32]
|
velocity: vec2[f32]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,7 +21,8 @@ struct ParticleData
|
||||||
struct SceneData
|
struct SceneData
|
||||||
{
|
{
|
||||||
deltaTime: f32,
|
deltaTime: f32,
|
||||||
mousePos: vec2[f32]
|
mousePos: vec2[f32],
|
||||||
|
effectRadius: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
external
|
external
|
||||||
|
|
@ -42,12 +44,20 @@ fn main(input: Input)
|
||||||
if (index >= data.particle_count)
|
if (index >= data.particle_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let damping = pow(0.5, sceneData.deltaTime);
|
// Gets pushed by the cursor
|
||||||
|
|
||||||
let attract_pos = sceneData.mousePos;
|
let attract_pos = sceneData.mousePos;
|
||||||
let dist = length(attract_pos - data.particles[index].position);
|
let dist = length(attract_pos - data.particles[index].position);
|
||||||
data.particles[index].velocity += 10000.0 * (attract_pos - data.particles[index].position) * sceneData.deltaTime / (dist * dist);
|
data.particles[index].velocity -= 10000.0 * sceneData.effectRadius / min(dist, sceneData.effectRadius) * sceneData.deltaTime * (attract_pos - data.particles[index].position) / (dist * dist * dist * dist);
|
||||||
|
|
||||||
|
// But want to return to their original position
|
||||||
|
let dist = length(data.particles[index].targetPosition - data.particles[index].position);
|
||||||
|
let shouldUseDir = dist < 1.0;
|
||||||
|
data.particles[index].velocity += 100.0 * sceneData.deltaTime * select(shouldUseDir, normalize(data.particles[index].targetPosition - data.particles[index].position), vec2[f32](0.0, 0.0));
|
||||||
|
|
||||||
|
// Lose speed with time
|
||||||
|
let damping = pow(0.5, sceneData.deltaTime);
|
||||||
data.particles[index].velocity *= damping;
|
data.particles[index].velocity *= damping;
|
||||||
|
|
||||||
|
// Move particle
|
||||||
data.particles[index].position += data.particles[index].velocity * sceneData.deltaTime;
|
data.particles[index].position += data.particles[index].velocity * sceneData.deltaTime;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,36 +60,77 @@ int main()
|
||||||
nzsl::FieldOffsets particleLayout(nzsl::StructLayout::Std140);
|
nzsl::FieldOffsets particleLayout(nzsl::StructLayout::Std140);
|
||||||
std::size_t particleColorOffset = particleLayout.AddField(nzsl::StructFieldType::Float3);
|
std::size_t particleColorOffset = particleLayout.AddField(nzsl::StructFieldType::Float3);
|
||||||
std::size_t particlePosOffset = particleLayout.AddField(nzsl::StructFieldType::Float2);
|
std::size_t particlePosOffset = particleLayout.AddField(nzsl::StructFieldType::Float2);
|
||||||
|
std::size_t particleTargetPosOffset = particleLayout.AddField(nzsl::StructFieldType::Float2);
|
||||||
std::size_t particleVelOffset = particleLayout.AddField(nzsl::StructFieldType::Float2);
|
std::size_t particleVelOffset = particleLayout.AddField(nzsl::StructFieldType::Float2);
|
||||||
|
|
||||||
std::size_t particleSize = particleLayout.GetAlignedSize();
|
std::size_t particleSize = particleLayout.GetAlignedSize();
|
||||||
|
|
||||||
constexpr std::size_t maxParticleCount = 10'000;
|
std::shared_ptr<Nz::Image> logo = Nz::Image::LoadFromFile(resourceDir / "Logo.png");
|
||||||
constexpr std::size_t initialParticleCount = maxParticleCount;
|
if (!logo)
|
||||||
|
{
|
||||||
|
std::cerr << "failed to load logo" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<Nz::Vector2ui, Nz::Color>> logoParticles;
|
||||||
|
for (unsigned int y = 0; y < logo->GetHeight(); ++y)
|
||||||
|
{
|
||||||
|
for (unsigned int x = 0; x < logo->GetWidth(); ++x)
|
||||||
|
{
|
||||||
|
Nz::Color color = logo->GetPixelColor(x, y);
|
||||||
|
if (color.a == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logoParticles.push_back({
|
||||||
|
{ x, y },
|
||||||
|
color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t particleCount = logoParticles.size();
|
||||||
|
|
||||||
nzsl::FieldOffsets bufferLayout(nzsl::StructLayout::Std140);
|
nzsl::FieldOffsets bufferLayout(nzsl::StructLayout::Std140);
|
||||||
std::size_t particleCountOffset = bufferLayout.AddField(nzsl::StructFieldType::UInt1);
|
std::size_t particleCountOffset = bufferLayout.AddField(nzsl::StructFieldType::UInt1);
|
||||||
std::size_t particlesOffset = bufferLayout.AddStructArray(particleLayout, maxParticleCount);
|
std::size_t particlesOffset = bufferLayout.AddStructArray(particleLayout, particleCount);
|
||||||
|
|
||||||
std::size_t bufferSize = bufferLayout.GetAlignedSize();
|
std::size_t bufferSize = bufferLayout.GetAlignedSize();
|
||||||
|
|
||||||
std::vector<Nz::UInt8> particleBufferInitialData(bufferSize);
|
std::vector<Nz::UInt8> particleBufferInitialData(bufferSize);
|
||||||
Nz::AccessByOffset<Nz::UInt32&>(particleBufferInitialData.data(), particleCountOffset) = initialParticleCount;
|
Nz::AccessByOffset<Nz::UInt32&>(particleBufferInitialData.data(), particleCountOffset) = particleCount;
|
||||||
|
|
||||||
std::mt19937 rand(std::random_device{}());
|
std::mt19937 rand(std::random_device{}());
|
||||||
std::uniform_real_distribution<float> colorDis(0.f, 1.f);
|
std::uniform_real_distribution<float> colorDis(0.f, 1.f);
|
||||||
std::uniform_real_distribution<float> posXDis(0.f, float(windowSize.x));
|
std::uniform_real_distribution<float> posXDis(-float(windowSize.x), windowSize.x * 2.f);
|
||||||
std::uniform_real_distribution<float> posYDis(0.f, float(windowSize.y));
|
std::uniform_real_distribution<float> posYDis(-float(windowSize.y), windowSize.y * 2.f);
|
||||||
std::uniform_real_distribution<float> velDis(-20.f, 20.f);
|
std::uniform_real_distribution<float> velDis(-50.f, 50.f);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < initialParticleCount; ++i)
|
Nz::Vector2f logoImageSize(Nz::Vector2ui(logo->GetSize()));
|
||||||
|
Nz::Vector2f logoSize = Nz::Vector2f(windowSize) * 0.8f;
|
||||||
|
|
||||||
|
// Center the logo in the canvas
|
||||||
|
Nz::Vector2f posScale = logoSize / logoImageSize;
|
||||||
|
|
||||||
|
Nz::Vector2f posOffset = (Nz::Vector2f(windowSize) - logoSize) * 0.5f;
|
||||||
|
|
||||||
|
// from image space to world space (topleft Y down to bottomleft Y up)
|
||||||
|
posScale.y *= -1.f;
|
||||||
|
posOffset.y += logoSize.y;
|
||||||
|
|
||||||
|
// Build particles
|
||||||
|
Nz::UInt8* particleBasePtr = particleBufferInitialData.data() + particlesOffset;
|
||||||
|
Nz::SparsePtr<Nz::Vector2f> particlePosPtr(particleBasePtr + particlePosOffset, particleSize);
|
||||||
|
Nz::SparsePtr<Nz::Vector2f> particleTargetPosPtr(particleBasePtr + particleTargetPosOffset, particleSize);
|
||||||
|
Nz::SparsePtr<Nz::Vector3f> particleColorPtr(particleBasePtr + particleColorOffset, particleSize);
|
||||||
|
Nz::SparsePtr<Nz::Vector2f> particleVelPtr(particleBasePtr + particleVelOffset, particleSize);
|
||||||
|
for (std::size_t i = 0; i < particleCount; ++i)
|
||||||
{
|
{
|
||||||
std::size_t baseOffset = particlesOffset + particleSize * i;
|
auto&& [pos, color] = logoParticles[i];
|
||||||
|
|
||||||
Nz::AccessByOffset<Nz::Vector3f&>(particleBufferInitialData.data(), baseOffset + particleColorOffset) = Nz::Vector3f(colorDis(rand), colorDis(rand), colorDis(rand));
|
particlePosPtr[i] = Nz::Vector2f(posXDis(rand), posYDis(rand));
|
||||||
//Nz::AccessByOffset<Nz::Vector3f&>(particleBufferInitialData.data(), baseOffset + particleColorOffset) = (i > 2500) ? Nz::Vector3f(0.f, 1.f, 0.f) : Nz::Vector3f(0.f, 0.f, 1.f);
|
particleTargetPosPtr[i] = posScale * Nz::Vector2f(pos) + posOffset;
|
||||||
Nz::AccessByOffset<Nz::Vector2f&>(particleBufferInitialData.data(), baseOffset + particlePosOffset) = Nz::Vector2f(posXDis(rand), posYDis(rand));
|
particleColorPtr[i] = Nz::Vector3f(color.r, color.g, color.b) * color.a;
|
||||||
Nz::AccessByOffset<Nz::Vector2f&>(particleBufferInitialData.data(), baseOffset + particleVelOffset) = Nz::Vector2f(velDis(rand), velDis(rand));
|
particleVelPtr[i] = Nz::Vector2f(velDis(rand), velDis(rand));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderBuffer> particleBuffer = device->InstantiateBuffer(Nz::BufferType::Storage, bufferSize, Nz::BufferUsage::DeviceLocal, particleBufferInitialData.data());
|
std::shared_ptr<Nz::RenderBuffer> particleBuffer = device->InstantiateBuffer(Nz::BufferType::Storage, bufferSize, Nz::BufferUsage::DeviceLocal, particleBufferInitialData.data());
|
||||||
|
|
@ -97,6 +138,7 @@ int main()
|
||||||
nzsl::FieldOffsets sceneBufferLayout(nzsl::StructLayout::Std140);
|
nzsl::FieldOffsets sceneBufferLayout(nzsl::StructLayout::Std140);
|
||||||
std::size_t deltaTimeOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float1);
|
std::size_t deltaTimeOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float1);
|
||||||
std::size_t mousePosOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float2);
|
std::size_t mousePosOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float2);
|
||||||
|
std::size_t effectRadiusOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float1);
|
||||||
|
|
||||||
std::size_t sceneBufferSize = sceneBufferLayout.GetAlignedSize();
|
std::size_t sceneBufferSize = sceneBufferLayout.GetAlignedSize();
|
||||||
|
|
||||||
|
|
@ -157,18 +199,15 @@ int main()
|
||||||
hasNewPipeline = true;
|
hasNewPipeline = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string windowTitle = "Compute test";
|
std::string windowTitle = "Particle test (" + std::to_string(particleCount) + " particles)";
|
||||||
Nz::Window window;
|
Nz::Window window;
|
||||||
if (!window.Create(Nz::VideoMode(1280, 720), windowTitle))
|
if (!window.Create(Nz::VideoMode(windowSize.x, windowSize.y), windowTitle))
|
||||||
{
|
{
|
||||||
std::cout << "Failed to create Window" << std::endl;
|
std::cout << "Failed to create Window" << std::endl;
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
Nz::WindowSwapchain windowSwapchain(device, window);
|
Nz::WindowSwapchain windowSwapchain(device, window);
|
||||||
|
|
||||||
constexpr float textureSize = 512.f;
|
|
||||||
float margin = (windowSize.y - textureSize) * 0.5f;
|
|
||||||
|
|
||||||
nzsl::FieldOffsets viewerLayout(nzsl::StructLayout::Std140);
|
nzsl::FieldOffsets viewerLayout(nzsl::StructLayout::Std140);
|
||||||
std::size_t projectionMatrixOffset = viewerLayout.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true);
|
std::size_t projectionMatrixOffset = viewerLayout.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true);
|
||||||
|
|
||||||
|
|
@ -228,6 +267,7 @@ int main()
|
||||||
auto& allocation = uploadPool.Allocate(sceneBufferSize);
|
auto& allocation = uploadPool.Allocate(sceneBufferSize);
|
||||||
Nz::AccessByOffset<float&>(allocation.mappedPtr, deltaTimeOffset) = deltaTime;
|
Nz::AccessByOffset<float&>(allocation.mappedPtr, deltaTimeOffset) = deltaTime;
|
||||||
Nz::AccessByOffset<Nz::Vector2f&>(allocation.mappedPtr, mousePosOffset) = Nz::Vector2f(mousePos.x, windowSize.y - mousePos.y);
|
Nz::AccessByOffset<Nz::Vector2f&>(allocation.mappedPtr, mousePosOffset) = Nz::Vector2f(mousePos.x, windowSize.y - mousePos.y);
|
||||||
|
Nz::AccessByOffset<float&>(allocation.mappedPtr, effectRadiusOffset) = (Nz::Mouse::IsButtonPressed(Nz::Mouse::Button::Left)) ? 10000.f : 100.f;
|
||||||
|
|
||||||
builder.PreTransferBarrier();
|
builder.PreTransferBarrier();
|
||||||
builder.CopyBuffer(allocation, sceneDataBuffer.get());
|
builder.CopyBuffer(allocation, sceneDataBuffer.get());
|
||||||
|
|
@ -239,7 +279,7 @@ int main()
|
||||||
{
|
{
|
||||||
builder.BindComputePipeline(*computePipeline);
|
builder.BindComputePipeline(*computePipeline);
|
||||||
builder.BindComputeShaderBinding(0, *computeBinding);
|
builder.BindComputeShaderBinding(0, *computeBinding);
|
||||||
builder.Dispatch(maxParticleCount / 64 + 1, 1, 1);
|
builder.Dispatch(particleCount / 64 + 1, 1, 1);
|
||||||
}
|
}
|
||||||
builder.EndDebugRegion();
|
builder.EndDebugRegion();
|
||||||
|
|
||||||
|
|
@ -261,7 +301,7 @@ int main()
|
||||||
|
|
||||||
builder.BindVertexBuffer(0, *spriteRenderData1.vertexBuffer);
|
builder.BindVertexBuffer(0, *spriteRenderData1.vertexBuffer);
|
||||||
builder.BindRenderShaderBinding(0, *spriteRenderData1.shaderBinding);
|
builder.BindRenderShaderBinding(0, *spriteRenderData1.shaderBinding);
|
||||||
builder.Draw(4, initialParticleCount);
|
builder.Draw(4, particleCount);
|
||||||
}
|
}
|
||||||
builder.EndRenderPass();
|
builder.EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
@ -325,6 +365,7 @@ struct Particle
|
||||||
{
|
{
|
||||||
color: vec3[f32],
|
color: vec3[f32],
|
||||||
position: vec2[f32],
|
position: vec2[f32],
|
||||||
|
target_position: vec2[f32],
|
||||||
velocity: vec2[f32]
|
velocity: vec2[f32]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue