OpenGL多线程

在OpenGL里面使用多线程加载纹理是很美好的构想。

网上讨论这个的并不多。中文博客里
http://www.cnblogs.com/mazhenyu/archive/2010/04/29/1724190.html

参考了某个老外的尝试:

http://veelck.wordpress.com/2008/11/28/multithread-texture-loading-in-opengl/
其基本思路如下:

要创建新的rendering context (RC), 先需要device context(DC).

DC可以在得到HWND后得到:
HDC hDC = GetDC(hWnd);

接下来使用Windows extension函数:wglCreateContext创建RC。如果失败返回NULL。

在这里我们用1个hDC创建2个RC:

HGLRC rendContext1 = wglCreateContext(hDC); 
HGLRC rendContext2 = wglCreateContext(hDC); 

接下来我们用1个RC加载图片,一个用来渲染。困难的是你必须共享2个RC之间的资源。

因为你在一个RC中创建的纹理在另外一个RC中是不可访问的,反之亦然。

使用这个方法共享RC:

wglShareLists(rendContext2, rendContext1); 

最好在调用context任何操作前完成这个操作!最好在与OpenGL做任何交互前调用。

现在可以在不同线程里使用RC了。不需要每次都使用,只需要在线程开始前调用即可。

renderingThread() 
{ 
    //... 
    wglMakeCurrent(hDC, rendContext1); 
    //... 
    wglDeleteContext(rendContext1); 
} 

loadingThread() 
{ 
    //... 
    wglMakeCurrent(hDC, rendContext2); 
    //... 
    wglDeleteContext(rendContext2); 
} 

再次注意,wglShareLists 只能在进程内工作。所以使用多线程而不是多进程。

wglMakeCurrent只是设置本线程的默认RC。所以并不关心其他线程在干什么。

现在你可以在Load线程里放心的调用图片加载,如glGenTextures、glTexParameteri、glTexImage2D了。

而Render线程也可以访问Load线程的资源。

如果你想在Render线程里也加载图片,记住某些图片库( DevIL)不支持多线程加载。自己去做线程互斥把。

我没有尝试多线程渲染。但从网上资料来看,即使有也没有意义。 OpenGLz的contexts切换会带来大量额外负担。

在进程的最后要释放并删除contexts。

wglMakeCurrent(NULL, NULL). 

====================================================

以上是作者的基本思路。

在我的项目里,我尝试用一个线程专门用于动态加载纹理。

看上去运行的不错。不幸的是,当纹理加载频率教高的时候,纹理会出现白框和闪烁。

在ATI的某些显卡上效果会好很多,基本看不到奇怪现象;在NV的显卡上相当明显。

这个问题尚没有完美解决。基本只能在多线程里将纹理读到内存,然后在主渲染线程里读入显存。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Qt中使用OpenGL进行多线程渲染可以提高渲染效率和用户体验。下面是一个基本的示例,演示了如何在Qt中使用OpenGL进行多线程渲染: 1. 首先,在Qt中创建一个新的OpenGL窗口类,继承自QOpenGLWidget。 ```cppclass MyGLWidget : public QOpenGLWidget{ public: MyGLWidget(QWidget *parent = nullptr) : QOpenGLWidget(parent) {} protected: void initializeGL() override { // 初始化OpenGL环境 } void resizeGL(int w, int h) override { // 处理窗口大小变化事件 } void paintGL() override { // 执行OpenGL渲染操作 } }; ``` 2. 接下来,在主窗口类中创建一个新的线程,并在该线程中进行OpenGL渲染操作。 ```cppclass MainWindow : public QMainWindow{ public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 创建OpenGL窗口 m_glWidget = new MyGLWidget(this); setCentralWidget(m_glWidget); // 创建渲染线程 m_renderThread = new QThread(this); m_glWidget->moveToThread(m_renderThread); // 连接信号槽,触发渲染操作 connect(m_renderThread, &QThread::started, m_glWidget, &MyGLWidget::update); connect(m_glWidget, &MyGLWidget::frameSwapped, m_renderThread, &QThread::quit); connect(m_glWidget, &MyGLWidget::destroyed, m_renderThread, &QThread::quit); // 启动渲染线程 m_renderThread->start(); } private: MyGLWidget *m_glWidget; QThread *m_renderThread; }; ``` 在上述代码中,我们在主窗口类的构造函数中创建了一个OpenGL窗口,并将其移动到一个新的线程中。然后,我们连接了一些信号槽,以触发渲染操作,并在窗口销毁时停止渲染线程。 这样,我们就可以在Qt中使用OpenGL进行多线程渲染了。当启动应用程序时,渲染线程将开始执行OpenGL渲染操作,而主线程仍然可以响应用户交互事件。请注意,这只是一个简单的示例,你可能需要根据你的具体需求进行更多的代码调整和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值