所以我对使用 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 的格式。我尝试过将原始数据传递到纹理。
我复制了你的示例,它在 Qt 6.7 中适用于我。尝试下载并运行它:black-box-was-fixed.zip
一些注意事项:
m_texture->setData(m_image)
内的每一帧调用 paintGL()
。你应该只在里面调用一次 initializeGL()
QImage::mirrored()
: 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);
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();
}
}