QOpenGLContext::swapBuffers() called with non-exposed window, behavior is undefined
时间: 2024-02-24 14:58:18 浏览: 21
这个警告通常是因为OpenGL上下文(QOpenGLContext)尝试在没有被显示的窗口上调用swapBuffers函数。这通常发生在以下情况下:
1. 窗口被最小化或隐藏,但OpenGL上下文仍然处于活动状态,并且尝试在窗口不可见的情况下刷新缓冲区。
2. 窗口刚刚被创建,但还没有被显示,OpenGL上下文尝试在窗口未显示的情况下刷新缓冲区。
为了避免这个警告,您可以在调用swapBuffers之前检查窗口的isVisible()方法,以确保窗口已经被显示:
```
if (window.isVisible()) {
context->swapBuffers(window.surface());
}
```
如果窗口没有被显示,则不会调用swapBuffers函数,从而避免警告。
另外,您还可以通过在窗口显示之前禁用OpenGL上下文来避免这个警告:
```
context->setScreen(window.screen());
context->setFormat(format);
context->create();
context->makeCurrent(&window);
context->doneCurrent();
window.show();
```
这样,OpenGL上下文将在窗口显示之前被禁用,并且不会尝试在未显示的窗口上调用swapBuffers函数。
相关问题
怎么将osgViewer::Viewer嵌入ui->openGLWidget
将 `osgViewer::Viewer` 嵌入到 `QOpenGLWidget` 中,可以通过以下步骤实现:
1. 继承 `QOpenGLWidget` 类,并实现以下虚函数:
```cpp
class OsgWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
OsgWidget(QWidget* parent = nullptr);
virtual ~OsgWidget();
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void paintEvent(QPaintEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
bool event(QEvent* event) override;
};
```
其中,`initializeGL`、`resizeGL` 和 `paintGL` 函数用于初始化 OpenGL 上下文并绘制场景,`paintEvent` 函数用于处理重绘事件,`keyPressEvent`、`keyReleaseEvent`、`mousePressEvent`、`mouseReleaseEvent` 和 `mouseMoveEvent` 函数用于处理键盘和鼠标事件,`event` 函数用于处理其他事件。
2. 在 `initializeGL` 函数中创建 `osgViewer::GraphicsWindow` 对象,并将其关联到 `osgViewer::Viewer` 对象中:
```cpp
void OsgWidget::initializeGL()
{
// Create an OSG graphics context
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowName = "OSG Widget";
traits->x = 0;
traits->y = 0;
traits->width = width();
traits->height = height();
traits->doubleBuffer = true;
traits->windowDecoration = false;
traits->sharedContext = 0;
// Create an OSG graphics window
osg::ref_ptr<osgViewer::GraphicsWindow> gw = osg::GraphicsContext::createGraphicsWindow(traits.get());
// Create an OSG viewer
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->getCamera()->setGraphicsContext(gw);
viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
// Set the viewer's scene data
osg::ref_ptr<osg::Node> scene = createSceneGraph();
viewer->setSceneData(scene.get());
// Save the viewer pointer for later use
m_viewer = viewer;
}
```
其中,`createSceneGraph` 函数用于创建 OSG 场景图。
3. 在 `paintGL` 函数中将 `osgViewer::Viewer` 的帧缓冲区绑定到 `QOpenGLWidget` 的帧缓冲区,并使用 `osgViewer::Viewer::frame` 函数绘制一帧:
```cpp
void OsgWidget::paintGL()
{
// Bind OSG's frame buffer object to the OpenGL context
m_viewer->getCamera()->getGraphicsContext()->realizeOpenGLContext();
m_viewer->getCamera()->getGraphicsContext()->makeCurrent();
m_viewer->getCamera()->getGraphicsContext()->bindPBufferToTexture();
// Draw a frame
m_viewer->frame();
// Swap the buffers
m_viewer->getCamera()->getGraphicsContext()->swapBuffers();
}
```
4. 在 `resizeGL` 函数中更新 `osgViewer::Viewer` 的视口:
```cpp
void OsgWidget::resizeGL(int w, int h)
{
// Update OSG's viewport
m_viewer->getCamera()->setViewport(new osg::Viewport(0, 0, w, h));
}
```
5. 在 `paintEvent` 函数中强制刷新 `QOpenGLWidget`:
```cpp
void OsgWidget::paintEvent(QPaintEvent* event)
{
// Force redraw
update();
}
```
6. 将 `OsgWidget` 添加到 `QMainWindow` 中:
```cpp
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QMainWindow mainWindow;
// Create an OSG widget
OsgWidget* osgWidget = new OsgWidget(&mainWindow);
// Add the OSG widget to the main window
mainWindow.setCentralWidget(osgWidget);
mainWindow.show();
return app.exec();
}
```
通过以上步骤,就可以将 `osgViewer::Viewer` 嵌入到 `QOpenGLWidget` 中,并在 Qt 应用程序中显示 OSG 场景图了。
kanzi使用::Renderer画线段
Kanzi 中的 ::Renderer 是一个底层图形渲染引擎,可以使用它来绘制线段。以下是使用 ::Renderer 绘制线段的示例代码:
```cpp
#include <Renderer.h>
...
// 创建 Renderer 对象
kanzi::Renderer renderer = kanzi::Renderer::getInstance();
// 设置线段颜色和宽度
renderer.setLineWidth(2);
renderer.setColor(255, 0, 0); // 红色
// 绘制线段
renderer.drawLine(0, 0, 100, 100); // 起点为 (0, 0),终点为 (100, 100)
// 刷新画面
renderer.swapBuffers();
```
以上代码会在屏幕上绘制一条起点坐标为(0,0),终点坐标为(100,100),线宽为2,颜色为红色的线段。你可以根据需要修改颜色、线宽、起点和终点坐标等参数。