为什么我看不到使用 QOpenGLWIdget 的纹理,它只显示一个黑框?

问题描述 投票:0回答:1

所以我对使用 QOpenGLWidget (Qt 6.6) 相当陌生,我将 QImage 传递给我的自定义 QOpenGLWidget,当我显示该小部件时,它只显示一个黑框。我环顾四周,找不到任何解决方案。有什么建议吗?

我的设置是,我在 Qt Designer 中使用 QWidget 作为我的自定义 QOpenGLWidget 的父级。

#include "OpenGLWidget.h"

OpenGLWidget::OpenGLWidget(QWidget* parent) : QOpenGLWidget(parent) 
{
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    setFixedSize(500, 500);
}

OpenGLWidget::~OpenGLWidget()
{
    makeCurrent();
    delete m_texture;
    doneCurrent();
}

void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    // Enable texture mapping
    glEnable(GL_TEXTURE_2D);

    // Create an OpenGL texture object
    m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_texture->setMinificationFilter(QOpenGLTexture::Nearest);
    m_texture->setMagnificationFilter(QOpenGLTexture::Nearest);
    m_texture->setWrapMode(QOpenGLTexture::ClampToEdge);
    m_texture->create();
    if (m_texture != nullptr && m_texture->isCreated())
    {
        // Create and compile shaders
        shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
            "#version 330\n"
            "in vec2 vertexPosition;"
            "in vec2 vertexTexCoord;"
            "out vec2 texCoord;"
            "void main() {"
            "    gl_Position = vec4(vertexPosition, 0.0, 1.0);"
            "    texCoord = vertexTexCoord;"
            "}");

        shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
            "#version 330\n"
            "in vec2 texCoord;"
            "uniform sampler2D textureSampler;"
            "out vec4 fragColor;"
            "void main() {"
            "    fragColor = texture(textureSampler, texCoord);"
            "}");

        // Create vertex buffer
        GLfloat vertices[] = {
            -1.0f, -1.0f, 0.0f, 0.0f,
             1.0f, -1.0f, 1.0f, 0.0f,
             1.0f,  1.0f, 1.0f, 1.0f,
            -1.0f,  1.0f, 0.0f, 1.0f
        };

        vertexBuffer.create();
        vertexBuffer.bind();
        vertexBuffer.allocate(vertices, sizeof(vertices));

        // Create vertex array object
        vertexArrayObject.create();
        vertexArrayObject.bind();

        shaderProgram.enableAttributeArray("vertexPosition");
        shaderProgram.enableAttributeArray("vertexTexCoord");
        shaderProgram.setAttributeBuffer("vertexPosition", GL_FLOAT, 0, 2, sizeof(GLfloat) * 4);
        shaderProgram.setAttributeBuffer("vertexTexCoord", GL_FLOAT, sizeof(GLfloat) * 2, 2, sizeof(GLfloat) * 4);
    }
}

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

void OpenGLWidget::paintGL()
{
    // Clear the buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Load image data into the OpenGL texture
    if (!m_image.isNull())
    {
        m_texture->setData(m_image);
    }

    // Use shader program
    if (shaderProgram.bind())
    {
        // Bind texture
        m_texture->bind();

        // Draw quad
        vertexArrayObject.bind();
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        vertexArrayObject.release();

        // Unbind texture
        m_texture->release();

        // Release shader program
        shaderProgram.release();
    }
}

void OpenGLWidget::setImage(QImage image)
{
    m_image = image;
}

我尝试过更改 QImage 的格式。我尝试过将原始数据传递到纹理。

c++ qt opengl
1个回答
0
投票

我复制了你的示例,它在 Qt 6.7 中适用于我。尝试下载并运行它:black-box-was-fixed.zip

一些注意事项:

  1. 不要在
    m_texture->setData(m_image)
    内的每一帧调用
    paintGL()
    。你应该只在里面调用一次
    initializeGL()
  2. 您应该使用
    QImage::mirrored()
    :
  3. 镜像纹理
    m_texture.create();
    m_texture.bind();
    m_texture.setData(QImage(":/assets/textures/box_texture_512x512.png").mirrored());
    m_texture.setMinMagFilters(QOpenGLTexture::Filter::Linear, QOpenGLTexture::Filter::Linear);
    m_texture.setWrapMode(QOpenGLTexture::WrapMode::ClampToEdge);
  1. 使用
    QOpenGLShader::ShaderTypeBit::Vertex
    代替
    QOpenGLShader::Vertex
    ,使用
    QOpenGLTexture::WrapMode::ClampToEdge
    代替
    QOpenGLTexture::WrapMode::ClampToEdge
    等等(参见示例),因为枚举在 Qt 6 中已被弃用。

