對於一個應用程序,我需要創建一個網格的深度圖像。基本上我想要一個圖像,其中每個像素都表示相機中心和交點之間的距離。我選擇使用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