Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / OpenGL, Blending и текстуры с альфой

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

dead_manПостоялецwww10 мар. 201819:24#0
Всем привет!

Столкнулся с проблемой: по разному смешиваются цвета в 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);

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

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

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

Изображение

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

MrShoorУчастникwww10 мар. 201821:45#1
Хммм. Не помню сохраняется ли стейт после установки, но как насчет того, чтобы попробовать рисовать текстуру так:
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();
Lion007Постоялецwww11 мар. 201814:10#2
текстуры (в 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 - то дизэйблим, если нет - то энейблим.

dead_manПостоялецwww11 мар. 201818:19#3
MrShoor
Цвет перед отрисовкой текстуры меняется в 1,1,1,1

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

FordPerfectПостоялецwww11 мар. 201819:05#4
Гамма по-разному выставлена? Какое именно значение цвета? {255,0,0}?
dead_manПостоялецwww11 мар. 201819:14#5
FordPerfect
Для сплошного прямоугольника задается glColor4f(1,0,0,0.5)
Текстура в png, цвет RGBA(255,0,0,127) (Исходник: test_alpha )
MrShoorУчастникwww11 мар. 201820:09#6
dead_man
> (Исходник: test_alpha )
Тю, я думал там исходник с кодом, а там опять гадать на кофейной гуще надо.
dead_manПостоялецwww11 мар. 201821:48#7
MrShoor
извините, весь исходник выложить не могу, кода очень много. всю информацию о процессе рендера я привел. интересует мнение кого-то, кто знаком с механизмом смешивания цветов в OpenGL
Lion007Постоялецwww11 мар. 201822:04#8
там может быть куча всяких фокусов... начиная от загрузки текстуры и кончая неизвестно чем :)
по идее, рисование красного квадратика с альфа = 0.5 и рисование белым цветом квадратика с текстурой, в которой красный цвет и альфа=0.5  должны давать идентичный результат - при условии,
что установлено glTextureEnv (GL_TEXTURE_ENV_MODE, GL_MODULATE). все остальное - это какие-то косяки, то ли с рендерингом, то ли с загрузкой текстуры.

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

MrShoorУчастникwww11 мар. 201822:05#9
dead_man
> извините, весь исходник выложить не могу, кода очень много.
а сделать минимальный пример с проблемой, и выложить сюда?
dead_manПостоялецwww11 мар. 201822:11#10
Lion007
MrShoor
хорошо, постараюсь оформить
}:+()___ [Smile]Постоялецwww12 мар. 20180:09#11
Lion007
> функция блендинга glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) - в большинстве случаев сомнительна
Наоборот, это единственно правильная функция блендинга (если бы GPU умел sRBG альфу, было бы лучше использовать glBlendFunc(GL_ONE, GL_SRC_ALPHA), но чего нет, того нет).
Другие варианты применимы только в ограниченных контекстах (типа константного цвета) и обычно говорят о низкой квалификации графического программиста.

Правка: 12 мар. 2018 0:10

dead_manПостоялецwww15 мар. 20180:10#12
Всем спасибо! Выяснил причину данной проблемы. Блендинг работает как надо. Как оказалось jogl неправильно загружал текстуру (вроде как выставлял неправильный формат пикселей). Для тех кто тоже использует jogl (или планирует) небольшое пояснение под спойлером.
+ Показать

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр