Войти
ПрограммированиеФорумГрафика

OpenGL, Blending и текстуры с альфой

#0
19:24, 10 мар. 2018

Всем привет!

Столкнулся с проблемой: по разному смешиваются цвета в OpenGL.
Рисуем картинку, поверх нее полупрозрачную красную текстуру и рядом такой же полупрозрачный красный прямоугольник.

Код рисования сплошного прямоугольника:

c = 0x7fffffff;
gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
gl.glColor4f(((c >> 16) & 0xFF) / 255.f, ((c >> 8) & 0xFF) / 255.f, (c & 0xFF) / 255.f, ((c >> 24) & 0xFF) / 255.f);
gl.glRecti(x, y, x + w, y + h);

Код рисования текстуры:

getTexture().bind(gl); // в функции getTexture создается и считывается текстура, если этого еще не было сделано

gl.glBegin(GL2.GL_QUADS);
gl.glTexCoord2f(0, 1);
gl.glVertex2i(x, y2);
gl.glTexCoord2f(1, 1);
gl.glVertex2i(x2, y2);
gl.glTexCoord2f(1, 0);
gl.glVertex2i(x2, y);
gl.glTexCoord2f(0, 0);
gl.glVertex2i(x, y);
gl.glEnd();

Если выставить блендинг такой:

gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);

Результат будет такой:
Изображение

Верхний квадрат - отрисованный сплошной цвет. Нижний - текстура. Как видно, текстура отрисовалась нормально, сплошной прямоугольник получился ярче.

Если блендинг такой:

gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);

То получаем это:
Изображение

Сплошной прямоугольник нормальный, текстура темнее.

Результат в идеале должен быть таким:

Изображение

Можно переключать блендинг по ходу отрисовки, но не хочется делать лишних действий. Подскажите, как правильно выставить блендинг, чтобы рисовалось одинаково?


#1
21:45, 10 мар. 2018

Хммм. Не помню сохраняется ли стейт после установки, но как насчет того, чтобы попробовать рисовать текстуру так:

gl.glBegin(GL2.GL_QUADS);
gl.glColor4f(1,1,1,1);
gl.glTexCoord2f(0, 1);
gl.glVertex2i(x, y2);
gl.glTexCoord2f(1, 1);
gl.glVertex2i(x2, y2);
gl.glTexCoord2f(1, 0);
gl.glVertex2i(x2, y);
gl.glTexCoord2f(0, 0);
gl.glVertex2i(x, y);
gl.glEnd();

#2
14:10, 11 мар. 2018

текстуры (в FFP) честно умножаются на текущий цвет (который через glColor). и это, вообще говоря, правильно - можно на лету, скажем, объект покрасить, или прозрачность задать не трогая самой текстуры.
Поэтому, как справедливо заметил камрад MrShoor, чтобы цвета текстуры не искажались, перед выводом текстурированного объекта надо выставить glColor4f(1, 1, 1, 1);

дальше, функция блендинга glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) - в большинстве случаев сомнительна, если только текстура не содержит premultyplied -цвета (то есть цвета, которые заранее на альфу помножены). по смыслу больше подходит glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) .

ну и последнее... хотя текстура 0, насколько помню, это просто белый непрозрачный пиксель, все-таки после glBindTexture(GL_TEXTURE_2D, 0), наверное, стоит выключить текстурирование - glDisable(GL_TEXTURE_2D);
теоретически, оно, конечно, ни на что влиять не должно - но так немножко аккуратнее. хотя, надо признать - добавляет головной боли по слежению за этим флагом :)
правда, для простоты, можно его установку совместить с биндом текстуры - если 0 - то дизэйблим, если нет - то энейблим.

#3
18:19, 11 мар. 2018

MrShoor
Цвет перед отрисовкой текстуры меняется в 1,1,1,1

Lion007
Спасибо за совет, но glDisable(GL_TEXTURE_2D); , к сожалению, проблему не решил...

#4
19:05, 11 мар. 2018

Гамма по-разному выставлена? Какое именно значение цвета? {255,0,0}?

#5
19:14, 11 мар. 2018

FordPerfect
Для сплошного прямоугольника задается glColor4f(1,0,0,0.5)
Текстура в png, цвет RGBA(255,0,0,127) (Исходник: test_alpha )

#6
20:09, 11 мар. 2018

dead_man
> (Исходник: test_alpha )
Тю, я думал там исходник с кодом, а там опять гадать на кофейной гуще надо.

#7
21:48, 11 мар. 2018

MrShoor
извините, весь исходник выложить не могу, кода очень много. всю информацию о процессе рендера я привел. интересует мнение кого-то, кто знаком с механизмом смешивания цветов в OpenGL

#8
22:04, 11 мар. 2018

там может быть куча всяких фокусов... начиная от загрузки текстуры и кончая неизвестно чем :)
по идее, рисование красного квадратика с альфа = 0.5 и рисование белым цветом квадратика с текстурой, в которой красный цвет и альфа=0.5  должны давать идентичный результат - при условии,
что установлено glTextureEnv (GL_TEXTURE_ENV_MODE, GL_MODULATE). все остальное - это какие-то косяки, то ли с рендерингом, то ли с загрузкой текстуры.

для чистоты эксперимента - рекомендую попробовать написать маленький тестовый примерчик - хоть на GLUT-е.
создать руками текстурку 1х1 - и вперед... вот если и на примерчике начнет блендиться по-разному - вот тогда будет обозримый кусок кода, в котором можно ковыряться! :)

#9
22:05, 11 мар. 2018

dead_man
> извините, весь исходник выложить не могу, кода очень много.
а сделать минимальный пример с проблемой, и выложить сюда?

#10
22:11, 11 мар. 2018

Lion007
MrShoor
хорошо, постараюсь оформить

#11
(Правка: 0:10) 0:09, 12 мар. 2018

Lion007
> функция блендинга glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) - в большинстве случаев сомнительна
Наоборот, это единственно правильная функция блендинга (если бы GPU умел sRBG альфу, было бы лучше использовать glBlendFunc(GL_ONE, GL_SRC_ALPHA), но чего нет, того нет).
Другие варианты применимы только в ограниченных контекстах (типа константного цвета) и обычно говорят о низкой квалификации графического программиста.

#12
0:10, 15 мар. 2018

Всем спасибо! Выяснил причину данной проблемы. Блендинг работает как надо. Как оказалось jogl неправильно загружал текстуру (вроде как выставлял неправильный формат пикселей). Для тех кто тоже использует jogl (или планирует) небольшое пояснение под спойлером.

+ Показать
ПрограммированиеФорумГрафика