前面记录了一下存在的问题和大致的解决方法
OpenGL:关于获取渲染结果的深度信息的问题_六月的翅膀的博客-优快云博客
下面就验证一下
先定义一个指针变量和一个成员函数
GLfloat* depth_value = NULL;//保存缓冲区里的深度信息
void updateDepthValue();
成员函数具体为
void GlWidget::updateDepthValue()
{
int WINDOW_WIDTH = (int)_width;
int WINDOW_HEIGHT = (int)_height;
glReadPixels(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,GL_DEPTH_COMPONENT, GL_FLOAT, depth_value);
}
注意,这里获得的深度值是0-1之间的(我查看的结果是非常接近1,大都在0.998以上,其实就是非线性变换的结果),就是Fdepth
这里关于深度值有个非线性变换,上图。这个非线性变换的曲线可以画出来看一下(这个在线画图的工具挺好用:数字王国 - 数学工具)
大致形状就是这种,x轴越小表示具体观察者越近,相应的映射的范围就越大(即x轴正方向所有点全部映射到y轴0-1之间,而x轴0-2这段区间就占了y轴的90%左右了),这样变换的目的是越远的物体,需要的精度就可以越宽松一点。
其中near和far在我这里是自定义写入的
near=0.01,far=10,将Fdepth、near和far代入,就可以求得Z,这个Z就是在near-far这个区间。
在paintGL()函数结尾调用updateDepthValue
void GlWidget::paintGL()
{
...//
...//渲染部分
updateDepthValue();
}
然后通过一个按钮连接槽函数,每次按钮按下时,查看当前深度信息
for (int y = WINDOW_HEIGHT-1; y >=0 ; y--)
{
for (int x = 0; x < WINDOW_WIDTH; x++)
{
GLfloat iii=depth_value[(y*WINDOW_WIDTH + x)];
uchar RGB_value = 1/(-99.9*iii+100);
if(y==WINDOW_HEIGHT/2)
qDebug()<<RGB_value ;
//蓝色
tmpBIT[0] = RGB_value;
//绿色
tmpBIT[1] = RGB_value;
//红色
tmpBIT[2] = RGB_value;
tmpBIT[3] = 255;//不起作用
tmpBIT += 4;
}
}
输出的结果如下:10代表距离无穷远
然后可以把结果再次归一化到255之间,将深度信息保存为图像
void GlWidget::saveFrameBuff_2(const char *fileName)
{
int WINDOW_WIDTH = (int)_width;
int WINDOW_HEIGHT = (int)_height;
QImage* img=new QImage(WINDOW_WIDTH,WINDOW_HEIGHT,QImage::Format_ARGB32);
uchar* tmpBIT = img->bits();
for (int y = WINDOW_HEIGHT-1; y >=0 ; y--)
{
for (int x = 0; x < WINDOW_WIDTH; x++)
{
GLfloat iii=depth_value[(y*WINDOW_WIDTH + x)];
uchar RGB_value = 1/(-99.9*iii+100)/10*255;
if(y==WINDOW_HEIGHT/2)
qDebug()<<RGB_value;
//蓝色
tmpBIT[0] = RGB_value;
//绿色
tmpBIT[1] = RGB_value;
//红色
tmpBIT[2] = RGB_value;
tmpBIT[3] = 255;//不起作用
tmpBIT += 4;
}
}
img->save("a.png");
}
渲染图
深度图
相关文章:
OpenGL投影矩阵(Projection Matrix)构造方法 - 知乎
OpenGL中的深度值winz与相机空间z值的关系推导_lysc_forever的博客-优快云博客_opengl深度值与z值
OpenGL_深度测试_线性深度值_会敲code的猫的博客-优快云博客_opengl深度值
opengl 投影矩阵转换获取得到near far,视场角等方法_XR风云的博客-优快云博客