首页 > 解决方案 > Qt 半透明 QOpenGLWidget 与背景奇怪地混合

问题描述

根据常识,如果你rgba(1,0,0,0)在屏幕上绘制颜色,它与颜色应该没有区别,rgba(0,0,0,0)因为 alpha 值为 0。

但是,当我使用 QOpenGLWidget 并将清除颜色设置为 时rgba(1,0,0,0),它并没有按我的意愿执行。(我在问题的底部附上了简化的代码演示)

为了演示混合有什么问题,我想发布一个屏幕截图,其中 mspaint 窗口位于 QOpenGLWidget 的正下方。 QOpenGLWidget 奇怪地与背景混合——rgba(1,0,0,0)

如果我将清除颜色设置为rgba(1,0,0,0.2),它看起来像: QOpenGLWidget 与背景奇怪地混合在一起——rgba(1,0,0,0.2)

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA)根据上面显示的屏幕截图,我猜帧缓冲区是通过类似于OpenGL的混合函数与背景混合的。

但我真正想要的是像glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA).

现在我通过使用color=vec4(color.xyz*color.w,color.w)之前的功能swapBuffers()和 DWM 中的混合过程自行对帧缓冲区进行后处理来解决这个问题。

我希望有一个平台函数可以调用来设置混合函数,但我在文档中找不到它。除了变通,有没有办法实现这个目标?还是我以错误的方式使用 OpenGL?

附代码:

主文件

#include <QApplication>
#include <QSurfaceFormat>
#include "forms/DemoWidget.h"

int main(int argc, char *argv[]) {

    QSurfaceFormat format;
    format.setVersion(3, 3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    format.setRedBufferSize(8);
    format.setGreenBufferSize(8);
    format.setBlueBufferSize(8);
    format.setAlphaBufferSize(8);
    format.setSamples(8);
    QSurfaceFormat::setDefaultFormat(format);
    QApplication application(argc, argv);
    application.setApplicationName("demo");
    DemoWidget demoWidget(nullptr);
    demoWidget.show();
    return application.exec();
}

DemoWidget.h

#pragma once

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>

class DemoWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
Q_OBJECT
public:
    DemoWidget(QWidget *parent=nullptr, const Qt::WindowFlags &f=Qt::WindowFlags());

    virtual ~DemoWidget();

protected:
    void initializeGL() override;

    void paintGL() override;
};

DemoWidget.cpp

#include "DemoWidget.h"

DemoWidget::DemoWidget(QWidget *parent, const Qt::WindowFlags &f) : QOpenGLWidget(parent, f | Qt::Window) {
    setAttribute(Qt::WA_TranslucentBackground,true);
    setAttribute(Qt::WA_NoSystemBackground,false);
    resize(600, 100);
}

DemoWidget::~DemoWidget() {}

void DemoWidget::initializeGL() {
    initializeOpenGLFunctions();
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(1, 0, 0, 0.2);
}

void DemoWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT);
}

另外,我的平台是Qt 6.2.1(MinGW 8.1.0 64bit)Windows 10.0.19043. 我尝试glfw了两者gccmsvc但得到了同样令人失望的结果。在 StackOverflow 中,我发现了一个基于 2012 年发布的类似问题的问题,但它是 onUbuntu 12.04 LTS并且它使用了libgl1-mesa-dev.

但是,我在 github 上找到了一个 sln 项目,它运行良好(尽管它包含的 gl.h 仅支持 OpenGL 1.1)。

标签: c++windowsopengl

解决方案


推荐阅读