随着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之多线程渲染的更多相关文章

  1. BGFX多线程渲染

    BGFX多线程渲染 1. 多线程基础 1. 并发概念 1. 并发任务简介 在多年以前,在手机.pc端.游戏机等,都是一个单核的CPU.这样,在硬件层面上,处理多个任务的时候,也是把一些任务切分成一些小 ...

  2. 《图解UE4渲染体系》Part 1 多线程渲染

    上回书<Part 0 引擎基础>说到,我们粗略地知道UE4是以哪些类来管理一个游戏场景里的数据的,但这仅仅是我们开始探索UE4渲染体系的一小步. 本回主要介绍UE4渲染体系中比较宏观顶层的 ...

  3. Unity4、Unity5移动平台多线程渲染在部分安卓手机上会造成闪退

    你看到的crash堆栈可能是这样的: SIGSEGV(SEGV_MAPERR)   #00  pc 0001276c                          /system/lib/libc ...

  4. HTML5触屏版多线程渲染模板技术分享

    前言: 了解js编译原理的屌丝们都知道,js是单线程的,想当年各路神仙为了实现js的多线程,为了解决innerHTML输出大段HTML卡页面的顽疾,纷纷设计了诸如假冒的“多线程“实现,我自己也在写开源 ...

  5. Unity3D 海水多线程渲染算法实现

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  6. 通过OpenGL理解前端渲染原理(1)

    一.OpenGL OpenGL,是一套绘制3D图形的API,当然它也可以用来绘制2D的物体.OpenGL有一大套可以用来操作模型和图片的函数,通常编写OpenGL库的人是显卡的制造者.我们买的显卡都支 ...

  7. DirectX* 11 多线程渲染的性能、方法和实践

    对于在 CPU 上运行的 PC 游戏,渲染通常是主要的性能瓶颈:多线程渲染是一种消除瓶颈的有效方法.本文研究了 DirectX* 11 多线程渲染的性能可扩展性,讨论了多线程渲染的两种基本方法,并介绍 ...

  8. 还在使用OpenGL ES做渲染,你Out了,赶紧来拥抱Vulkan吧~

    背景介绍 Vulkan是Khronos组织制定的"下一代"开放的图形显示API.是与DirectX12能够匹敌的GPU API标准. Vulkan是基于AMD的Mantle API ...

  9. opengl离屏渲染(不需要和窗口绑定,仅当作一个可以渲染一张图片的API使用)+ opencv显示

    具体过程参考的是这篇BLOG: http://wiki.woodpecker.org.cn/moin/lilin/swig-glBmpContext 这一片BLOG的代码有个 BOOL SaveBmp ...

  10. OpenGL中的渲染方式—— GL_TRIANGLE_STRIP

    OpenGL值绘制三角形的方式常用的有三种,分别是GL_TRIANGLES.GL_TRIANGLE_STRIP.GL_TRIANGLE_FAN,其效果如依次是: 从左起:第一个方式是GL_TRIANG ...

随机推荐

  1. ThreadLocal原理详解——终于弄明白了ThreadLocal

    目录 概述 API介绍 ThreadLocal的理解 ThreadLocal的原理分析 总结 概述 在java学习生涯中可能很多人都会听到ThreadLocal变量,从字面上理解ThreadLocal ...

  2. 什么是Token?为什么大模型要计算Token数

    本文分享自华为云社区<[技术分享]什么是Token?为什么GPT基于Token定价>,作者:开天aPaaS小助手Tracy. 在使用LLM大模型时,我们经常会遇到一个关键词,叫:Token ...

  3. Django——自定义前端上传文件

    from django.db import models class Mytb(models.Model): file = models.FileField(upload_to='uploads/') ...

  4. WPF+Emgucv实现在图像上画出感兴趣的区域 并进行掩膜获取 得到图像均值 和简单的 漫水填充

    <Grid.RowDefinitions></Grid.RowDefinitions> <Grid> <UniformGrid Columns="2 ...

  5. .net版OCR紧随PP-OCRv3重磅发布

    .net版OCR地址PaddleOCRSharp PaddleOCRSharp是一个基于PaddleOCR的C++代码修改并封装的.NET的工具类库.包含文本识别.文本检测.基于文本检测结果的统计分析 ...

  6. 一周万星的文本转语音开源项目「GitHub 热点速览」

    上周的热门开源项目让我想起了「图灵测试」,测试者在不知道对面是机器还是人类的前提下随意提问,最后根据对方回复的内容,判断与他们交谈的是人还是计算机.如果无法分辨出回答者是机器还是人类,则说明机器已通过 ...

  7. 纯css+html做emoji动态表情

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...

  8. 「TAOI-2」Ciallo~(∠・ω< )⌒★ 题解

    「TAOI-2」Ciallo-(∠・ω< )⌒★ 题解 不难发现,答案可以分成两种: 整段的 中间删一点,两端凑一起的 考虑分开计算贡献. 如果 \(s\) 中存在子串等于 \(t\),那么自然 ...

  9. Flarum 安装和使用教程

    随着开源社区的日益繁荣,人们对社区品质的要求也越来越高.传统的 BBS 论坛模式已经难以满足现代用户对美观.便捷.互动性的需求.搭建一个现代化的高品质社区,成为许多网站管理者的迫切需求和共同挑战. 今 ...

  10. 博客更换新域名为52ecy.cn

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 博客更换新域名为52ecy.cn 日期:2017-10-2 ...