На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Правила раздела "Программирование графики"
1) Данный раздел предназначен для обсуждения проблем, возникающих при программировании задач, связанных с чтением, сохранением, обработкой, созданием, отрисовкой графической информации (в том числе - 3D [OpenGL, Direct3D] и анимации [в т.ч. VFW, DirectShow, OpenDML]).
Флэш обсуждают здесь!.

2) Если вы хотите получить совет для конкретной платформы/языка программирования, обязательно укажите их в вопросе.

3) Уважаемые новички! Мы приветствуем Ваше желание научить всех посетителей раздела правильному программированию. Но огромная просьба, перед тем, как писать поучения в старых (последний ответ - "старее" месяца, а особенно, если вопрошавший не появляется на форуме уже не первый месяц, в чем можно убедиться в его профиле) темах, хорошо подумать, будет ли кому-нибудь, кроме Вас cамих, это интересно.



Ваше мнение о модераторах: user posted imageBarazuk, user posted imageOpenGL, user posted imageMikle
Модераторы: OpenGL, Mikle
  
> OpenGL и неправильный расчёт альфы, Наложение белого на белый даёт серый
Добрый день. Сел писать графику на OpenGL < 3.0, то есть без шейдеров, VAO и прочего. Думал, что легче будет, да и хотел бы гарантировать, что программа запустится на любом железе, вплоть до древнего хлама. Ну и наткнулся на проблему. Когда рисуется квадрат с текстурой белого полупрозрачного цвета (т.е. альфа у каждого пикселя = 0.5) поверх белого непрозрачного квадрата, то получается серый.

Настройки каждой текстуры:
ExpandedWrap disabled
        glGenTextures(1, texture);
        glBindTexture(GL_TEXTURE_2D, *texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmapdata.Width, bitmapdata.Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, bitmapdata.Scan0);


И рисование:
ExpandedWrap disabled
        unsigned int len = drawlist.legth();
        GlBlendEquation glBlendEquation = (GlBlendEquation)glutGetProcAddress("glBlendEquation");
     
        glClear(GL_COLOR_BUFFER_BIT);
        for (int i = 0; i < len; i++)
        {
            glBlendEquation(0x8006);//GL_FUNC_ADD
            glBindTexture(GL_TEXTURE_2D, drawlist[i].texture);
            glBegin(GL_QUADS);
            glBlendEquation(0x8006);//На всякий случай после begin
            
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            glColor4f(1.0f, 1.0f, 1.0f, drawlist[i].alpha);
     
            glTexCoord2f(0.0f, 0.0f);
            glVertex2fv(&drawlist[i].points[0]);
            glTexCoord2f(1.0f, 0.0f);
            glVertex2fv(&drawlist[i].points[2]);
            glTexCoord2f(1.0f, 1.0f);
            glVertex2fv(&drawlist[i].points[4]);
            glTexCoord2f(0.0f, 1.0f);
            glVertex2fv(&drawlist[i].points[6]);
            glEnd();
     
        }
     
        glBindTexture(GL_TEXTURE_2D, 0);
        glFlush();
        glutSwapBuffers();


Я подумал, что в glBlendEquation оказался GL_MAX, поэтому и сделал костыль, но не помогло. При этом картинки с общей альфой (т.е. альфа каждого пикселя 255, но рисуется поверх полупрозрачного квадрата) оно рисует нормально. Как быть? Пока что вижу только способ переписать всё с шейдерами, а если на какой-то машине не запуститься, то запускать альтернативу, которая будет плохо рисовать всякие туманы и контуры (что в принципе приемлемо, но хотелось бы знать, в чём причина).

На изображении на самом деле рисуется изображение с равномерным градиентом от белого к прозрачному.
Прикреплённая картинка
Прикреплённая картинка
Всё правильно работает.
Через толстое-толстое стекло ты смотришь на белый квадрат. Какого цвета он будет?
Тот же квадрат перед тобой, а за ним стекло. Теперь какой цвет?
Раньше так писали
ExpandedWrap disabled
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Цитата business user @
Какого цвета он будет?

Белый.
Цитата business user @
Теперь какой цвет?

Тоже белый, разве нет? Почему он должен быть не белым? Я смотрю на белую стену сквозь тонкое белое стекло, сквозь толстое белое, без стекла - всё равно всё будет белым?

цвет = альфа текстуры * цвет текстуры + (1 - альфа текстуры) * цвет в буфере
В нашем случае: цвет = А * белый + (1 - А) * белый = 1 * белый = белый

И там стоял glBlendFunc где-то в инициализации, в фрагменты, что я показал, он не вошёл. Но я поставил его ещё пару раз в цикл на всякий случай, результат тот же. Я просто не понимаю логику OpenGL.
Я OpenGL не знаю, но в Direct3D будет белый, значит и здесь должно быть так же.
Могу предположить: текстура белого полупрозрачного квадрата, случайно, не из PNG грузится, который premultipled? Если да, до должно быть как-то так:
ExpandedWrap disabled
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Цитата Mikle @
текстура белого полупрозрачного квадрата, случайно, не из PNG грузится, который premultipled

Точно! Проверил побайтово получившуюся картинку, посмотрел на PixelFormat, и таки да, она premultiplied. Не думал, что LockBits может вернуть не тот PixelFormat, что в картинке, и даже не тот, что ей передают... Кажется, пора искать какую-то библиотеку по открытию изображений.

Добавлено: хотя если представить, что Bitmap при загрузке из файла на самом деле загрузку откладывает, а настоящий формат оно узнаёт только когда его в явном виде просят вытянуть изображение побайтово, то это обретает смысл.
Сообщение отредактировано: k.sovailo -
Цитата k.sovailo @
Кажется, пора искать какую-то библиотеку по открытию изображений.

premultipled по структуре ни чем не отличается от обычного ARGB, разница в том, как его нужно использовать.
Нужно искать не "какую-то библиотеку по открытию изображений", а программу для сохранения изображений, которая не делает, как фотошоп, все PNG принудительно premultipled.
Mikle, кстати да, именно фотошоп я и использовал. Я знаю, что такое premultiplied, мне просто надоела ситуация, когда GDI+ (сейчас все изображения загружаются через него) постоянно выдаёт не то, что я прошу.
Цитата k.sovailo @
просто надоела ситуация, когда GDI+ (сейчас все изображения загружаются через него) постоянно выдаёт не то, что я прошу.

Ещё раз - файл premultiplied ни чем не отличается от не premultiplied. Само слово "premultiplied" - это свойство изображения, а не файла. Либо поменяй glBlendFunc как я писал выше, чтобы пользоваться premultiplied, либо, если надо именно обычную альфу, сохраняй с помощью GDI+ или с помощь какого-нибудь Paint.net. Фотошоп при сохранении в PNG меняет не просто формат, он меняет сами данные - умножает цвет на альфу.
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


Рейтинг@Mail.ru
[ Script Execution time: 0,1145 ]   [ 21 queries used ]   [ Generated: 19.07.19, 06:56 GMT ]