Add color to MSAOpenCL particles example [SOLVED]

Hi everyone,
I am trying to add color to those nice particles, but it seems I can’t do that. Here’s my code:

void ofApp::draw(){
opencl.finish();

ofFloatColor *colorPointer = &color[0];


//glColor3f(1.0f, 1.0f, 1.0f);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);

opencl.finish();

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, sizeof(ofFloatColor), colorPointer );

glVertexPointer(2, GL_FLOAT, 0, 0);

glDrawArrays(GL_POINTS, 0, NUM_PARTICLES);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

Now, color is a simple array, with NUM_PARTICLES size, of type ofColor filled with random colors:

for(int i=0; i<NUM_PARTICLES; i++) {
    Particle &p = particles[i];
    p.vel.set(0, 0);
    p.mass = ofRandom(0.5, 1);
    color[i].set((ofRandom(1),ofRandom(1),ofRandom(1)));
    particlePos[i].set(ofRandomWidth(), ofRandomHeight());
}

Maybe there is something wrong in my glColorPointer. I’d greatly appreciate any help, thank you!

how was this solved?
S

Update - I almost have this now but I want to update the particle colours at the same time as their positions. This appears to be causing an error; am I missing something?

Approach taken so far is as follows:

  • produce a second vbo object similar to that which stores particle position but that contains float3 items; fill these with random ofFloat colour profiles

  • so in setup():

      opencl.setupFromOpenGL();
    
      // create vbo
      glGenBuffersARB(1, &vbo);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
      glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float2) * NUM_PARTICLES, 0, GL_DYNAMIC_COPY_ARB);
    
      // create cbo
       glGenBuffersARB(1, &cbo);
       glBindBufferARB(GL_ARRAY_BUFFER_ARB, cbo);
       glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float3) * NUM_PARTICLES, 0, GL_DYNAMIC_COPY_ARB);
       glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
    
      // init host and CL buffers
       particles.initBuffer(NUM_PARTICLES);
       particlePos.initFromGLObject(vbo, NUM_PARTICLES);
       particleCos.initFromGLObject(cbo, NUM_PARTICLES);
    
      // init data
       for(int i=0; i<NUM_PARTICLES; i++) {
          Particle &p = particles[i];
          p.vel.set(0, 0);
          p.mass = ofRandom(0.5, 1);
         particleCos[i].set(ofRandom(1),ofRandom(1),ofRandom(1));
         particlePos[i].set(ofRandomWidth(), ofRandomHeight());
      }
    
       particles.writeToDevice();
       particlePos.writeToDevice();
       particleCos.writeToDevice();
    
       opencl.loadProgramFromFile("MSAOpenCL/Particle.cl");
       opencl.loadKernel("updateParticle");
    
       opencl.kernel("updateParticle")->setArg(0, particles);
       opencl.kernel("updateParticle")->setArg(1, particlePos);
       opencl.kernel("updateParticle")->setArg(2, mousePos);
       opencl.kernel("updateParticle")->setArg(3, dimensions);
       opencl.kernel("updateParticle")->setArg(4, particleCos);
    
  • update() remains the same and then, in draw():

      opencl.finish();
    
       glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
       glVertexPointer(2, GL_FLOAT, 0, 0);
       glEnableClientState(GL_VERTEX_ARRAY);
    
       glBindBufferARB(GL_ARRAY_BUFFER_ARB, cbo);
       glColorPointer(3, GL_FLOAT, 0, 0);
       glEnableClientState(GL_COLOR_ARRAY);
    
       glPointSize(1);
       glDrawArrays(GL_POINTS, 0, NUM_PARTICLES);
    
       glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
       glDisableClientState(GL_VERTEX_ARRAY);
       glDisableClientState(GL_COLOR_ARRAY);
       opencl.finish();
    
  • finally, in particle.cl file I add an extra global argument to the function ‘updateParticle’, giving:

       __kernel void updateParticle(__global Particle* particles, __global float2* posBuffer, const float2 mousePos, const float2 dimensions, __global float3* cosBuffer){
        int id = get_global_id(0);
       __global Particle *p = &particles[id];
    
        float2 diff = mousePos - posBuffer[id];
        float invDistSQ = 1.0f / dot(diff, diff);
        diff *= MOUSE_FORCE * invDistSQ;
    
        p->vel += (dimensions*0.5f - posBuffer[id]) * CENTER_FORCE - diff* p->mass;
        float speed2 = dot(p->vel, p->vel);
        if(speed2<MIN_SPEED) posBuffer[id] = mousePos + diff * (1.0f + p->mass);
        posBuffer[id] += p->vel;
        p->vel *= DAMP;
    
        //cosBuffer[id]+=1;
       }
    

The above runs perfectly, with random colours assigned to each particle, until I comment in the line: cosBuffer[id]+=1; At this point it throws a crash.

I was assuming that adding this line would allow me to manipulate and update individual particle colours via the second vbo object. What am I doing wrong? I recon it must be a pretty simple solution, but can’t figure it out. Can anyone help?

S

1 Like

well, here’s the point where it is pausing up, in the MSAOpenCLKernel.cpp:

cl_int OpenCLKernel::unbindOpenGLInterOp(){
	cl_int err = CL_SUCCESS;
	if (!mOpenGLInteropArguments.empty()){
		// we have to release our opengl interop objects, if we acquired them earlier.
		err = clEnqueueReleaseGLObjects(pOpenCL->getQueue(), mOpenGLInteropArguments.size() , mOpenGLInteropArguments.data(), 0, NULL, NULL);
	}
	return err;
}

I don’t have much of a clue as to why, other than it looks like a binding issue. Pretty stumped…

In my experience openCL doesn’t deal really well with float3 variables. Instead of that you should use a float4 with some 0.0 number in the fourth value. Anyway I used ofFloatColor as a float4 because it actually has 4 values, the fourth being the alpha channel.
In the openCL kernel, why would you sum 1 to your float color? It is in the range 0. 1. so a +1 would go out of range.

ARG, indeed it does look like it was a result of the difference between float3 and float4. That’s two days of my life I’ll never get back!
(the a+1 was just me being clumsy, and of no consequence)

Good to know though, many thanks for pointing that one out.

S

1 Like