【转】OpenGL多线程创建纹理,附加我的测试结果
原文地址 http://www.cnblogs.com/mazhenyu/archive/2010/04/29/1724190.html
关于这个问题以前只知道多个线程不能同时使用一个RC,结果为了能动态加载,当初还做了一个通过拆分主线程的工作来模拟多线程加载的伪多线程程序,今天突然很想把这个问题彻底搞明白,结果从百度到google.com最后才在终于找到这么一篇讲解详细的英文文章,可怜我4级都没过的英语啊...
这是英文原文地址:http://veelck.wordpress.com/2008/11/28/multithread-texture-loading-in-opengl/
老外写东西一般废话会比较多,为了节省技术人员的宝贵时间就不逐句翻译了,提取一下要点吧,如下:
首先使用同一个DC创建两个RC,并且使用wglShareLists共享两个RC的资源。建议不要给这三个函数之间加其他向RC中添加东西的GL函数。
HGLRC hRC1 = wglCreateContext(hDC);
HGLRC hRC2 = wglCreateContext(hDC);
wglShareLists(hRC2, hRC1);
注意:wglShareLists的第一个参数中的RC是分享别人资源的,第二个参数中的RC是奉献资源供别人分享的。
//这是一个用来渲染场景的线程(也可用主线程来渲染)
renderingThread()
{
//...
wglMakeCurrent(hDC, hRC1);
//...
}
理论上来讲,可以在多创建几个RC,然后用多线程同时渲染。但是据说这样做是可行但却无益的。因为OpenGL会进行一些频繁的切换,导致产生高昂的开销。
//这是一个用来加载资源的线程,可以加载图片,并使用创建纹理,设置纹理参数等。
loadingThread()
{
//...
wglMakeCurrent(hDC, hRC2);
//...
}
注意,加载工作也可以写在多个线程中,例如使用多个线程从硬盘中读取图片文件(在多核机器上用双核读图片会比单核快一些),然后使用一个专门的线程调用GL的函数来创建纹理。但是,如果使用一些开源的图像库来读取图片的话就要注意了,有些开源的图像库不支持多线程,如DevIL。(FreeImage记得也存在这个问题)
最后别忘了在各个线程结束时调用wglMakeCurrent(NULL, NULL);取消DC与RC的关联。
还有要删除RC
wglDeleteContext(hRC2);
wglDeleteContext(hRC1);
最后要发一下牢骚。网上三维图形方面的资料相比其他计算机技术而言实在是不多,而且大多数还没有用。国内更是少的可怜,可能高人们都在忙着为买房子而奋斗导致没时间上网了。以下是该英文文章作者的感言,深有同感啊,向这种有国际主义精神的高人致敬。
It was quite a struggle to find anything useful in the web, only some minor things at few forums and mailing groups. But using that with some thinking and reading between lines I finally found the solution I’d like to share, as it can save (in my opinion) much time of searching and experimenting for others.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
我的测试:
测试程序由nehe的lesson7项目修改完成
#include<process.h>
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HGLRC hRCShareing=NULL;// 用于分享hRC的资源
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
hRCShareing = wglCreateContext(hDC);
wglShareLists(hRCShareing, hRC);
// 启动加载线程
_beginthread(TextureLoadingThread, NULL, NULL); //开启加载纹理线程
void TextureLoadingThread(void* p)
{
//...
wglMakeCurrent(hDC, hRCShareing);
if (!LoadGLTextures()) // Jump To Texture Loading Routine
{
return; // If Texture Didn't Load Return FALSE
}
//...
wglMakeCurrent(NULL, NULL);
// 结束线程
_endthread();
}
测试结果:
通过OK,纹理显示正常
如果注释掉下面共享hrc的代码,如下所示
//wglShareLists(hRCShareing, hRC);
则纹理无法显示,看到的是个白块。
GLFW文档对Current context的注释:
Before you can make OpenGL or OpenGL ES calls, you need to have a current context of the correct type. A context can only be current for a single thread at a time, and a thread can only have a single context current at a time.
【转】OpenGL多线程创建纹理,附加我的测试结果的更多相关文章
- OpenGL 多线程共享纹理
1:opengl 多线程共享纹理纹理: //解码时候使用opengl进行绘制,需要构建队列和两个线程,分别用于解码数据并且填充纹理和渲染. 主线程常见两个共享上下文: main() { ⋯⋯⋯⋯ gH ...
- Android OpenGL ES(八)----纹理编程框架
1.把纹理载入进OpenGL中 我们的第一个任务就是把一个图像文件的数据载入到一个OpenGL的纹理中. 作为開始.让我们又一次舍弃第二篇的框架.又一次创建一个程序,新建一个util工具包,在该包下创 ...
- Linux OpenGL 实践篇-5 纹理
纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...
- RenderTexture动态创建纹理
CCRenderTexture,它允许你来动态创建纹理,并且可以在游戏中重用这些纹理. 使用 CCRenderTexture非常简单 – 你只需要做以下5步就行了: 创建一个新的CCRenderTex ...
- 从零开始的openGL——四、纹理贴图与n次B样条曲线
前言 在上篇文章中,介绍了如何加载绘制模型以及鼠标交互的实现,并且遗留了个问题,就是没有模型表面没有纹理,看起来很丑.这篇文章将介绍如何贴纹理,以及曲线的绘制. 纹理贴图 纹理加载 既然是贴图,那首先 ...
- Opengl ES之纹理贴图
纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上.一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据. 所谓的纹理贴图,就是使用Opengl将 ...
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- python多线程创建与使用(转)
原文:http://codingpy.com/article/python-201-a-tutorial-on-threads/ 创建多线程 创建多线程主要有2种方式. 使用threading.Thr ...
- 使用Visual Studio Team Services进行压力和性能测试(一)——创建基础的URL压力测试
使用Visual Studio Team Services进行压力和性能测试(一)--创建基础的URL压力测试 概述 压力测试使应用程序更加健壮,并审核在用户负载下的行为,这样我们可以在当前的基础设施 ...
随机推荐
- C标准头文件<math.h>
定义域错误可以理解为超出了函数的适用范围,如果发生了定义域错误,设errno为EDOM 如果结果不能表示为double值,则发生值域错误,如果结果上溢,则函数返回HUGE_VAL的值,设errno为E ...
- 【Java学习系列】第2课--Java语法及面向对象
本文地址 分享提纲: 1. Java程序特点 1.1 基本语法 1.2 字符串 1.3 变量 1.4 Java数组 1.5 Java枚举 1.6 Java修饰符 1.7 Java编译制定在制定目录 2 ...
- 再谈HashMap
HashMap是一个高效通用的数据结构,它在每一个Java程序中都随处可见.先来介绍些基础知识.你可能也知 道,HashMap使用key的hashCode()和equals()方法来将值划分到不同的桶 ...
- HTTPS和HTTP的概念和区别
HTPPS和HTTP的概念 HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP ...
- 十种MYSQL显错注入原理讲解(二)
上一篇讲过,三种MYSQL显错注入原理.下面我继续讲解. 1.geometrycollection() and geometrycollection((select * from(select * f ...
- 【极品代码】一般人我不告诉他,手机端h5播放时不自动全屏代码
已测适用于ios,某些安卓手机微信下播放视频会出现播放器控件(这个实在是无力吐槽噢,因为之前还遇到过微信播放完视频后竟然无法退出全屏出现广告的情况,只有播放完后刷新页面并且要放到框架页里才能屏蔽微信视 ...
- SQL Server 2012新增和改动DMV
SQL Server 2012新增和改动DMV 系统视图 说明 sys.dm_exec_query_stats (Transact-SQL) 添加了四列,以帮助排除长时间运行的查询所存在的问题. 可 ...
- Java类加载基本过程
基本过程: 根据类的全限定名称加载定义类的二进制字节流. 将字节流代表的静态存储结构转化为方法区的运行时数据结构 内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各 ...
- mysql查询本周、月、季度、年
#查询本周记录 select * from product_process where WEEKOFYEAR(update_time)=WEEKOFYEAR(now()); #查询本月数据 selec ...
- monkey之monkey命令详解
四大类-- 常用选项.事件选项.约束选项.调试选项 1.常用选项 --help:打印帮助信息 -v:指定打印信息的详细级别,一个-v增加一个级别 ,默认级别为 0 .用于指定反馈信息级别(信息级别就是 ...