gpt4 book ai didi

c++ - QOpenGLWidget 的 resizeGL 不是调用 glViewport 的地方?

转载 作者:太空狗 更新时间:2023-10-29 21:39:24 24 4
gpt4 key购买 nike

我正在试验新的 QOpenGLWidget 类(请注意,这不是 QGLWidget 类)。

我正在画一个三角形。我有一个普通的顶点着色器,它接收剪辑空间中的坐标,因此不涉及矩阵或投影。其中一个顶点的坐标为 -1, -1, 0, 1,另一个顶点的坐标为 1, 1, 0, 1

当我没有调用任何 glViewport 时,程序呈现为好像我正在调用 glViewport(0, 0, w, h); 在我的 resizeGL 函数中,我不是。也就是说,无论我如何调整窗口大小,三角形的两个顶点都附在窗口的左下角和右上角。

当我在我的 resizeGL 函数中实际添加一个对 glViewport 的调用时,它显然被忽略了——如果我传递 w 也没关系/2、h/2 或任何其他值,渲染与调用 glViewport(0, 0, w, h); 时完全相同(例如,我希望在 glViewport(0, 0, w/2, h/2);)

的情况下,三角形出现在窗口的左下角

当我在 paingGL 函数中调用 glViewport(0, 0, width()/2, height()/2) 时,渲染如预期 - 一切正常绘制在窗口的左下角。

所以看起来 glViewport 在 resizeGLpaintGL 之间的某处被覆盖了。这是怎么回事,我该如何解决?我是否必须求助于在我的 paintGL 函数中进行视口(viewport)转换?

文档中列出的 QGLWidget 和 QOpenGLWidgets 之间的区别之一是后者呈现到帧缓冲区而不是直接呈现到屏幕。这能成为解释的关键吗?

为了以防万一,我附上了完整的代码以供引用。

//三角形.h

#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

//三角形.cpp

#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();
}

//控件.h

#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

//控件.cpp

#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

#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());
}
}

//顶点着色器

#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;
}

//片段着色器

#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 (…)

是的。而你的期望究竟是什么?调用 glViewport 以使 OpenGL 程序健壮的唯一有效位置是在绘图代码中。将 glViewport 放在窗口调整大小处理程序中的每一个教程都是错误的,应该被烧掉。

When I call glViewport(0, 0, width()/2, height()/2) in paingGL function, the rendering is as expected

是的,这就是您应该使用它的方式。

关于c++ - QOpenGLWidget 的 resizeGL 不是调用 glViewport 的地方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33059185/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com