2

I want to leverage OpenGL to sample a discrete scalar map. The scalar map is given on per-triangle basis, i.e. one scalar per triangle.

First, I draw each triangle with flat shading and a color value corresponding to the scalar map. Then, I read the sampled scalar map from the framebuffer using glReadPixels(...).

My problem is as follows:

For some reason I can only recover color values up to 1e-2! I have no clue why this precision is so bad. I'm writing and reading floats from the framebuffer.

Does anyone know why I can recover only such a bad floating point precision from the framebuffer?

Here is the important code snippet, where I simply use a constant color value colorValue for each triangle. If I set colorValue e.g. to 1e-4, I can only recover zeros from the framebuffer.

// Set viewport to desired map size
glViewport(0,0,imageWidth, imageHeight);
glClearColor(0.,0.,0.,1.); // Black background
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glDisable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1,1.,-1,1);
glMatrixMode(GL_MODELVIEW);

// Draw scalar map
glBegin(GL_TRIANGLES);
for (unsigned int f=0; f<F.rows(); ++f)
 {
  val = colorVal;
  glColor3f(val, val, val);

  glVertex3f(...);
  glVertex3f(...);
  glVertex3f(...);
}
glEnd();
glFlush();
glFinish();

GLfloat* fbuffer = new GLfloat[imageWidth*imageHeight];
glReadPixels(0,0,imageWidth,imageHeight,GL_RED,GL_FLOAT,fbuffer);
user1086105
  • 247
  • 4
  • 11

1 Answers1

4

It does not matter what you are writing to or reading from the framebuffer, so much as it does what the framebuffer actually stores.

GL will happily convert colors to/from unsigned normalized all day long. Unless you have a floating-point framebuffer, lots of unpleasant things happen such as clamping ([0.0,1.0]) and scaling into the range of fixed-point values (8-bit usually).

Given an 8-bit unsigned normalized colorbuffer, the smallest non-zero color value you can store and recover is ~0.0039 (1.0/255.0).

The process of creating a floating-point default framebuffer is platform/framework specific. To do what you want portably, the easiest thing is actually to draw into an FBO with a floating-point color attachment that you create after you setup the default framebuffer.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • Thanks for pointing in the correct direction! I'm quite new to OpenGL so I did not know about FBOs. The answer posted [here](http://stackoverflow.com/questions/10950743/low-precision-and-clamping-when-writing-to-floating-point-fbo) solved my problem. Thanks a lot! – user1086105 May 20 '14 at 11:59