Неправильное альфа-смешение при рендеринге в QGLFramebufferObject

Я пишу для своего приложения средство визуализации векторной графики на основе OpenGL. Он должен отображаться в объекте фреймбуфера, а не непосредственно на экране. Поскольку я пишу приложение на Qt, я использую QGLFramebufferObject, который является классом-оболочкой для объекта фреймбуфера OpenGL.

Я создал минимальный пример, который показывает неправильный результат, который я также получаю при рендеринге более сложных вещей (например, с использованием фрагментного шейдера, который устанавливает цвета с не равным единице альфа-значением). Я просто визуализирую красный кружок и полупрозрачный зеленый кружок на черном экране, а затем то же самое в FBO:

void MainWidget::initializeGL()
{
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0, 0, 0, 0);
}

void MainWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void MainWidget::paintGL()
{
    // DRAW ON THE SCREEN
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glPointSize(100);
        glEnable(GL_POINT_SMOOTH);
        glBegin(GL_POINTS);
        glColor4f(1, 0, 0, 1);
        glVertex2f(-.2, 0);
        glColor4f(0, 1, 0, .5);
        glVertex2f( .2, 0);
        glEnd();
    }

    QGLFramebufferObject fbo(width(), height());
    fbo.bind();

    // DRAW ON THE FBO USING THE SAME CODE AND THE SAME CONTEXT
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glPointSize(100);
        glEnable(GL_POINT_SMOOTH);
        glBegin(GL_POINTS);
        glColor4f(1, 0, 0, 1);
        glVertex2f(-.2, 0);
        glColor4f(0, 1, 0, .5);
        glVertex2f( .2, 0);
        glEnd();
    }

    fbo.release();
    fbo.toImage().save("debug.png");
}

Результат на экране (масштаб 400%) выглядит так:

введите описание изображения здесь

Рендеринг QGLFramebufferObject выглядит следующим образом (также масштабируется на 400%):

введите описание изображения здесь

Обратите внимание, что это изображение не полностью непрозрачно, поэтому здесь это то же изображение с добавленной за ним шахматной доской:

введите описание изображения здесь

Даже область, в которой два круга перекрываются, не полностью непрозрачна. Да и сглаживание выглядит довольно некрасиво.

Как это происходит? И как я могу это исправить?

Я уже пробовал:

  • Различные функции наложения.
  • Явное отключение буфера глубины, буфера трафарета и выборки в QGLFramebufferObject. Я не уверен, добавляет ли формат по умолчанию QGLFramebufferObject то, что мне не нужно.

person leemes    schedule 06.09.2012    source источник
comment
@Nicol Bolas, я откатил вашу правку, потому что речь идет не о сглаживании точек. Я получаю такие же результаты при рендеринге треугольников даже без сглаживания. Я пробовал много разных минимальных примеров. Рисование гладких точек - это самый маленький из них.   -  person leemes    schedule 06.09.2012
comment
Извините, я забыл инструкцию glClearColor. Это полностью прозрачно. Добавление его в код ничего не меняет.   -  person leemes    schedule 06.09.2012


Ответы (1)


Попробуйте следующее:

QGLFramebufferObjectFormat fmt;
fmt.setSamples(1); // or 4 or disable this line
fmt.setInternalTextureFormat(GL_RGBA8);
QGLFramebufferObject fbo(width(), height(), fmt);

Это принудительно устанавливает определенный формат пикселей, а также отключает рендеринг текстуры с использованием мультисэмплинга (в противном случае QT всегда выполняет рендеринг в текстуру). Это может дать разные результаты. Вы также можете поэкспериментировать с форматом.

Кроме того, какое у вас оборудование? Мой максимальный размер точки составляет всего 64 пикселя (GTX 260), вы пытаетесь отрендерить 100 пиксельных точек. Это может быть проблемой. Генерируются ли какие-либо ошибки OpenGL? То же самое происходит с мелкими точками?

Вы также можете попробовать намекнуть (если это возможно в QT):

glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

Но я бы не ожидал, что это что-то изменит.

person the swine    schedule 09.11.2012