2013-04-01 39 views
0

請考慮以下代碼。 imageDataf是一個float *。事實上,如代碼所示,它由由光線追蹤器創建的float4值組成。當然,顏色值是線性空間,我需要它們伽馬校正屏幕上的輸出。 所以我可以做的是一個簡單的循環與伽瑪校正2.2(見循環)。另外,我可以使用GL_FRAMEBUFFER_SRGB_EXT,它的工作原理幾乎相同,但具有「帶狀」問題。GL_FRAMEBUFFER_SRGB_EXT分帶問題(伽馬校正)

img

左使用GL_FRAMEBUFFER_SRGB_EXT,右是手動的伽馬校正。正確的圖片看起來很完美在某些監視器上發現它可能會遇到一些困難。有沒有人有線索如何解決這個問題?我想爲「免費」做伽瑪校正,因爲CPU版本使GUI有點遲緩。請注意,實際的光線追蹤是在使用GPU(optix)的另一個線程中完成的,因此實際上它在渲染性能方面速度一樣快。

GLboolean sRGB = GL_FALSE; 
glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &sRGB); 
if (sRGB) { 
    //glEnable(GL_FRAMEBUFFER_SRGB_EXT); 
} 

for(int i = 0; i < 768*768*4; i++) 
{ 
    imageDataf[i] = (float)powf(imageDataf[i], 1.0f/2.2f); 
} 

glPixelStorei(GL_UNPACK_ALIGNMENT, 8); 

glDrawPixels(static_cast<GLsizei>(buffer_width), static_cast<GLsizei>(buffer_height), 
    GL_RGBA, GL_FLOAT, (GLvoid*)imageDataf); 

//glDisable(GL_FRAMEBUFFER_SRGB_EXT); 

回答

3

當啓用GL_FRAMEBUFFER_SRGB,這意味着OpenGL的將假定爲一個片段的顏色是線性色彩空間。因此,當它將它們寫入sRGB格式的圖像時,它會將它們從內部線性轉換爲sRGB。除...你的像素是不是線性。您已經將它們轉換爲非線性色彩空間。

但是,我假設您只是在那裏忘記了if聲明。我假設,如果幀緩衝區具有sRGB功能,則可以跳過該循環並直接上傳數據。相反,我會解釋爲什麼你會得到樂隊。

因爲您要求的OpenGL操作執行以下操作,所以會出現條帶化。對於您指定的每種顏色:

  1. 將浮動限制在[0,1]範圍內。
  2. 將浮點數轉換爲無符號,標準化的8位整數。
  3. 使用該無符號,標準化的8位顏色生成片段。
  4. 將無符號,規範化的8位碎片顏色從線性RGB空間轉換爲sRGB空間並存儲它。

步驟1-3都來自於使用glDrawPixels。你的問題是第2步。你想保持你的浮點值爲浮點數。然而你堅持使用固定功能流水線(即:glDrawPixels),其中強制從浮點到無符號歸一化整數的轉換。

如果您將數據上傳到浮動紋理並使用適當的片段着色器渲染此紋理(即使只是一個簡單的gl_FragColor = texture(tex, texCoord);着色器),您也可以。着色器管道使用浮點數學,而不是整數數學。所以不會發生這樣的轉換。

總之:停止使用glDrawPixels

+0

+1:很好的答案 – radical7

+0

當然,我使用GL_FRAMEBUFFER_SRGB註釋掉for循環,這應該從生成的圖像中明顯看出。那麼,因爲除了圖形用戶界面稍微滯後之外,我不會因此受到任何處罰,因此我將讓GPU獨自進行實際的光線追蹤。謝謝你的幫助。 – apartridge