使用OpenGL进行GLFW 3.0资源加载

时间:2013-07-22 03:07:36

标签: multithreading opengl glfw

我已经开始在单独的线程上进入稍微压倒性的OpenGL资源加载场景,因此主线程可以继续渲染对象。介入时,我注意到GLFW在一个月后发布了更新版本,更容易进行上下文管理。

然而,使用glfwMakeContextCurrent()我无法实现这一点。在加载线程中我使用此函数,在完成后我再次添加它,以便主线程接收上下文以供进一步使用。这不允许我创建和编译着色器或任何其他OpenGL相关的创建。

更新:

需要做什么才能在这种情况下使用GLFW?由于GLFW是可移植的,我很乐意使用包含它的代码。我不知道准备一个保持GLFW API的线程的必要步骤。

正如this博客文章所述,我需要创建两个带有OpenGL上下文的线程(不是相同的上下文; D),然后共享信息。但是,显示的说明是特定于平台的。那么我怎样才能使用GLFW,所以示例中的步骤尽可能与平台无关?

1 个答案:

答案 0 :(得分:17)

使用share上的glfwCreateWindow()参数:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <chrono>
#include <thread>
#include <atomic>

// reload shared VBO with random data every second
void MyThread( GLFWwindow* win, GLuint vbo, std::atomic< bool >& running )
{
    glfwMakeContextCurrent( win );
    glewInit();
    while( running )
    {
        float temp[ 512 ];
        for( size_t i = 0; i < 512; i+=2 )
        {
            temp[ i+0 ] = static_cast< float >( rand() % 600 );
            temp[ i+1 ] = static_cast< float >( rand() % 600 );
        }

        glBindBuffer( GL_ARRAY_BUFFER, vbo );
        glBufferData( GL_ARRAY_BUFFER, sizeof( float ) * 512, temp, GL_DYNAMIC_DRAW );
        glBindBuffer( GL_ARRAY_BUFFER, 0 );

        // oddly important, might need to be glFinish()
        glFlush();

        std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
    }
}

int main( int argc, char** argv )
{
    if( !glfwInit() )
        return -1;

    glfwWindowHint( GLFW_VISIBLE, GL_FALSE );
    GLFWwindow* threadWin = glfwCreateWindow( 1, 1, "Thread Window", NULL, NULL );

    glfwWindowHint( GLFW_VISIBLE, GL_TRUE );
    GLFWwindow* window = glfwCreateWindow( 600, 600, "Hello World", NULL, threadWin );
    glfwMakeContextCurrent( window );
    glewInit();

    // load shared VBO with dummy data
    float temp[ 512 ] = { 0 };
    GLuint vbo;
    glGenBuffers( 1, &vbo );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, sizeof( float ) * 512, temp, GL_DYNAMIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    std::atomic< bool > running( true );
    std::thread aThread( MyThread, threadWin, vbo, std::ref( running ) );

    while( !glfwWindowShouldClose( window ) )
    {
        glfwPollEvents();

        glClear( GL_COLOR_BUFFER_BIT );

        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glOrtho( 0, 600, 0, 600, -1, 1 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        glEnableClientState( GL_VERTEX_ARRAY );   
        glBindBuffer( GL_ARRAY_BUFFER, vbo );
        glVertexPointer( 2, GL_FLOAT, 0, 0 );
        glColor3ub( 255, 0, 0 );
        glDrawArrays( GL_LINES, 0, 256 );
        glBindBuffer( GL_ARRAY_BUFFER, 0 );
        glDisableClientState( GL_VERTEX_ARRAY );   

        std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
        glfwSwapBuffers( window );
    }

    running = false;
    aThread.join();

    glfwTerminate();
    return 0;
}