LINUX.ORG.RU

2D frame-by-frame bitmap-based animation program

 , ,


0

1

Здравствуйте.

Случилось как-то мне родить некое поделие: $subj (берёшь мышь или планшет типа wacom, рисуешь по-кадрово и получается в итоге анимация). Вроде как работает, делает что нужно и т.д.. Написано на Си с использованием X-ов (если компилировать под *nix) + OpenGL.

В программе реализованы слои и некий аналог «Symbol» из Adobe Flash. Как происходит отображение слоёв и этого аналога «Symbol» (все текстуры и картинки в RGBA формате):

1. Созданный фрэймбуффер, полученный из glGenFramebuffersEXT, очищаю в цвет (0.0, 0.0, 0.0, 0.0). К этому фрэймбуфферу цепляю текстуру.

2. GL_BLEND включён, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).

3. Иду по всем слоям, начиная с нижнего слоя, и загружаю картинку из данного слоя в текстуру и отрисовываю квадрат с этой текстурой.

4. После завершения всех слоёв, выставляю glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) и отрисовываю фон цветом (0.7, 0.7, 0.7, 1.0), «белый лист бумаги» - квадрат цветом (1.0, 1.0, 1.0, 1.0), и прикреплённую к тому фрэймбуфферу текстуру.

Для аналога «Symbol» сначала выполняются такие же шаги (внутри него тоже есть слои), но кладутся они (в кратце) в отдельную текстуру. Потом, когда дело в отрисовке всей сцены доходит до слоя, где находится этот «Symbol», просто отрисовывается его текстура.

Всё бы ничего, но такой алгоритм отрисовки не подходит. Ибо если на картинку с альфой 1.0 ложится картинка с альфой < 1.0, то получается итоговая текстура с альфой < 1.0 и на шаге 4 видно сквозь картинку задний фон. А если отрисовывать ещё и «Symbol», то получается двойной alpha-blending и картинка из «Symbol» получается темнее, чем должна быть на самом деле.

Вот и встаёт вопрос, как же сделать правильную отрисовку? Есть идеи? Например, gimp даёт правильные результаты, но в суть его отрисовки я ещё не вникал, потому что он-то не маленький и боюсь закопаться в нём с головой.



Последнее исправление: kapitan-amerika (всего исправлений: 1)

Ответ на: комментарий от Amp

Да, игрался как-то с ним, даже думал, что добился нужного результата, но потом понял, что лишь для частного случая: на шаге 3 использовал (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE). По идее это лишь даёт альфе на нижнем слое не стать меньше, чем она была. А если два слоя с альфой по 0.5 отрисовываются, то в результате альфа становится равной 1.0, что не есть, коненчо же, что нужно. Но ладно, буду думать.

kapitan-amerika
() автор топика
Ответ на: комментарий от kapitan-amerika

Не, ну вообще такая вот штука

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

визуально похожа на правду.

kapitan-amerika
() автор топика

А такой алгоритм разве не даст нужного результата?

1. Фон фреймбуфера в «цвет листа бумаги» (1.0, 1.0, 1.0, 1.0)
2. Начиная с нижнего рисуешь все слои с GL_MODULATE на квадах цвета (1.0, 1.0, 1.0, 1.0). Либо просто с GL_REPLACE.
3. Результирующую текстуру фреймбуфера на квад с GL_REPLACE.

Если нужен какой-то совсем уж хитрый алгоритм смешивания цветов - можно отойти от fixed pipeline и написать фрагментный шейдер.

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

Amp ★★★
()
Последнее исправление: Amp (всего исправлений: 2)
Ответ на: комментарий от Amp

А такой алгоритм разве не даст нужного результата?

Да, он даёт что нужно и получается такой же результат как я выше написал через glBlendFuncSeparate. Но он не подходит для отрисовки того аналога «Symbol» - фрэймбуффер должен быть прозрачным и содержать на себе только картинки с некой альфой.

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

Совершенно верно. Все нормальные люди используют ту же cairo. На самом деле прога очень маленькая и функций в ней настолько мало, что какая-то сторонняя библиотека лишь прибавит ей «веса» (в плане сборки помимо самой проги, ещё необходимо собрать зависимости). А если дело касается ещё и сборки под винду, то тут вообще хоть вешайся. Я стооолько геморра натерпелся, когда портировал её под винду. То там mingw поставь, то opengl библиотеки раздобудь, то для open нужно флаг BINARY указывать... А если ещё и зависимости собирать, то ну нафиг-нафиг. А вообще, нашёл я как-то баг в загрузке BMP-файлов в Qt версии 4.8.4 (+- 0.1.5), так там вместо uint было просто int. И при операции >> тащился старший бит. Ну как после этого доверять сторонним библиотекам, если даже в самом Qt стоит неоттестированный код? (вопрос риторический)

Ну это я так. Конечно, скорее всего нужно брать уже готовые библиотеки и не париться. А пережить портирование под другие платформы уж как-нибудь можно.

kapitan-amerika
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.