Particle simulation - number of fragments(pixels) not equal to the window size.

Hi,

What is the relation between the window size and the number of fragments being computed? I am writing a pixel shader for particle simulation and I observe that the window size needs to be adjusted depending on the number of particles in the simulation. Suppose, I am simulating it for 500 particles (each particle represents a fragment and the complete list of particle array is mapped onto a texture) and my window size initially is 128x128. This window size should be sufficient to simulate the process (right) but when I do the simulation, my values are all zeros. However, when I change my window size to some other (bigger size), I find correct simulation results.

I am attaching the snippet of my source code. I create my viewport to the size of my output buffer (FBO) and then I draw a quad onto this FBO. I checked my code again and failed to find anything wrong. I would really appreciate if someone can take a peek and see if I did commit some mistake and figure why the number of fragments equal the window size.

#################################################
void InitializeGLUT (int* argc, string* argv)
{
glutInit (argc, argv);
glutInitWindowSize (XSCREEN, YSCREEN);
glutInitDisplayMode (GLUT_RGBA | GLUT_ALPHA);
glutCreateWindow (“Application”);
glewInit ();
readbuffer = 0;
writebuffer = 1;
readframebuffer = GL_COLOR_ATTACHMENT0_EXT;
writeframebuffer = GL_COLOR_ATTACHMENT1_EXT;
} // InitializeGLUT

void MapTextures (void)
{
glGenTextures (1, &TextureA);
glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureA);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_RGBA32_NV, CMAX, RMAX, 0, GL_RGBA, GL_FLOAT, &A);

glGenTextures (1, &TextureB);
glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureB);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_RGBA32_NV, CMAX, RMAX, 0, GL_RGBA, GL_FLOAT, &B);
} // MapTextures

void CreateRenderToTextureObjects (void)
{
glGenFramebuffersEXT (1, &FrameBuffer);
FrameBufferStatus ();
glGenTextures (2, TextureC);

glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureC[readbuffer]);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_RGBA32_NV, CMAX, RMAX, 0, GL_RGBA, GL_FLOAT, &C);

glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureC[writebuffer]);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_RGBA32_NV, CMAX, RMAX, 0, GL_RGBA, GL_FLOAT, NULL);
} // CreateRenderToTextureObjects

void Display (void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glClearDepth (1.0f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, progID);
glEnable (GL_FRAGMENT_PROGRAM_ARB);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, FrameBuffer);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, readframebuffer, GL_TEXTURE_RECTANGLE_NV, TextureC[readbuffer], 0);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, writeframebuffer, GL_TEXTURE_RECTANGLE_NV, TextureC[writebuffer], 0);
glDrawBuffer (writeframebuffer);
DrawQuad ();
ReadTexture ();
FrameBufferStatus ();
GLError ();
glDisable (GL_FRAGMENT_PROGRAM_ARB);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
SwapFrameBufferAttachments ();
} // Display

void DrawQuad (void)
{
glViewport (0, 0, XSCREEN, YSCREEN);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, XSCREEN, 0, YSCREEN, 0, 1);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

glActiveTexture (GL_TEXTURE0_ARB);
glEnable (GL_TEXTURE_RECTANGLE_NV);
glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureA);

glActiveTexture (GL_TEXTURE1_ARB);
glEnable (GL_TEXTURE_RECTANGLE_NV);
glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureB);

glActiveTexture (GL_TEXTURE2_ARB);
glEnable (GL_TEXTURE_RECTANGLE_NV);
glBindTexture (GL_TEXTURE_RECTANGLE_NV, TextureC[readbuffer]);

glBegin (GL_QUADS);
glColor4f (0.5, 0.5, 0.5, 0);

glMultiTexCoord2f (GL_TEXTURE0_ARB, 0.0, 0.0);
glMultiTexCoord2f (GL_TEXTURE1_ARB, 0.0, 0.0);
glMultiTexCoord2f (GL_TEXTURE2_ARB, 0.0, 0.0);
glVertex2f (0.0, 0.0);

glMultiTexCoord2f (GL_TEXTURE0_ARB, CMAX, 0.0);
glMultiTexCoord2f (GL_TEXTURE1_ARB, CMAX, 0.0);
glMultiTexCoord2f (GL_TEXTURE2_ARB, CMAX, 0.0);
glVertex2f (XSCREEN, 0.0);

glMultiTexCoord2f (GL_TEXTURE0_ARB, CMAX, RMAX);
glMultiTexCoord2f (GL_TEXTURE1_ARB, CMAX, RMAX);
glMultiTexCoord2f (GL_TEXTURE2_ARB, CMAX, RMAX);
glVertex2f (XSCREEN, YSCREEN);

glMultiTexCoord2f (GL_TEXTURE0_ARB, 0.0, RMAX);
glMultiTexCoord2f (GL_TEXTURE1_ARB, 0.0, RMAX);
glMultiTexCoord2f (GL_TEXTURE2_ARB, 0.0, RMAX);
glVertex2f (0.0, YSCREEN);

glEnd ();
glFinish ();
} // DrawQad
#################################################

Also, XSCREEN = CMAX & YSCREEN = RMAX.

Any help is highly appreciated.

Thanks.

  • FMS

You are rendering exactly on the zNear plane.
Try glOrtho (0, XSCREEN, 0, YSCREEN, -1, 1);
Are you sure you wanted GL_CLAMP and not GL_CLAMP_TO_EDGE?
You’re not specifying GLUT_DEPTH but clearing the depth buffer. You don’t use depth, because you didn’t enable depth tests.
Fragment programs don’t need texture units to be enabled they use texture image units which are implicitly enabled by the fragment program.
Texture coordinates are identical in all three texcoord attributes.
With fragment programs you don’t need a 1-to-1 TexCoord to texture unit correspondence like in the fixed function pipeline. One TexCoord attribute will be enough, if you use only that in the shader.
Put the color before the begin. It’s constant for all four vertices.

Hi,

I have been investigating for the last several days as to why this particular thing is happening. Let me brief you all and hope someone could provide some clue as where the bug could lie.

I am implementing particle simulation on the GPU. I initialize the FBO size as 128x128. Thus, this FBO is capable of simulating 16384 particles. When I use glReadPixels() to read back to make sure whether particles are properly stored on the GPU, I find that the particles are properly stored. Now I run the simulation for 425 particles and I find that most of the results are black or garbage. But some results are correct. So I suspect that it could be the fragment program that may have some kind of logic problem. I throughly trace my code and really could not find any logic bugs. Then I increase the window size (FBO size) to 256x256 and I get all correct values. None of the values is garbage. So this further clarifies that it is not a logic problem with my shader.

This whole thing really doesn’t make any sense to me and I am desperate for the answer. I would really appreciate if someone could cite some light on what the problem and why it is behaving this way.

Any help is appreciated.

Thanks.