title: How to draw OpenGL pixels with the GPU
body: <p><b>Brief:</b><br/>
  I'm making a Powder Toy that makes use of Parallel Processing to do the game physics, its dealing with a 500 x 500 area of powder. The game does mostly everything with the particles on the GPU but it uses the CPU to render the particles (decreases speed by a lot). How would I render the particles on the GPU instead of the CPU? I'm mostly keeping my particle data on the GPU because most of the operations happen there, and cudaMemcpy is quite slow, making by project uncontrollably lag when its on host memory.
  <br/><br/><b>Code:</b><br/>
  Here's my display function</p>
  
  <pre><code>void display()
  {
      // Measure performance
      mainloopMeasurePerformanceStart(1);
  
      // Clear the screen
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
  
      // Copy particle data to render
      cudaMemcpy(&amp;particles, d_particles, sizeof(particles), cudaMemcpyDeviceToHost);
  
      // Loop over the sand particles
      for(int i=0;i&lt;250000;i++)
      {
          // Is the sand particle alive
          if(particles[i].alive)
          {
              // Get the position
              int pos[2];
              id_to_pos(i,pos);
  
              // Draw the pixel
              glColor3f(particles[i].color[0],particles[i].color[1],particles[i].color[2]);
              glBegin(GL_QUADS);
                  glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5)*2);
                  glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5)*2);
                  glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5+0.002)*2);
                  glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5+0.002)*2);
              glEnd();
          }
      }
  
      // Get the mouse position
      int m_posX, m_posY;
      mousePos(&amp;m_posX, &amp;m_posY);
  
      // Draw the cursor
      glColor3f(1.0f, 1.0f, 1.0f);
      for(int i=0;i&lt;360;i++)
      {
          // Calculate the position
          double pos[2];
          pos[0] = sin(2*PI/360*i)*cursor_radius+m_posX;
          pos[1] = cos(2*PI/360*i)*cursor_radius+m_posY;
  
          glBegin(GL_QUADS);
              glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5)*2);
              glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5)*2);
              glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5+0.002)*2);
              glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5+0.002)*2);
          glEnd();
      }
  
      // Swap the front and back frame buffers
      glutSwapBuffers();
  
      // Measure performance
      mainloopMeasurePerformanceEnd();
  }
  </code></pre>
  
  <p>And where the processing for the sand happens:</p>
  
  <pre><code>__global__ void do_sand(
      Sand *particles, bool *mouseStates, unsigned long seed,
      int m_pos_x, int m_pos_y, double cursor_radius
  ){
      // Get the overall ID
      int id = blockIdx.x*100+threadIdx.x;
  
      // Convert the ID to a position
      int pos[2];
      id_to_pos(id,pos);
  
      // Convert the mouse position to an array
      int m_pos[2];
      m_pos[0] = m_pos_x;
      m_pos[1] = m_pos_y;
  
      // Is the sand particle alive
      if(particles[id].alive)
      {
          // Is there sand being cleared and is this particle in range
          if(mouseStates[GLUT_RIGHT_BUTTON] &amp;&amp; distance_between(pos, m_pos) &lt; cursor_radius)
          {
              // Delete this particle
              particles[id].alive = false;
          }
  
          // Do physics
          bool done = false;
          int check;
  
          switch(particles[id].model)
          {
              // Powder
              case 'P':
              {
                  // Is vertical movement valid
                  if(pos[1]-1 &gt;= 0 &amp;&amp; !done)
                  {
                      // Get the ID
                      check = pos_to_id(pos[0], pos[1]-1);
  
                      // Is this space free
                      if(!particles[check].alive)
                      {
                          // Move the particle
                          particles[check] = particles[id];
                          particles[id].alive = false;
                          done = true;
                      }
                  }
  
                  // Randomly pick the sands course
                  int choice;
                  if((seed * id * 5423) % 2 == 0) choice=1;
                  else choice=-1;
  
                  // Check left movement
                  if(pos[0]-choice &lt; 500 &amp;&amp; pos[0]-choice &gt;= 0 &amp;&amp; pos[1]-1 &gt;= 0 &amp;&amp; !done)
                  {
                      // Get the ID
                      check = pos_to_id(pos[0]-choice,pos[1]-1);
  
                      // Is this space free
                      if(
                          !particles[check].alive &amp;&amp;
                          !particles[pos_to_id(pos[0]-choice,pos[1])].alive &amp;&amp;
                          !(
                              particles[pos_to_id(pos[0]-choice*2,pos[1])].alive &amp;&amp;
                              particles[pos_to_id(pos[0]-choice*2,pos[1]-1)].alive
                          )
                      ){
                          // Move the particle
                          particles[check] = particles[id];
                          particles[id].alive = false;
                          done = true;
                      }
                  }
  
                  // Check right movement
                  if(pos[0]+choice &lt; 500 &amp;&amp; pos[0]+choice &gt;= 0 &amp;&amp; pos[1]-1 &gt;= 0 &amp;&amp; !done)
                  {
                      // Get the ID
                      check = pos_to_id(pos[0]+choice,pos[1]-1);
  
                      // Is this space free
                      if(
                          !particles[check].alive &amp;&amp;
                          !particles[pos_to_id(pos[0]+choice,pos[1])].alive &amp;&amp;
                          !(
                              particles[pos_to_id(pos[0]+choice*2,pos[1])].alive &amp;&amp;
                              particles[pos_to_id(pos[0]+choice*2,pos[1]-1)].alive
                          )
                      ){
                          // Move the particle
                          particles[check] = particles[id];
                          particles[id].alive = false;
                          done = true;
                      }
                  }
              }
  
              // Fluid
              case 'F':
              {
  
              }
          }
      }
  
      // Is there sand being added and is this particle in range
      else if(mouseStates[GLUT_LEFT_BUTTON] &amp;&amp; distance_between(pos, m_pos) &lt; cursor_radius)
      {
          // Make this particle
          particles[id].alive = true;
          particles[id].color[0] = 0.0f;
          particles[id].color[1] = 0.0f;
          particles[id].color[2] = 0.6f;
          particles[id].model = 'P';
      }
  }
  </code></pre>