feat(2): Assignment 2
This commit is contained in:
parent
92881224ea
commit
31cc8f0a84
2 changed files with 123 additions and 1 deletions
|
@ -1,6 +1,9 @@
|
||||||
|
|
||||||
#include "GpuApplication.h"
|
#include "GpuApplication.h"
|
||||||
|
|
||||||
|
#define BOUNDARY 0.9f
|
||||||
|
#define PUSBACK 0.05f
|
||||||
|
|
||||||
GpuParticleSystem::GpuParticleSystem(std::string kernelFile) {
|
GpuParticleSystem::GpuParticleSystem(std::string kernelFile) {
|
||||||
this->kernelFile = kernelFile;
|
this->kernelFile = kernelFile;
|
||||||
srand(0);
|
srand(0);
|
||||||
|
@ -78,6 +81,10 @@ void GpuParticleSystem::InitPosVel() {
|
||||||
// --------------
|
// --------------
|
||||||
// Your code here
|
// Your code here
|
||||||
// Initialize positions and velocities so that the particles start off on the left side of the screen.
|
// Initialize positions and velocities so that the particles start off on the left side of the screen.
|
||||||
|
for (int i = 0; i < nrParticles; i++) {
|
||||||
|
positions[i * 2] = -BOUNDARY + PUSBACK;
|
||||||
|
positions[i * 2 + 1] = -BOUNDARY + PUSBACK + (2 * BOUNDARY - 2 * PUSBACK) * i / nrParticles;
|
||||||
|
}
|
||||||
// --------------
|
// --------------
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +95,16 @@ void GpuParticleSystem::Run() {
|
||||||
// --------------
|
// --------------
|
||||||
// Your code here
|
// Your code here
|
||||||
// Setup OpenCL so that the 'updateParticles' kernel can be executed for every frame in the loop below
|
// Setup OpenCL so that the 'updateParticles' kernel can be executed for every frame in the loop below
|
||||||
|
cl::Buffer positions_device(context, CL_MEM_READ_WRITE, sizeof(float) * nrParticles * 2);
|
||||||
|
cl::Buffer velocities_device(context, CL_MEM_READ_WRITE, sizeof(float) * nrParticles * 2);
|
||||||
|
|
||||||
|
cl::KernelFunctor<cl::Buffer, cl::Buffer, float, float, float> kernelFunctor(program, "updateParticles");
|
||||||
|
cl::NDRange rangeGlobal(nrParticles);
|
||||||
|
cl::EnqueueArgs enqueArgs(queue, rangeGlobal);
|
||||||
|
|
||||||
|
// Write initial data to the device buffers.
|
||||||
|
queue.enqueueWriteBuffer(positions_device, CL_TRUE, 0, sizeof(float) * nrParticles * 2, positions.data());
|
||||||
|
queue.enqueueWriteBuffer(velocities_device, CL_TRUE, 0, sizeof(float) * nrParticles * 2, velocities.data());
|
||||||
// --------------
|
// --------------
|
||||||
|
|
||||||
// Setup the OpenGL VBOs that will pass the position and velocity of each particle to the vertex shader
|
// Setup the OpenGL VBOs that will pass the position and velocity of each particle to the vertex shader
|
||||||
|
@ -123,6 +140,9 @@ void GpuParticleSystem::Run() {
|
||||||
// --------------
|
// --------------
|
||||||
// Your code here
|
// Your code here
|
||||||
// Update the OpenCL cl::Buffers holding the positions and velocities
|
// Update the OpenCL cl::Buffers holding the positions and velocities
|
||||||
|
printf("Resetting the simulation\n");
|
||||||
|
queue.enqueueWriteBuffer(positions_device, CL_TRUE, 0, sizeof(float) * nrParticles * 2, positions.data());
|
||||||
|
queue.enqueueWriteBuffer(velocities_device, CL_TRUE, 0, sizeof(float) * nrParticles * 2, velocities.data());
|
||||||
// --------------
|
// --------------
|
||||||
reset = false;
|
reset = false;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +151,19 @@ void GpuParticleSystem::Run() {
|
||||||
// Your code here
|
// Your code here
|
||||||
// Update the particles' position and velocities using the OpenCL kernel
|
// Update the particles' position and velocities using the OpenCL kernel
|
||||||
// Make sure that the OpenGL VBOs are updated with these new values (hint: glBindBuffer, glBufferSubData )
|
// Make sure that the OpenGL VBOs are updated with these new values (hint: glBindBuffer, glBufferSubData )
|
||||||
|
|
||||||
|
// Launch the kernel
|
||||||
|
cl::Event event = kernelFunctor(enqueArgs, positions_device, velocities_device, dt, cursorX, cursorY);
|
||||||
|
|
||||||
|
// Read the data from the device buffer into the host vector
|
||||||
|
queue.enqueueReadBuffer(positions_device, CL_TRUE, 0, sizeof(float) * nrParticles * 2, positions.data());
|
||||||
|
queue.enqueueReadBuffer(velocities_device, CL_TRUE, 0, sizeof(float) * nrParticles * 2, velocities.data());
|
||||||
|
|
||||||
|
// Update the OpenGL VBOs
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * nrParticles * 2, positions.data());
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * nrParticles * 2, velocities.data());
|
||||||
// --------------
|
// --------------
|
||||||
|
|
||||||
// render to screen
|
// render to screen
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
void kernel updateParticles(global float* positions, global float* velocities, float dt, float cursorX, float cursorY) {
|
void kernel updateParticles(global float* positions, global float* velocities, float dt, float cursorX, float cursorY) {
|
||||||
|
|
||||||
// feel free to play with these values
|
// feel free to play with these values
|
||||||
float particleRepulsionRadius = 0.1f;
|
float particleRepulsionRadius = 0.1f;
|
||||||
float particleRepulsionStrength = 10.0f;
|
float particleRepulsionStrength = 10.0f;
|
||||||
|
@ -14,4 +14,93 @@ void kernel updateParticles(global float* positions, global float* velocities, f
|
||||||
float damping = 0.96f;
|
float damping = 0.96f;
|
||||||
|
|
||||||
// Your code here
|
// Your code here
|
||||||
|
const float boundary = 0.9f;
|
||||||
|
const float pushback = 0.05f;
|
||||||
|
const float boundaryScale = 1 / (boundaryRepulsionRadius * boundaryRepulsionRadius) * boundaryRepulsionStrength;
|
||||||
|
const float particleScale = 1/ particleRepulsionRadius * particleRepulsionStrength;
|
||||||
|
|
||||||
|
/* 1. Get the index of the current thread, and thus the indices of the current particle in
|
||||||
|
positions and velocities arrays. */
|
||||||
|
const int particleId = get_global_id(0);
|
||||||
|
const int x = particleId * 2;
|
||||||
|
const int y = particleId * 2 + 1;
|
||||||
|
|
||||||
|
/* 4. The particle should be affected by gravity. Use g = 9.8 m/s^2. */
|
||||||
|
velocities[y] -= 9.8f * dt;
|
||||||
|
|
||||||
|
/* 5. Several repulsion forces should work on the particle. Note however, that force = m * a,
|
||||||
|
but we neglect mass here, so instead of applying N forces on the particle, we apply N
|
||||||
|
acceleration vectors, which, when all summed up change the velocities (using dt). */
|
||||||
|
/* 5.1. The particle should stay within the boundary box. */
|
||||||
|
// When a particle crosses a boundary, it should be teleported back to the correct side of the
|
||||||
|
// boundary, and the velocity along this axis should be reset to 0.
|
||||||
|
if (positions[x] < -boundary) {
|
||||||
|
positions[x] = -boundary + pushback;
|
||||||
|
velocities[x] = 0;
|
||||||
|
} else if (positions[x] > boundary) {
|
||||||
|
positions[x] = boundary - pushback;
|
||||||
|
velocities[x] = 0;
|
||||||
|
}
|
||||||
|
if (positions[y] < -boundary) {
|
||||||
|
positions[y] = -boundary + pushback;
|
||||||
|
velocities[y] = 0;
|
||||||
|
} else if (positions[y] > boundary) {
|
||||||
|
positions[y] = boundary - pushback;
|
||||||
|
velocities[y] = 0;
|
||||||
|
}
|
||||||
|
// Secondly, if a particle is within boundaryRepulsionRadius of a boundary, a repulsion force
|
||||||
|
// should be added, pointed away from the boundary. The acceleration should increase according
|
||||||
|
// to a parabole. (f(x) = x^2)
|
||||||
|
if (positions[x] < -boundary + boundaryRepulsionRadius) {
|
||||||
|
float pos = -boundary + boundaryRepulsionRadius - positions[x];
|
||||||
|
velocities[x] += boundaryScale * pos * pos * dt;
|
||||||
|
} else if (positions[x] > boundary - boundaryRepulsionRadius) {
|
||||||
|
float pos = positions[x] - boundary + boundaryRepulsionRadius;
|
||||||
|
velocities[x] -= boundaryScale * pos * pos * dt;
|
||||||
|
}
|
||||||
|
if (positions[y] < -boundary + boundaryRepulsionRadius) {
|
||||||
|
float pos = -boundary + boundaryRepulsionRadius - positions[y];
|
||||||
|
velocities[y] += boundaryScale * pos * pos * dt;
|
||||||
|
} else if (positions[y] > boundary - boundaryRepulsionRadius) {
|
||||||
|
float pos = positions[y] - boundary + boundaryRepulsionRadius;
|
||||||
|
velocities[y] -= boundaryScale * pos * pos * dt;
|
||||||
|
}
|
||||||
|
/* 5.2. The particle should be repelled from other particles within repulsionRadius. Similarly
|
||||||
|
to the previous point, you can use repulsionRadius and repulsionStrength. Instead of a
|
||||||
|
parabole, you can simply make the norm of the acceleration vector increase linearly
|
||||||
|
with closeness to the other particle. */
|
||||||
|
for (int i = 0; i < get_global_size(0); i++) {
|
||||||
|
if (i == particleId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
float dx = positions[x] - positions[i * 2];
|
||||||
|
float dy = positions[y] - positions[i * 2 + 1];
|
||||||
|
float dist = sqrt(dx * dx + dy * dy);
|
||||||
|
if (dist < particleRepulsionRadius) {
|
||||||
|
float scale = particleScale * (particleRepulsionRadius - dist) / dist;
|
||||||
|
velocities[x] += scale * dx * dt;
|
||||||
|
velocities[y] += scale * dy * dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 5.3. The particle should be repelled from the cursor. You can reuse boundaryRepulsionRadius
|
||||||
|
and boundaryRepulsionStrength. */
|
||||||
|
float dx = positions[x] - cursorX;
|
||||||
|
float dy = positions[y] - cursorY;
|
||||||
|
float dist = sqrt(dx * dx + dy * dy);
|
||||||
|
if (dist < boundaryRepulsionRadius) {
|
||||||
|
float scale = boundaryScale * (boundaryRepulsionRadius - dist) / dist;
|
||||||
|
velocities[x] += scale * dx * dt;
|
||||||
|
velocities[y] += scale * dy * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3. Just before this, the velocity should be dampened as follows: */
|
||||||
|
velocities[x] *= damping;
|
||||||
|
velocities[y] *= damping;
|
||||||
|
|
||||||
|
/* 2. At the end of this function, the position of the particle should be updated using its
|
||||||
|
velocity and dt (= the duration of 1 frame, in seconds). Hopefully you still remember how
|
||||||
|
to update a position based on the velocity, and the velocity based on the acceleration,
|
||||||
|
and a small timestep (dt). */
|
||||||
|
positions[x] += velocities[x] * dt;
|
||||||
|
positions[y] += velocities[y] * dt;
|
||||||
}
|
}
|
Reference in a new issue