black-box-was-fixed.pro

QT       += core gui openglwidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# disables all the APIs deprecated before Qt 6.0.0
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000

SOURCES += \
    main.cpp \
    opengl_widget.cpp

HEADERS += \
    opengl_widget.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    assets.qrc

资产.qrc

<RCC>
    <qresource prefix="/">
        <file>assets/textures/box_texture_512x512.png</file>
    </qresource>
</RCC>

主.cpp

#include "opengl_widget.h"

#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    OpenGLWidget w;
    w.show();
    return app.exec();
}

opengl_widget.h

#ifndef OPENGL_WIDGET_H
#define OPENGL_WIDGET_H

#include <QtGui/QOpenGLFunctions>
#include <QtOpenGL/QOpenGLVertexArrayObject>
#include <QtOpenGL/QOpenGLBuffer>
#include <QtOpenGL/QOpenGLShaderProgram>
#include <QtOpenGL/QOpenGLTexture>
#include <QtOpenGLWidgets/QOpenGLWidget>

class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions
{
public:
    OpenGLWidget(QWidget *parent = nullptr);
    ~OpenGLWidget();

private:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;

private:
    QOpenGLBuffer vertexBuffer;
    QOpenGLVertexArrayObject vertexArrayObject;
    QOpenGLShaderProgram shaderProgram;
    QOpenGLTexture m_texture;
};

#endif // OPENGL_WIDGET_H

opengl_widget.cpp

#include "opengl_widget.h"

OpenGLWidget::OpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
    , m_texture(QOpenGLTexture::Target::Target2D)
{
    setWindowTitle("Example");
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    setFixedSize(350, 350);
}

OpenGLWidget::~OpenGLWidget() {}

void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    // Enable texture mapping
    glEnable(GL_TEXTURE_2D);

    // qDebug() << "OpenGL version:" << (const char*) glGetString(GL_VERSION) << "\n";
    // qDebug() << "GLSL version: " << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";
    // qDebug() << "Vendor: " << (const char*) glGetString(GL_VENDOR) << "";

    m_texture.create();
    m_texture.bind();
    m_texture.setData(QImage(":/assets/textures/box_texture_512x512.png").mirrored());
    m_texture.setMinMagFilters(QOpenGLTexture::Filter::Linear, QOpenGLTexture::Filter::Linear);
    m_texture.setWrapMode(QOpenGLTexture::WrapMode::ClampToEdge);

    // Create and compile shaders
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex,
        "#version 130\n"
        "in vec2 vertexPosition;"
        "in vec2 vertexTexCoord;"
        "out vec2 texCoord;"
        "void main()"
        "{"
        "    gl_Position = vec4(vertexPosition, 0.0, 1.0);"
        "    texCoord = vertexTexCoord;"
        "}");

    shaderProgram.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment,
        "#version 130\n"
        "in vec2 texCoord;"
        "uniform sampler2D textureSampler;"
        "out vec4 fragColor;"
        "void main()"
        "{"
        "    fragColor = texture(textureSampler, texCoord);"
        "}");

    // Create vertex buffer
    GLfloat vertices[] = {
        -1.0f, -1.0f, 0.0f, 0.0f,
        1.0f, -1.0f, 1.0f, 0.0f,
        1.0f,  1.0f, 1.0f, 1.0f,
        -1.0f,  1.0f, 0.0f, 1.0f
    };

    vertexBuffer.create();
    vertexBuffer.bind();
    vertexBuffer.allocate(vertices, sizeof(vertices));

    // Create vertex array object
    vertexArrayObject.create();
    vertexArrayObject.bind();

    vertexBuffer.bind();
    shaderProgram.bind();
    shaderProgram.enableAttributeArray("vertexPosition");
    shaderProgram.enableAttributeArray("vertexTexCoord");
    shaderProgram.setAttributeBuffer("vertexPosition", GL_FLOAT,
                                     0, 2, sizeof(GLfloat) * 4);
    shaderProgram.setAttributeBuffer("vertexTexCoord", GL_FLOAT,
                                     sizeof(GLfloat) * 2, 2, sizeof(GLfloat) * 4);
}

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

void OpenGLWidget::paintGL()
{
    // Clear the buffer
    glClearColor(0.2f, 0.2f, 0.2f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Use shader program
    if (shaderProgram.bind())
    {
        // Bind texture
        m_texture.bind();

        // Draw quad
        vertexArrayObject.bind();
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        // Unbind texture
        m_texture.release();

        // Release shader program
        shaderProgram.release();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.