对于一个应用程序,我需要创建一个网格的深度图像。基本上我想要一个图像,其中每个像素都表示相机中心和交点之间的距离。我选择使用OpenGL来完成这项任务,以便大部分计算可以在GPU上完成,而不是在CPU上完成。从碎片生成器返回花车
这是我对顶点着色器的代码。它计算交点的实际坐标,并将坐标存储在varying vec4
中,以便我可以在分片着色器中访问它。
varying vec4 verpos;
void main(void)
{
gl_Position = ftransform();
verpos = gl_ModelViewMatrix*gl_Vertex;
}
这里是片段着色器的代码。在片段着色器中,我使用这些坐标来计算使用毕达哥拉斯到原点(0,0,0)的eulidean距离。要访问CPU的计算值,我的计划是使用gl_FragColor
存储的距离为颜色,并使用glReadPixels(0, 0, width, height, GL_RED, GL_FLOAT, &distances[0]);
varying vec4 verpos;
void main()
{
float x = verpos.x;
float y = verpos.y;
float z = verpos.z;
float depth = sqrt(x*x + y*y + z*z)/5000.0;
gl_FragColor = vec4(depth, depth, depth, 1.0);
}
问题是提取颜色值,那我只收结果精度为0.003921569
(=1/255
)。 结果值包含例如0.364705890, 0.364705890, 0.364705890, 0.364705890, 0.368627459, 0.368627459, 0.368627459
。一行中的大部分值完全相同,然后跳转到1/255。 因此,在某处之间gl_FragColor
和glReadPixels
OpenGL将浮点数转换为8位,然后将其转换回浮点数。
如何在不放松精度的情况下将距离值提取为float值?
如果您要写入8位RGBA的后缓冲区,如果您想写浮点值,则需要使用附加的“HALF_FLOAT”或“FLOAT”纹理渲染到“FrameBufferObject”,然后从中读取质地。 –
为什么这个深度的因子是1/5000?为什么你不使用现成的'length'内置函数,即'length(verpos)'。从技术上讲,甚至可以节省将深度写入碎片颜色(并全部禁用颜色写入)的步骤,并只读取深度缓冲区的内容并线性化深度值的1/x映射。深度缓冲区至少有16位,更可能是24位。从技术上讲,你甚至可以将线性深度写入深度缓冲区,但会影响性能。 – datenwolf
@datenwolf我除以5000,使得值在'[0,1]'范围内。 – user38034