C++ 使用glReadPixels(…)读取帧缓冲区时精度低

C++ 使用glReadPixels(…)读取帧缓冲区时精度低,c++,opengl,framebuffer,glreadpixels,C++,Opengl,Framebuffer,Glreadpixels,我想利用OpenGL对离散标量贴图进行采样。标量映射基于每个三角形给出,即每个三角形一个标量 首先,我用平面着色和对应于标量贴图的颜色值绘制每个三角形。然后,我使用glReadPixels(…)从帧缓冲区读取采样的标量映射 我的问题如下: 由于某些原因,我只能恢复高达1e-2的颜色值!我不知道为什么这个精度这么差。我正在写入和读取帧缓冲区中的浮动 // Set viewport to desired map size glViewport(0,0,imageWidth, imageHeight)

我想利用OpenGL对离散标量贴图进行采样。标量映射基于每个三角形给出,即每个三角形一个标量

首先,我用平面着色和对应于标量贴图的颜色值绘制每个三角形。然后,我使用glReadPixels(…)从帧缓冲区读取采样的标量映射

我的问题如下:

由于某些原因,我只能恢复高达1e-2的颜色值!我不知道为什么这个精度这么差。我正在写入和读取帧缓冲区中的浮动

// 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);
有人知道为什么我只能从帧缓冲区恢复如此糟糕的浮点精度吗

下面是一个重要的代码片段,我只需为每个三角形使用一个常量color valuecolorValue。如果将colorValue设置为1e-4,则只能从帧缓冲区恢复零

// 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);
//将视口设置为所需的贴图大小
glViewport(0,0,imageWidth,imageHeight);
glClearColor(0,0,0,1.);//黑色背景
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glDisable(GLU照明);
glMatrixMode(GL_投影);
glLoadIdentity();
gluOrtho2D(-1,1.,-1,1);
glMatrixMode(GLU模型视图);
//绘制标量图
glBegin(GL_三角形);

对于(unsigned int f=0;f而言,写入帧缓冲区或从帧缓冲区读取的内容并不重要,只与帧缓冲区实际存储的内容有关

GL会很高兴地将颜色转换成/转换成一整天的颜色。除非您有浮点帧缓冲区,否则会发生很多不愉快的事情,例如钳制([0.01.0])和缩放到定点值范围(通常为8位)

给定8位无符号标准化颜色缓冲区,可以存储和恢复的最小非零颜色值为~0.00391.0/255.0


创建浮点默认帧缓冲区的过程是特定于平台/框架的。要实现可移植性,最简单的方法实际上是在设置默认帧缓冲区后创建一个带有浮点颜色附件的FBO。
写什么或读什么都无所谓从帧缓冲区,只要它执行帧缓冲区实际存储的内容

// 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);
GL会很高兴地将颜色转换成/转换成一整天的颜色。除非您有浮点帧缓冲区,否则会发生很多不愉快的事情,例如钳制([0.01.0])和缩放到定点值范围(通常为8位)

给定8位无符号标准化颜色缓冲区,可以存储和恢复的最小非零颜色值为~0.00391.0/255.0


创建浮点默认帧缓冲区的过程是特定于平台/框架的。要实现可移植性,最简单的方法实际上是在设置默认帧缓冲区后创建一个带有浮点颜色附件的FBO。如何创建GL缓冲区?听起来像是没有创建真正的FP缓冲区。您是如何创建GL缓冲区的?听起来好像您没有创建真正的FP缓冲区。感谢您指出了正确的方向!我对OpenGL非常陌生,所以不知道FBO。发布的答案解决了我的问题。非常感谢!感谢您指出了正确的方向!我对OpenGL非常陌生,所以我这么做了不知道FBO的情况。发布的答案解决了我的问题。非常感谢!
// 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);