openGL之多线程渲染
随着Vulkan的引入,我们的图形技术的发展到达了一个新的顶点,但是呢,我们的老干爹OpenGL作为落日余晖,他在一些Vulkan才有的新功能上,也提供了一些支持,现在我们来讨论一下OpenGL之多线程渲染。
这里要补一补课:
windows上调用openGL最原始的原始方式
大概流程是这样的详情请见:https://gitee.com/GProReat/codes/bjptwd3hglozmi25esn4v31
1.获取句柄, 在win32或者MFC里面可以直接获取HWND,但是在glut,glfw,sdl等可以通过GetActiveWindow来获取HWND。
2.GetDC,这个是获取窗口的DC, HDC ( Handle To Device Context)是图像的设备描述表,窗口显示上下文句柄,其中可以进行图形显示。
3.PixelFormat的支持,这里可以看刚才代码段里面PixelFormat的设置
4.创建OpenGL的上下文wglCreateContext, 以及切换到当前的上下文,wglMakeCurrent,传入HGLRC类型的object。
5.初始化操作 各种开关比如: depthTest,AlphaTest,DepthFunc,Texture2等操作。
6.在窗口的绘制的时候,也就是WM_PAINT相应的时候处理绘制。
这里关键一点是,调用OpenGL绘制之后使用SwapBuffers,还有glFlush。
7.资源释放。
note:windows上使用openGL来渲染,大家可以找MFC或者win32上的OpenGL绘制。
接下来开始我们的主题:openGL多线程渲染:
根据我的测试,HGLRC 的创建与线程无关,也就是说目前HGLRC可以在另外一个线程创建(需要在当前线程wglShareLists),也可以在当前线程创建,
下面为核心代码:
this->hGLRC2 = wglCreateContext(hDC);
wglShareLists(hGLRC2, hGLRC);
std::thread th([this]() {
wglMakeCurrent(hDC, hGLRC2);
texAnotherThread.LoadFromFile1("1.jpg");
});
th.join();
当然我们根据测试,也能发现,HGLRC在shared之前或者之后加载资源,都能做到共享
hGLRC = wglGetCurrentContext();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
std::thread th([this]() {
hGLRC2 = wglCreateContext(hDC);
wglMakeCurrent(hDC, hGLRC2);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
texAnotherThread.LoadFromFile1("1.jpg");
}
th.join();
wglShareLists(hGLRC, hGLRC2);
还有根据我的测试wglShareLists(hGLRC, hGLRC2); 他实际上这两个参数顺序是有讲究的,如果在创建完上下文之后,直接共享,那么这俩参数顺序没有影响,如果在hGLRC2里加载完tetxure,那么只能wglShareLists(hGLRC2,hGLRC)
代码如下:(顺序无关的)
void MultiThreadTexture_App::Init()
{
hWnd = GetActiveWindow();
hDC = GetDC(hWnd);
hGLRC = wglGetCurrentContext();
hGLRC2 = wglCreateContext(hDC);
wglShareLists(hGLRC, hGLRC2); //顺序无关
isRunning = true;
std::thread th([this]() {
wglMakeCurrent(hDC, hGLRC2);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
texAnotherThread.LoadFromFile1("1.jpg");
});
th.join();
}
void MultiThreadTexture_App::Init()
{
hWnd = GetActiveWindow();
hDC = GetDC(hWnd);
hGLRC = wglGetCurrentContext();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
hGLRC2 = wglCreateContext(hDC); isRunning = true;
std::thread th([this]() {
wglMakeCurrent(hDC, hGLRC2);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
texAnotherThread.LoadFromFile1("1.jpg");
});
th.join();
//这两个参数顺序是和渲染结果有关系的
wglShareLists(hGLRC2, hGLRC); //只能这样子。 }
使用线程2来渲染,代码如下: 结果是可以显示
void MultiThreadTexture_App::Init()
{
hWnd = GetActiveWindow();
hDC = GetDC(hWnd);
hGLRC = wglGetCurrentContext();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
hGLRC2 = wglCreateContext(hDC);
wglShareLists(hGLRC, hGLRC2);
isRunning = true;
std::thread th([this]() {
wglMakeCurrent(hDC, hGLRC2);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
texAnotherThread.LoadFromFile1("1.jpg");while (isRunning) //使用程序来控制 isRunning在线程运行之前为true,程序退出为false
{
if (isRenderBegin) //在调用Render的时候为true。
{
Render(-10);
AfterRender();
}
}
});
th.detach();
} void MultiThreadTexture_App::Render(int deltaMillionSeconds)
{
if (!isRenderBegin)
isRenderBegin = true;
if (deltaMillionSeconds != -10) return;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, width / height, 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 100, 0, 0, 0, 0, 1, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glClearDepth(1000);
glEnable(GL_FILL);
glBindTexture(GL_TEXTURE_2D, texAnotherThread.texId);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(1, 0); glVertex3f(100, 0, 0);
glTexCoord2f(1, 1); glVertex3f(100, 100, 0);
glTexCoord2f(0, 1); glVertex3f(0, 100, 0);
glEnd(); }
最后,做了一个交替渲染, 每1s为间隔,线程1,线程2交替渲染,而且他们使用对方的资源,比如第1s线程1渲染用的是线程2加载的纹理,第2s线程2渲染用的是线程1加载的纹理,如此循环...
代码如下:
void MultiThreadTexture_App::Init()
{
hWnd = GetActiveWindow();
hDC = GetDC(hWnd);
hGLRC = wglGetCurrentContext();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
hGLRC2 = wglCreateContext(hDC);
wglShareLists(hGLRC, hGLRC2);
tex.LoadFromFile1("2.png");
isRunning = true;
lastRenderThreadID = -1;//默认值
std::thread th([this]() {
wglMakeCurrent(hDC, hGLRC2);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
texAnotherThread.LoadFromFile1("1.jpg");
while (isRunning) //使用程序来控制 isRunning在线程运行之前为true,程序退出为false
{
if (isRenderBegin) //在调用Render的时候为true。
{
Render(-10);
AfterRender();
}
}
});
th.detach(); }
//deltaMillionSeconds是根据时间变化的,每一帧的间隔
void MultiThreadTexture_App::Render(int deltaMillionSeconds)
{
mtx.lock();
if (!isRenderBegin)
isRenderBegin = true; isRenderBegin = true;
if (deltaMillionSeconds == -10)
RenderThreadID = 2;
else
RenderThreadID = 1; if (lastRenderThreadID != -1 && lastRenderThreadID == RenderThreadID)
{//和之前的线程一致
::Sleep(1000); //保证1s调用1次
mtx.unlock();
return;
} glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, width / height, 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 100, 0, 0, 0, 0, 1, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glClearDepth(1000);
glEnable(GL_FILL);
//这里互相使用对方的资源
if (RenderThreadID == 1)
glBindTexture(GL_TEXTURE_2D, texAnotherThread.texId);
else
glBindTexture(GL_TEXTURE_2D, tex.texId); glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(1, 0); glVertex3f(100, 0, 0);
glTexCoord2f(1, 1); glVertex3f(100, 100, 0);
glTexCoord2f(0, 1); glVertex3f(0, 100, 0);
glEnd();
lastRenderThreadID = RenderThreadID;
//休息1秒钟然后
::Sleep(1000);
mtx.unlock();
} void MultiThreadTexture_App::Release()
{
isRunning = false;
}
线程1用的是游戏截图,线程2用的是狗头。而渲染使用对方的资源,效果图如下:
openGL之多线程渲染的更多相关文章
- BGFX多线程渲染
BGFX多线程渲染 1. 多线程基础 1. 并发概念 1. 并发任务简介 在多年以前,在手机.pc端.游戏机等,都是一个单核的CPU.这样,在硬件层面上,处理多个任务的时候,也是把一些任务切分成一些小 ...
- 《图解UE4渲染体系》Part 1 多线程渲染
上回书<Part 0 引擎基础>说到,我们粗略地知道UE4是以哪些类来管理一个游戏场景里的数据的,但这仅仅是我们开始探索UE4渲染体系的一小步. 本回主要介绍UE4渲染体系中比较宏观顶层的 ...
- Unity4、Unity5移动平台多线程渲染在部分安卓手机上会造成闪退
你看到的crash堆栈可能是这样的: SIGSEGV(SEGV_MAPERR) #00 pc 0001276c /system/lib/libc ...
- HTML5触屏版多线程渲染模板技术分享
前言: 了解js编译原理的屌丝们都知道,js是单线程的,想当年各路神仙为了实现js的多线程,为了解决innerHTML输出大段HTML卡页面的顽疾,纷纷设计了诸如假冒的“多线程“实现,我自己也在写开源 ...
- Unity3D 海水多线程渲染算法实现
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...
- 通过OpenGL理解前端渲染原理(1)
一.OpenGL OpenGL,是一套绘制3D图形的API,当然它也可以用来绘制2D的物体.OpenGL有一大套可以用来操作模型和图片的函数,通常编写OpenGL库的人是显卡的制造者.我们买的显卡都支 ...
- DirectX* 11 多线程渲染的性能、方法和实践
对于在 CPU 上运行的 PC 游戏,渲染通常是主要的性能瓶颈:多线程渲染是一种消除瓶颈的有效方法.本文研究了 DirectX* 11 多线程渲染的性能可扩展性,讨论了多线程渲染的两种基本方法,并介绍 ...
- 还在使用OpenGL ES做渲染,你Out了,赶紧来拥抱Vulkan吧~
背景介绍 Vulkan是Khronos组织制定的"下一代"开放的图形显示API.是与DirectX12能够匹敌的GPU API标准. Vulkan是基于AMD的Mantle API ...
- opengl离屏渲染(不需要和窗口绑定,仅当作一个可以渲染一张图片的API使用)+ opencv显示
具体过程参考的是这篇BLOG: http://wiki.woodpecker.org.cn/moin/lilin/swig-glBmpContext 这一片BLOG的代码有个 BOOL SaveBmp ...
- OpenGL中的渲染方式—— GL_TRIANGLE_STRIP
OpenGL值绘制三角形的方式常用的有三种,分别是GL_TRIANGLES.GL_TRIANGLE_STRIP.GL_TRIANGLE_FAN,其效果如依次是: 从左起:第一个方式是GL_TRIANG ...
随机推荐
- 异构数据源同步之数据同步 → datax 再改造,开始触及源码
开心一刻 其实追女生,没那么复杂 只要你花心思,花时间,陪她聊天,带她吃好吃的,耍好玩的,买好看的 慢慢你就会发现什么叫做 打水漂 不说了,我要去陪她看电影了 前情回顾 异构数据源同步之数据同步 → ...
- CSS操作——边框属性
1.border-style(边框风格) 定义边框的风格,值可以有: /* none:没有边框,当border的值为none的时候,系统将会忽略[border-color] hidden:隐藏边框,低 ...
- Hangfire 使用笔记 任务可以分离到别的项目中,无需重复部署Hangfire,通过API方式通信。
"巨人们"的地址 Hangfire Mysql: https://github.com/arnoldasgudas/Hangfire.MySqlStorage 在获取set表数据的 ...
- block专递参数导致野指针引发crash
一.问题引入 近日开发中引入一个随机crash,Crash堆栈如下: Exception Type: SIGSEGV Exception Codes: SEGV_ACCERR at 0x0000000 ...
- windows报错
如果说你dns没有权威的话1.先去long.com上面右键属性把"区域传送给所有服务器打勾"2.右键属性,在名称分析器中,输入要添加为辅助dns的服务器的ip显示解析成功就可以了
- 获取某一个数的2进制位数以及bitmask
举例说明:比如32对应的2进制为2b'100000,对应的bitmask为2b'11111. 实现代码: #include <stdio.h> typedef unsigned char ...
- minos 1.2 内存虚拟化——guest
首发公号:Rand_cs minos 1.2 内存虚拟化--guest 项目来自乐敏大佬:https://github.com/minosproject/minos 本文继续讲述 minos 中的内存 ...
- windows 批处理 检查并启动 windows 服务
windows 批处理 检查并启动 windows 服务 set srvname="YSWindowsService" sc query|find %srvname% && ...
- work04
第一题: 分析以下需求,并用代码实现(每个小需求都需要封装成方法) 1.求两个数据之和(整数 小数),在main方法中打印出来 2.判断两个数据是否相等(整数 小数),在控制台上打印出来 3.获取两个 ...
- 使用spark-sql处理Doris大表关联
背景 最近项目上有一个需求,需要将两张表(A表和B表)的数据进行关联并回写入其中一张表(A表),两张表都是分区表,但是关联条件不包括分区字段. 分析过程 方案一 最朴素的想法,直接关联执行,全表关联, ...