The base program used here is the NVIDIA's oclParticles example provided in the NVIDIA_GPU_Computing_SDK package.
Here I made some changes on the boundaries of collisions, so it looks that there is a hole at the bottom of the box and the particles are coming out of the box.
All collisions between the particles are defined as previous, I didn't change that. The hole is a 0.25 length square.
Then, I change the positions of the particles to be at y=0 when they're coming out from the box through the hole. This result into a fountain like simulation.
The bottom of the box.
And the interaction of the fountain particles with a thrown sphere of particles.
I also made a circular hole of radius 0.5. This is how it looks like
As I mentioned before I did this just changing the collision's boundaries in the integration kernel of Particles.cl.
Tuesday, July 27, 2010
Thursday, July 22, 2010
Rendering of particles with random radius
The base program used here is the NVIDIA's oclParticles example provided in the NVIDIA_GPU_Computing_SDK package.
The aim here is to render each particle with a random radius. The interactions and collisions are computed with a constant radius. So, our approach is to create a VBO for the radius and used to render the particles.
First, we created the instance variables for the VBO, CPU and GPU data in the inc/particlesSystem_class.h.
Then, we edited the src/particleSystem_class.cpp. I'm going to show the changes made per method.
_initialize()
getArray()
hdata = m_hRad;
ddata = m_dRad;
vbo = m_radiusVBO;
copyArrayFromDevice(hdata, ddata, vbo, m_numParticles * sizeof(float));
break;
setArray()
unregisterGLBufferObject(m_radiusVBO); glBindBuffer(GL_ARRAY_BUFFER, m_radiusVBO);
glBufferSubData(GL_ARRAY_BUFFER, start * sizeof(float), count * sizeof(float), data);
glBindBuffer(GL_ARRAY_BUFFER, 0); registerGLBufferObject(m_radiusVBO); break;
initGrid()
The aim here is to render each particle with a random radius. The interactions and collisions are computed with a constant radius. So, our approach is to create a VBO for the radius and used to render the particles.
First, we created the instance variables for the VBO, CPU and GPU data in the inc/particlesSystem_class.h.
uint m_radiusVBO;
float *m_hRad;
memHandle_t m_dRad;
float *m_hRad;
memHandle_t m_dRad;
Then, we edited the src/particleSystem_class.cpp. I'm going to show the changes made per method.
_initialize()
- allocate memory for the CPU and GPU data, and create the VBO
m_radiusVBO = createVBO(m_numParticles * sizeof(float);
Note that createVBO() is a method previously defined in this class.
_finalize()
_finalize()
- delete the CPU and GPU data, and the VBO as is did it for the other instance variables
- First we have to add RADIUS to the enumeration ParticleArray in the inc/particleSystem_class.h.
- Then, we implement the case RADIUS. Since the radius data is smaller than the positions and velocities data, we need to do the copyArrayFromDevice on each case.
setArray()
- implement the case RADIUS
initGrid()
- here is where we fill the data with random values, so inside the loop we initialize the CPU data
m_hRad[i] = frand();
reset()
addSphere()
Now, we have to edit the src/shaders.cpp because we need to change the vertex shader, pointRadius now is going to be an attribute instead of an uniform variable. This is because the radius is going to be different for each particle, so every time a particle is going to be render a new value is need to be read.
Since we need to get the info of the positions and the radius from the main.cpp we have to add setRadiusBuffer() to inc/render_particles.cpp to initialize the VBO in the render_particles class with the info obtained from the main.cpp. We set the radius VBO in the main program as did it with the position VBO.
It's time to star rendering the particles, so lets edit the src/render_particles.cpp. So, it can be able to read and render the particles with random radius.
Then, we edit the _drawPoints() method. Basically, we add the following inside the else statement:
GLint r;
if(m_radiusVBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_radiusVBO);
r = glGetAttribLocation(m_radiusVBO, "pointRadius");
glVertexAttribPointer(r, 1, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glEnableVertexAttribArray(r); }
At the end we disable the vertex array.
glDisableVertexAttribArray(r);
And finally, we have to comment out the line that gives the uniform values to the shader, if you not comment this line then you still going to be rendering the particles with the same radius.
//glUniform1f( glGetAttribLocation(m_program, "pointRadius"), m_particleRadius );
Now, you are done and you can render particles with different radius using VBO's and shaders.
- we do the same thing than in initGrid(), we initialize again the data with new random numbers
- at the end of the method we set the array with the new data
setArray(RADIUS, m_hRad, 0, m_numParticles);
addSphere()
- we assign random radius for the particles that are going to be added to the system when we add the big sphere
- then we set the array again
Now, we have to edit the src/shaders.cpp because we need to change the vertex shader, pointRadius now is going to be an attribute instead of an uniform variable. This is because the radius is going to be different for each particle, so every time a particle is going to be render a new value is need to be read.
Since we need to get the info of the positions and the radius from the main.cpp we have to add setRadiusBuffer() to inc/render_particles.cpp to initialize the VBO in the render_particles class with the info obtained from the main.cpp. We set the radius VBO in the main program as did it with the position VBO.
It's time to star rendering the particles, so lets edit the src/render_particles.cpp. So, it can be able to read and render the particles with random radius.
Then, we edit the _drawPoints() method. Basically, we add the following inside the else statement:
GLint r;
if(m_radiusVBO) {
At the end we disable the vertex array.
glDisableVertexAttribArray(r);
And finally, we have to comment out the line that gives the uniform values to the shader, if you not comment this line then you still going to be rendering the particles with the same radius.
//glUniform1f( glGetAttribLocation(m_program, "pointRadius"), m_particleRadius );
Now, you are done and you can render particles with different radius using VBO's and shaders.
Subscribe to:
Posts (Atom)