首页 > 其他分享 >OpenGL之多线程渲染

OpenGL之多线程渲染

时间:2022-10-04 11:44:18浏览次数:52  
标签:多线程 glEnable hGLRC 渲染 OpenGL DEPTH hGLRC2 hDC GL

随着Vulkan的引入,我们的图形技术的发展到达了一个新的顶点,但是呢,我们的老干爹OpenGL作为落日余晖,他在一些Vulkan才有的新功能上,也提供了一些支持。现在我们来讨论一下OpenGL之多线程渲染。

这里要补一补课: windows上最原生的API来使用Opengl 大概流程是这样的详情请见:https://gitee.com/GProReat/codes/bjptwd3hglozmi25esn4v31

1.获取句柄, 在win32或者MFC里面可以直接获取HWND,但是在glut,glfw,sdl等可以通过GetActiveWindow来获取HWND。

2.GetDC

3.PixelFormat的支持,这里可以看刚才代码段里面PixelFormat的设置 

4.创建OpenGL的上下文wglCreateContext, 以及切换到当前的上下文,wglMakeCurrent,传入HGLRC类型的object。

5.初始化操作  各种开关比如: depthTest,AlphaTest,DepthFunc,Texture2等操作。

6.在窗口的绘制的时候,也就是WM_PAINT相应的时候处理绘制。

  这里关键一点是, SwapBuffers。 还有glFlush。

7.资源释放。

note:windows上使用Opengl来渲染,大家可以找MFC或者win32上的windows绘制。

 

接下来开始我们的主题:Opengl多线程渲染:

根据我的测试,HGLRC 的创建于线程无关,也就是说目前HGLRC可以在另外一个线程创建(需要在当前线程wglShareLists),也可以在当前线程创建,

下面为核心代码:  

this->hGLRC2 = wglCreateContext(hDC);
wglShareLists(hGLRC2, hGLRC);
std::thread th([this]() {
    wglMakeCurrent(hDC, hGLRC2);
    //wglShareLists(hGLRC2, hGLRC);
    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]() {
        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();    
        this->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);
        //wglShareLists(hGLRC2, hGLRC);
        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);
    this->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);
        //wglShareLists(hGLRC2, hGLRC);
        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);
    //wglShareLists()
    this->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);
        //wglShareLists(hGLRC2, hGLRC);
        texAnotherThread.LoadFromFile1("1.jpg");
        cout << "加载完成" << endl;
        while (isRunning)  //使用程序来控制 isRunning在线程运行之前为true,程序退出为false
        {
            if (isRenderBegin)   //在调用Render的时候为true。
            {
                Render(-10);
                AfterRender();
            }
        }
        });
    th.detach();
    //这两个参数顺序是和渲染结果有关系的
//    wglMakeCurrent(hDC, hGLRC);

}

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渲染,第2s线程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);
    tex.LoadFromFile1("2.png");
    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();

}
//deltaMillionSeconds是根据时间变化的,每一帧的间隔
void MultiThreadTexture_App::Render(int deltaMillionSeconds)
{
    if (!isRenderBegin)
        isRenderBegin = true;

    if (RenderThreadID == 1 && deltaMillionSeconds != -10)
        return;
    if (RenderThreadID == 2 && deltaMillionSeconds == -10)
        return;
    
    isRenderBegin = true;
    if (deltaMillionSeconds == -10)
        RenderThreadID = 2;
    else
        RenderThreadID = 1;

    //if (deltaMillionSeconds != -10) return;    //只保证线程2的绘制可以成功 否则返回
    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();
    //休息1秒钟然后
    ::Sleep(1000);
}

线程1用的是游戏截图,线程2用的是狗头。而渲染使用对方的资源,给大家来个效果图:

 

标签:多线程,glEnable,hGLRC,渲染,OpenGL,DEPTH,hGLRC2,hDC,GL
From: https://www.cnblogs.com/yang131/p/16753516.html

相关文章

  • 从输入URL到渲染的过程中到底发生了什么?
    CDN缓存DNSTCP三次握手、四次挥手浏览器渲染过程输入URL到页面渲染过程的一些优化下面我将“从输入URL到渲染的全过程”大概的描述出来,再对其过程加以解释,了解过程......
  • 程序、进程和线程 Java多线程的状态【杭州多测师】【杭州多测师_王sir】
    CPU是以时间片的方式为进程分配CUP处理时间的,如果当一个进程同时要完成几件事的时候,如当从网上下载文件的时候,需要一边下载一边显示进度而且还要一边保存,如果按照单线程的......
  • 计算机视觉与图形学-神经渲染专题-StructNeRF室内重建
    (说明:如果您认为下面的文章对您有帮助,请您花费一秒时间点击一下最底部的广告以此来激励本人创作,谢谢!!!)神经辐射场(NeRF)通过密集捕获的输入图像实现照片真实感视图合成。然而,......
  • [CG从零开始] 4. pyopengl 绘制一个正方形
    在做了1~3的基础工作后,我们的开发环境基本OK了,我们可以开始尝试利用pyopengl来进行绘制了。本文主要有三个部分利用glfw封装窗口类,并打开窗口;封装shader类,进......
  • 12_列表渲染
    1.基本列表<!DOCTYPEhtml><html><head><metacharset="UTF-8"/><title>基本列表</title><scripttype="text/javascript"src="../j......
  • java多线程--6 死锁问题 锁Lock
    java多线程--6死锁问题锁Lock死锁问题多个线程互相抱着对方需要的资源,然后形成僵持死锁状态packagecom.ssl.demo05;publicclassDeadLock{publicstatic......
  • java多线程---4 线程同步介绍及不安全案例说明
    java多线程---4线程同步介绍及不安全案例说明线程同步并发:同一个对象被多个线程同时操作。处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这......
  • 2022神经渲染的进展综述
    神经渲染的进展综述来源:​​https://zhuanlan.zhihu.com/p/567654308​​EuroGraphics‘2022综述论文“AdvancesinNeuralRendering“,2022年3月,作者来自MPI、谷歌研究、E......
  • java多线程--3 线程状态、线程方法、线程类型
    java多线程--3线程状态、线程方法、线程类型线程状态创建状态:**就绪状态:**进入状态:创建状态:启动线程阻塞状态:阻塞解除运行状态:释放CPU资源阻塞状态:......
  • 肖sir_Java 多线程___Java 网络协议__20
    Java网络编程1.1网络编程介绍网络编程指的就是直接或间接地通过网络协议与其他计算机进行通信。网络编程中的基础概念:1,网络分类2,网络编程模型3,网络协议4,套接字和......