我目前正在尝试使用GLEW实现Qt 5窗口和QOpenGLContext的工作。是的,我知道Qt 5提供了自己的OpenGL函数封装,但由于我的渲染引擎依赖于GLEW并支持其他窗口库,因此Qt内置的内容不是一个选择。
现在,这是我迄今为止得到的结果:
我子类化了QWindow,并配备了QOpenGLContext。上下文成功初始化。
在初始化QOpenGLContext之后,我(再次成功)调用glewInit()来初始化GLEW。
我现在能够以与其他窗口框架(更准确地说是GLFW)完全相同的方式将几何体渲染到默认帧缓冲区中。
这里是棘手的部分:我正在使用OpenGL的uniform buffer objects之一将光数据传输到GPU。一旦我调用glBufferData()进行初始填充,就会出现分段错误。使用基于GLFW的实现和上下文初始化时,一切正常。我知道这种行为对于未经充分初始化的OpenGL上下文可以预期,但是再次设置QOpenGLContext并调用glewInit()似乎非常好用。
这里有一些代码展示了我正在尝试做什么...
QtWindow::QtWindow(QWindow *parent)
: QWindow(parent) {
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format;
format.setVersion(4,5);
format.setOption(QSurfaceFormat::DeprecatedFunctions);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
}
这应该足够后面理解我所需的格式。现在,在第一帧呈现之前,我设置上下文和GLEW...
void QtWindow::init_context() {
if (!initialized_) {
context_handler_.init(this);
initialized_ = true;
glewExperimental = GL_TRUE;
auto e = glewInit();
if (e != GLEW_OK) {
std::cout << "Failed to initialize glew: "
<< glewGetErrorString(e) << std::endl;
}
glGetError();
}
}
我使用一个小的辅助类来初始化QOpenGLContext
,因为我需要防止Qt取消定义GLEW宏:
void QtContextHandler::init(QWindow* parent) {
if (!qt_context_) {
qt_context_ = new QOpenGLContext(parent);
qt_context_->setFormat(parent->requestedFormat());
if (qt_context_->create()) {
auto format(qt_context_->format());
std::cout << "Initialized Qt OpenGL context "
<< format.majorVersion() << "."
<< format.minorVersion() << " successfully."
<< std::endl;
qt_context_->makeCurrent(parent);
} else {
std::cout << "Failed to initialize Qt OpenGL context!"
<< std::endl;
}
}
}
以下是我设置轻量UBO的步骤,也是OpenGL初始化崩溃时出现的情况。我使用oglplus作为GL包装器,但由于它相当紧密地包装了OpenGL的函数,所以你应该能够理解:
ubo_.Bind(ogl::Buffer::Target::Uniform);
oglplus::Buffer::Data(oglplus::Buffer::Target::Uniform, sizeof(data), &data, oglplus::BufferUsage::DynamicDraw);
有人尝试过类似的方法并能分享他们的经验吗?我会很感激任何帮助,因为我被困在尝试弄清楚自己做错了什么的过程中。再次强调:初始化似乎顺利进行,我甚至能够创建用于渲染网格的VBOs/VAOs/IBOs!只有创建UBO会导致分段错误。
编辑:好的,这里有一些新的见解。首先,如果上传的数据超过一定大小(约90字节),就会发生分段错误。换句话说,我可以使用由Qt创建的上下文渲染仅具有一个自定义光源的场景。但是,当查询GL_MAX_UNIFORM_BLOCK_SIZE时,驱动程序告诉我可用于统一块的64KB(对于由GLFW创建的上下文也是如此)。有人有可能出现问题的想法吗?
glBufferData
就会出现段错误。你检查过此时的glBufferData
是否为非空吗? - G.M.std::array<int, 10> d = {0,1,2,3,4,5,6,7,8,9}
和ogl::Buffer::Data(ogl::Buffer::Target::Uniform, sizeof(d), &d, ogl::BufferUsage::DynamicDraw);
,它完美地工作了(除了意外的着色器行为,显然)。我感觉我用于光数据的数据类型被搞乱了或者出了什么问题。 - Felix Lauer