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 ...
随机推荐
- Nginx 修饰符 Location 详解
概述 location 指令可以用在虚拟服务器 server 部分,并且意味着提供来自客户端的 URI 或者内部重定向访问. location 的定义如下: location [modifier] u ...
- Android 12(S) MultiMedia(十二)MediaCodecList & IOmxStore
这节来了解下MediaCodecList相关代码路径: frameworks/av/media/libstagefright/MediaCodecList.cpp frameworks/av/medi ...
- this,构造器,static,final,单例模式
this关键字 在java中this是一个引用变量,即指向当前对象地址的引用(指针),→可以把this当作当前对象,便于更好的索引. this() 实际是调用了当前对象的构造器 1. 引用当前对象的属 ...
- Python 将Word/ Exce/ PDF/ PPT文档转为OFD文档
OFD(Open Fixed-layout Document )是我国自主制定的一种开放版式文件格式标准.OFD文档具有不易被篡改.格式独立.版式固定等特点,目前常用于政府公文.金融.电子发票等领域. ...
- 无需搭建环境,零门槛带你体验Open-Sora文生视频应用
本文分享自华为云社区<Open-Sora 文生视频原来在AI Gallery上也能体验了>,作者:码上开花_Lancer. 体验链接:Open-Sora 文生视频案例体验 不久前,Open ...
- this的二种使用方式
package com.ht.TestThis; public class TestThisKey { public static void main(String[] args) { // TODO ...
- JavaScript语法形式3 外链式
定义 script 标签,在 script 标签中,通过src属性导入外部js文件,并且加载执行外部js文件中国的程序代码内容 因为代码执行顺序问题,一般定义 script 标签 在 body标签 ...
- webpack配置css预处理
webpack默认只支持js的打包,不支持其它类型,为了让它支持样式的打包就需要加载一些loader 打包css文件 在webpack中配置对应的loader 在入口js文件中通过import导入样式 ...
- 算法金 | LSTM 原作者带队,一个强大的算法模型杀回来了
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 时间拉回 2019 年,有「计算机界诺贝尔奖」之称图灵奖获得者公布,深度学习三巨头:Y ...
- C#.NET 使用Windows证书库中的证书
public static X509Certificate2 GetCertificate(string commonName, StoreName storeName) { X509Certific ...