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]
|
||||
(
|
||||
(pow(1.0 - length(uv), 10.0)).xxx,
|
||||
(pow(1.0 - length(uv), 14.0)).xxx,
|
||||
1.0
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ struct Particle
|
|||
{
|
||||
color: vec3[f32],
|
||||
position: vec2[f32],
|
||||
targetPosition: vec2[f32],
|
||||
velocity: vec2[f32]
|
||||
}
|
||||
|
||||
|
|
@ -20,7 +21,8 @@ struct ParticleData
|
|||
struct SceneData
|
||||
{
|
||||
deltaTime: f32,
|
||||
mousePos: vec2[f32]
|
||||
mousePos: vec2[f32],
|
||||
effectRadius: f32
|
||||
}
|
||||
|
||||
external
|
||||
|
|
@ -42,12 +44,20 @@ fn main(input: Input)
|
|||
if (index >= data.particle_count)
|
||||
return;
|
||||
|
||||
let damping = pow(0.5, sceneData.deltaTime);
|
||||
|
||||
// Gets pushed by the cursor
|
||||
let attract_pos = sceneData.mousePos;
|
||||
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;
|
||||
|
||||
// Move particle
|
||||
data.particles[index].position += data.particles[index].velocity * sceneData.deltaTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,36 +60,77 @@ int main()
|
|||
nzsl::FieldOffsets particleLayout(nzsl::StructLayout::Std140);
|
||||
std::size_t particleColorOffset = particleLayout.AddField(nzsl::StructFieldType::Float3);
|
||||
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 particleSize = particleLayout.GetAlignedSize();
|
||||
|
||||
constexpr std::size_t maxParticleCount = 10'000;
|
||||
constexpr std::size_t initialParticleCount = maxParticleCount;
|
||||
std::shared_ptr<Nz::Image> logo = Nz::Image::LoadFromFile(resourceDir / "Logo.png");
|
||||
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);
|
||||
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::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::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> posYDis(0.f, float(windowSize.y));
|
||||
std::uniform_real_distribution<float> velDis(-20.f, 20.f);
|
||||
std::uniform_real_distribution<float> posXDis(-float(windowSize.x), windowSize.x * 2.f);
|
||||
std::uniform_real_distribution<float> posYDis(-float(windowSize.y), windowSize.y * 2.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));
|
||||
//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);
|
||||
Nz::AccessByOffset<Nz::Vector2f&>(particleBufferInitialData.data(), baseOffset + particlePosOffset) = Nz::Vector2f(posXDis(rand), posYDis(rand));
|
||||
Nz::AccessByOffset<Nz::Vector2f&>(particleBufferInitialData.data(), baseOffset + particleVelOffset) = Nz::Vector2f(velDis(rand), velDis(rand));
|
||||
particlePosPtr[i] = Nz::Vector2f(posXDis(rand), posYDis(rand));
|
||||
particleTargetPosPtr[i] = posScale * Nz::Vector2f(pos) + posOffset;
|
||||
particleColorPtr[i] = Nz::Vector3f(color.r, color.g, color.b) * color.a;
|
||||
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());
|
||||
|
|
@ -97,6 +138,7 @@ int main()
|
|||
nzsl::FieldOffsets sceneBufferLayout(nzsl::StructLayout::Std140);
|
||||
std::size_t deltaTimeOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float1);
|
||||
std::size_t mousePosOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float2);
|
||||
std::size_t effectRadiusOffset = sceneBufferLayout.AddField(nzsl::StructFieldType::Float1);
|
||||
|
||||
std::size_t sceneBufferSize = sceneBufferLayout.GetAlignedSize();
|
||||
|
||||
|
|
@ -157,18 +199,15 @@ int main()
|
|||
hasNewPipeline = true;
|
||||
});
|
||||
|
||||
std::string windowTitle = "Compute test";
|
||||
std::string windowTitle = "Particle test (" + std::to_string(particleCount) + " particles)";
|
||||
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::abort();
|
||||
}
|
||||
Nz::WindowSwapchain windowSwapchain(device, window);
|
||||
|
||||
constexpr float textureSize = 512.f;
|
||||
float margin = (windowSize.y - textureSize) * 0.5f;
|
||||
|
||||
nzsl::FieldOffsets viewerLayout(nzsl::StructLayout::Std140);
|
||||
std::size_t projectionMatrixOffset = viewerLayout.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true);
|
||||
|
||||
|
|
@ -228,6 +267,7 @@ int main()
|
|||
auto& allocation = uploadPool.Allocate(sceneBufferSize);
|
||||
Nz::AccessByOffset<float&>(allocation.mappedPtr, deltaTimeOffset) = deltaTime;
|
||||
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.CopyBuffer(allocation, sceneDataBuffer.get());
|
||||
|
|
@ -239,7 +279,7 @@ int main()
|
|||
{
|
||||
builder.BindComputePipeline(*computePipeline);
|
||||
builder.BindComputeShaderBinding(0, *computeBinding);
|
||||
builder.Dispatch(maxParticleCount / 64 + 1, 1, 1);
|
||||
builder.Dispatch(particleCount / 64 + 1, 1, 1);
|
||||
}
|
||||
builder.EndDebugRegion();
|
||||
|
||||
|
|
@ -261,7 +301,7 @@ int main()
|
|||
|
||||
builder.BindVertexBuffer(0, *spriteRenderData1.vertexBuffer);
|
||||
builder.BindRenderShaderBinding(0, *spriteRenderData1.shaderBinding);
|
||||
builder.Draw(4, initialParticleCount);
|
||||
builder.Draw(4, particleCount);
|
||||
}
|
||||
builder.EndRenderPass();
|
||||
}
|
||||
|
|
@ -325,6 +365,7 @@ struct Particle
|
|||
{
|
||||
color: vec3[f32],
|
||||
position: vec2[f32],
|
||||
target_position: vec2[f32],
|
||||
velocity: vec2[f32]
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue