如何使用QOpenGLWidget解决GL_INVALID_OPERATION错误
How can I solve GL_INVALID_OPERATION error with QOpenGLWidget?
我有一个OpenGL三维纹理和一个2d纹理,我想将它们组合到片段着色器中。整个UI是用QOpenGLWidget完成的,这大大简化了工作流程。现在我有个问题。一旦我尝试做这样的事情:
vec4 col = texture(tex, uvCoord);
outColor = texture(lookUp, col.rgb);
在我的片段着色器中,在绘制几何体的过程中,我得到了一个GL_INVALID_OPERATION错误。绘制矩形四边形后,方法paintGL((中就会出现错误。如果我在碎片着色器中执行此操作:
outColor = texture(lookUp, uvCoord);
我没有得到错误,我在显示的窗口中看到了预期的颜色。如果能给我提供任何可以搜索解决方案的提示,我将不胜感激。
#include "tex3dtest.h"
Tex3dtest::Tex3dtest(QWidget *parent)
: QMainWindow(parent)
{
setCentralWidget(new ImageGLWidget());
}
ImageGLWidget::ImageGLWidget(QWidget* parent) : QOpenGLWidget(parent)
{
texture = Q_NULLPTR;
setFixedSize(512, 512);
QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3, 3);
setFormat(format);
}
ImageGLWidget::~ImageGLWidget()
{}
const int LUT3D_EDGE_SIZE = 32;
void ImageGLWidget::printError(GLuint error)
{
switch (error)
{
case GL_NO_ERROR:
qDebug() << "NoError";
break;
case GL_INVALID_ENUM:
qDebug() << "OpenGL ERROR: GL_INVALID_ENUM";
break;
case GL_INVALID_VALUE:
qDebug() << "OpenGL ERROR: GL_INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
qDebug() << "OpenGL ERROR: GL_INVALID_OPERATION";
break;
case GL_STACK_OVERFLOW:
qDebug() << "OpenGL ERROR: GL_STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
qDebug() << "OpenGL ERROR: GL_STACK_UNDERFLOW";
break;
case GL_OUT_OF_MEMORY:
qDebug() << "OpenGL ERROR: GL_OUT_OF_MEMORY";
break;
}
}
void ImageGLWidget::createTexture()
{
qDebug() << "ImageGLWidget::createTexture";
GLenum err;
int num3Dentries = 3 * LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE;
textureContent.resize(num3Dentries);
for (unsigned int i = 0; i < num3Dentries; i++)
textureContent[i] = ((float)i)/num3Dentries * 100.0f;
texture = new QOpenGLTexture(QOpenGLTexture::Target::Target3D);
bool is3d = texture->hasFeature(QOpenGLTexture::Feature::Texture3D);
texture->setFormat(QOpenGLTexture::TextureFormat::RGB32F);
texture->setSize(LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE);
texture->allocateStorage(QOpenGLTexture::PixelFormat::RGB, QOpenGLTexture::PixelType::Float32);
texture->setMagnificationFilter(QOpenGLTexture::Linear);
texture->setMinificationFilter(QOpenGLTexture::Linear);
texture->setWrapMode(QOpenGLTexture::ClampToEdge);
texture->setData(QOpenGLTexture::PixelFormat::RGB, QOpenGLTexture::PixelType::Float32, &textureContent[0]);
int num2Dentries = 256 * 256 * 3;
textureContent1.resize(num2Dentries);
for (unsigned int i = 0; i < num2Dentries; i++)
textureContent1[i] = ((float)rand())/RAND_MAX;
texture1 = new QOpenGLTexture(QOpenGLTexture::Target::Target2D);
texture1->setFormat(QOpenGLTexture::TextureFormat::RGB32F);
texture1->setSize(256, 256, 0);
texture1->allocateStorage(QOpenGLTexture::PixelFormat::RGB, QOpenGLTexture::PixelType::Float32);
texture1->setMagnificationFilter(QOpenGLTexture::Linear);
texture1->setMinificationFilter(QOpenGLTexture::Linear);
texture1->setWrapMode(QOpenGLTexture::ClampToEdge);
texture1->setData(QOpenGLTexture::PixelFormat::RGB, QOpenGLTexture::PixelType::Float32, &textureContent1[0]);
}
static const float vertexData[] = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f
};
static const char *vtxVBO =
"#version 330n"
"layout(location = 0) in vec3 position;n"
"layout(location = 1) in vec2 uv;n"
"out vec2 uvCoord;n"
"void main()n"
"{n"
" gl_Position = vec4(position, 1.0);n"
" uvCoord = uv;n"
"}n";
static const char *frgVBO =
"#version 330n"
"in vec2 uvCoord;n"
"out vec4 outColor;n"
"uniform sampler2D tex;n"
"uniform sampler3D lookUp;n"
"void main()n"
"{n"
" vec4 col = texture(tex, uvCoord);n"
" outColor = texture(lookUp, col.rgb);n"
"// outColor = texture(tex, uvCoord);n"
"}n";
void ImageGLWidget::initializeGL()
{
GLenum err;
qDebug() << "initializeGL";
initializeOpenGLFunctions();
createTexture();
program = new QOpenGLShaderProgram();
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vtxVBO);
program->addShaderFromSourceCode(QOpenGLShader::Fragment, frgVBO);
program->link();
program->bind();
vertexbuffer.create();
vertexbuffer.bind();
vertexbuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
vertexbuffer.allocate(vertexData, sizeof(float) * 6 * 5);
vao.create();
vao.bind();
program->enableAttributeArray(0);
program->enableAttributeArray(1);
int stride = 5 * sizeof(float);
int uvOffset = 3 * sizeof(float);
program->setAttributeBuffer(0, GL_FLOAT, 0, 3, stride);
program->setAttributeBuffer(1, GL_FLOAT, uvOffset, 2, stride);
vao.release();
vertexbuffer.release();
program->release();
}
void ImageGLWidget::paintGL()
{
qDebug() << "ImageGLWidget::paintGL";
GLenum err;
glClear(GL_COLOR_BUFFER_BIT);
texture->bind();
texture1->bind();
program->bind();
vao.bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
vao.release();
program->release();
}
头文件是这样的:
#pragma once
#include <QtWidgets/QMainWindow>
#include <qopenglwidget.h>
#include <qopenglfunctions.h>
#include <qopenglshaderprogram.h>
#include <qopengltexture.h>
#include <qopenglvertexarrayobject.h>
#include <qopenglbuffer.h>
class Tex3dtest : public QMainWindow
{
Q_OBJECT
public:
Tex3dtest(QWidget *parent = Q_NULLPTR);
private:
};
class ImageGLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
Q_OBJECT;
public:
ImageGLWidget(QWidget* parent = Q_NULLPTR);
~ImageGLWidget();
virtual void initializeGL();
virtual void paintGL();
void printError(GLuint error);
void createTexture();
private:
QOpenGLShaderProgram *program;
QOpenGLTexture *texture;
QOpenGLTexture *texture1;
QOpenGLVertexArrayObject vao;
QOpenGLBuffer vertexbuffer;
std::vector<float> textureContent;
std::vector<float> textureContent1;
};
该问题可以通过在着色器程序中设置统一值来解决。在initializeGL中,我添加:
programOCIO->bind();
texture2DLoc = programOCIO->uniformLocation("tex");
texture3DLoc = programOCIO->uniformLocation("lookUp");
后来在paintGL方法中,我添加了:
glActiveTexture(GL_TEXTURE0);
texture->bind();
glActiveTexture(GL_TEXTURE1);
lut3dTex->bind();
programOCIO->setUniformValue(texture2DLoc, 0);
programOCIO->setUniformValue(texture3DLoc, 1);
现在运行良好。
相关文章:
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++模板错误:"invalid explicitly-specified argument for template parameter"
- SDL_CreateTextureFromSurface() "Invalid texture"错误?
- 如何'Invalid conversion'和'no match for operator'更正这些 c++ 错误
- 访问函数变体时"Invalid conversion"错误
- 出现这种错误的原因是什么"invalid use of non-static data member "
- 模板类和'invalid use of incomplete type'错误
- 为什么我会收到"invalid conversion from 'Queue*/Stack*' to 'int'"错误消息?
- 错误"invalid types ... for array subscript"是什么意思?
- Java 本机访问代码错误:"Invalid memory access"
- 封送C++交错数组会产生"Invalid managed/unmanaged type combination"错误
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- 为什么我的重载 + 运算符在返回时会产生"Invalid address specified to RtlValidateHeap"错误?
- 如何修复代码中的"Invalid memory reference"错误?
- C++抛出错误"Invalid special open parenthesis."中的正则表达式
- 模板类错误的向量:"Template argument 2 is invalid"
- 如何避免"invalid initialization of reference" C++中琐碎函子的错误
- 让编译器告诉哪些方法不具体,而不是错误'invalid new-expression of abstract class type'
- map.insert:"Invalid arguments"错误与 pair<enum,vector<*>>
- 尝试执行任何需要它的操作时,无法修复 WinAPI 中的"invalid handle"错误