2016-07-25 76 views
0

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

如何在不放鬆精度的情況下將距離值提取爲float值?

+1

如果您要寫入8位RGBA的後緩衝區,如果您想寫浮點值,則需要使用附加的「HALF_FLOAT」或「FLOAT」紋理渲染到「FrameBufferObject」,然後從中讀取質地。 –

+0

爲什麼這個深度的因子是1/5000?爲什麼你不使用現成的'length'內置函數,即'length(verpos)'。從技術上講,甚至可以節省將深度寫入碎片顏色(並全部禁用顏色寫入)的步驟,並只讀取深度緩衝區的內容併線性化深度值的1/x映射。深度緩衝區至少有16位,更可能是24位。從技術上講,你甚至可以將線性深度寫入深度緩衝區,但會影響性能。 – datenwolf

+0

@datenwolf我除以5000,使得值在'[0,1]'範圍內。 – user38034

回答

1

將R32F或R16F紋理附加到FBO並對其進行渲染。然後像glReadPixels()那樣用glGetTexImage2D()提取像素。