QOpenGLWidget's resizeGL is NOT the place to call glViewport?
我正在尝试新的QOpenGLWidget类(请注意,这不是QGLWidget类)。
我正在画一个三角形。我有一个琐碎的顶点着色器,可在剪辑空间中接收坐标,因此不涉及任何矩阵或投影。其中一个顶点的坐标为
无论我什么时候都没有调用glViewport,该程序将呈现为好像我在resizeGL函数中调用了
当我实际上在我的
当我在
因此,似乎glViewport被覆盖在
文档中列出的QGLWidget和QOpenGLWidgets之间的区别之一是,后者将渲染到帧缓冲区,而不是直接渲染到屏幕。这可以把握解释的关键吗?
以防万一,我附上完整的代码以供参考。
// triangle.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #ifndef TRIANGLE_H #define TRIANGLE_H #include <QOpenGLBuffer> #include <QOpenGLFunctions> class Triangle { public: Triangle(); void render(); void create(); private: QOpenGLBuffer position_vbo; QOpenGLFunctions *glFuncs; }; #endif // TRIANGLE_H |
// triangle.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include"triangle.h" Triangle::Triangle() :position_vbo(QOpenGLBuffer::VertexBuffer) { } void Triangle::create() { glFuncs = QOpenGLContext::currentContext()->functions(); position_vbo.create(); float val[] = { -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, -0.366f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, }; position_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw); position_vbo.bind(); position_vbo.allocate(val, sizeof(val)); position_vbo.release(); } void Triangle::render() { position_vbo.bind(); glFuncs->glEnableVertexAttribArray(0); glFuncs->glEnableVertexAttribArray(1); glFuncs->glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); glFuncs->glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(3*4*sizeof(float))); glFuncs->glDrawArrays(GL_TRIANGLES, 0, 3); glFuncs->glDisableVertexAttribArray(0); glFuncs->glDisableVertexAttribArray(1); position_vbo.release(); } |
// widget.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #ifndef WIDGET_H #define WIDGET_H #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLShaderProgram> #include"triangle.h" class Widget : public QOpenGLWidget , protected QOpenGLFunctions { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); protected: virtual void initializeGL() override; virtual void paintGL() override; virtual void resizeGL(int w, int h) override; private: QOpenGLShaderProgram* program; Triangle t; }; #endif // WIDGET_H |
// widget.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include"widget.h" #include <exception> #include <QDebug> Widget::Widget(QWidget *parent) : QOpenGLWidget(parent) { } Widget::~Widget() { } void Widget::initializeGL() { initializeOpenGLFunctions(); program = new QOpenGLShaderProgram(this); if(!program->addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/vertexshader.vert")) { throw std::exception(("Vertex Shader compilation error:" + program->log()).toLocal8Bit().constData()); } if(!program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/fragmentshader.frag")) { throw std::exception(("Fragment Shader compilation error:" + program->log()).toLocal8Bit().constData()); } if(!program->link()) { throw std::exception(("Program Link error:" + program->log()).toLocal8Bit().constData()); } t.create(); } void Widget::paintGL() { glClearColor(0.f, 0.15f, 0.05f, 0.f); glClear(GL_COLOR_BUFFER_BIT); //glViewport(0, 0, width()/2, height()/2); //works!! program->bind(); t.render(); program->release(); } void Widget::resizeGL(int w, int h) { glViewport(0, 0, w/2, h/2); //doesn't work } |
// main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include"widget.h" #include <exception> #include <QApplication> #include <QMessageBox> int main(int argc, char *argv[]) { QApplication a(argc, argv); try { Widget w; w.show(); return a.exec(); } catch(std::exception const & e) { QMessageBox::warning(nullptr,"Error", e.what()); } } |
//顶点着色器
1 2 3 4 5 6 7 8 9 10 11 | #version 330 layout (location = 0) in vec4 position; layout (location = 1) in vec4 color; smooth out vec4 theColor; void main() { gl_Position = position; theColor = color; } |
//片段着色器
1 2 3 4 5 6 7 | #version 330 out vec4 fragColor; smooth in vec4 theColor; void main() { fragColor = theColor; } |
So it seems that the glViewport is overridden somewhere between resizeGL and paintGL. What is going on and how do I fix it? Do I have to resort to doing viewport transformations in my paintGL function?
Qt5可以将OpenGL用于其自己的图形。同样,作为QOpenGLWindow子级的小部件的内容也呈现给FBO。因此,这意味着在代码和Qt的功能之间进行了许多glViewport调用。
When I actually add a call to glViewport in my resizeGL function, it is apparently ignored (a€|)
是的。您的期望到底是什么?为了使OpenGL程序更强大,唯一调用
When I call glViewport(0, 0, width()/2, height()/2) in paingGL function, the rendering is as expected
是的,这就是您应该使用它的方式。