2013-04-01 2 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), который заставляет преобразовать от float к беззнаковым нормализованным целым числам.

Если вы загрузили свои данные в текстуру поплавка и использовали правильный шейдер фрагмента для рендеринга этой текстуры (даже простой шейдер gl_FragColor = texture(tex, texCoord);), все будет в порядке. Конвейер шейдеров использует математику с плавающей запятой, а не целочисленную математику. Поэтому такого преобразования не произойдет.

Вкратце: прекратите использование glDrawPixels.

+0

+1: хороший ответ – radical7

+0

Конечно, я комментирую цикл for при использовании GL_FRAMEBUFFER_SRGB, что должно быть очевидно из сгенерированного изображения. Ну, так как для меня нет штрафа, кроме небольшого отставания в графическом интерфейсе, я дам GPU быть одному, чтобы сделать фактический трассировка лучей. Спасибо за вашу помощь. – apartridge

Смежные вопросы