使用GLFW3在OpenGL上下文之间共享纹理不起作用

时间:2014-04-25 18:54:05

标签: c++ opengl glfw

以下程序应该是:

  1. 创建一个不可见的GLFWwindow* masterWindow
  2. 从文件加载纹理,而活动的OpenGL上下文是与masterWindow
  3. 关联的上下文
  4. 创建GLFWwindow* childWindow,在此窗口的OpenGL上下文和masterWindow上下文之间激活共享
  5. childWindow
  6. 中显示纹理的全窗四边形

    然而,这不起作用,即取代纹理,我得到childWindow中显示的图形内存的随机片段。如果我在加载之前将childWindow的上下文设置为当前显示纹理,这就是为什么我认为问题既不是我的着色器也不是我的纹理加载例程(我从这里开始,{{3 }})。 我明白我应该能够分享纹理(请参阅这个问题的回答:https://github.com/DavidEGrayson/ahrs-visualizer/blob/master/png_texture.cpp),那么我做错了什么?如果重要的话,我会使用2008年末的Macbook,安装了NVIDIA 9400m和Mavericks / OpenGL 3.3。

    #include <iostream>
    #define GLEW_STATIC
    #include <glew.h>
    #include <glfw3.h>
    
    const char* vShader =
      "#version 150 core\n"
      "in vec2 vertex;"
      "in vec2 vertexUV;"
      "out vec2 UV;"
      "void main() {gl_Position = vec4(vertex,0,1);UV=vertexUV;}";
    const char* fShader =
     "#version 150 core\n"
     "uniform sampler2D sampler;"
     "in vec2 UV;"
     "out vec4 color;"
     "void main() {color = texture(sampler, UV);}";
    
    GLuint png_texture_load(const char * file_name, unsigned int * width=NULL, unsigned int * height=NULL);
    GLuint make_program(const char* vShader, const char* fShader);
    
    GLFWwindow* masterWindow(NULL);
    
    void create_window_with_texture(GLuint texture)
    {
      GLFWwindow* childWindow(glfwCreateWindow(256,256, "", NULL, masterWindow));
      glfwMakeContextCurrent(childWindow);
    
      // texture appears if loaded from here
      // texture=png_texture_load("rose.png");                                                                                                               
    
      GLfloat vertices[]={-1,-1,1,-1,-1,1,1,1, // window corners in clip space                                                                               
                      0,0,1,0,0,1,1,1};    // corners in uv-space                                                                                        
      GLubyte indices[]={0,2,1,3};             // points for a two triangle strip                                                                            
    
      GLuint vArray,vBuffer,iBuffer;
      glGenVertexArrays(1,&vArray);glBindVertexArray(vArray);
      glGenBuffers(1,&vBuffer);glBindBuffer(GL_ARRAY_BUFFER,vBuffer);
      glGenBuffers(1,&iBuffer);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,iBuffer);
      glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_DYNAMIC_DRAW);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_DYNAMIC_DRAW);
    
      GLuint program(make_program(vShader,fShader));
      glUseProgram(program);
      glUniform1i(glGetUniformLocation(program,"sampler"),0);
      GLuint vertexPtr(GLuint(glGetAttribLocation(program,"vertex")));
      glEnableVertexAttribArray(vertexPtr);
      GLuint vertexUVPtr(GLuint(glGetAttribLocation(program, "vertexUV")));
      glEnableVertexAttribArray(vertexUVPtr);
      glVertexAttribPointer(vertexPtr, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0 );
      glVertexAttribPointer(vertexUVPtr, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)32);
    
      glActiveTexture(GL_TEXTURE0);
      glDisable(GL_DEPTH_TEST);
      glDisable(GL_BLEND);
    
      glBindTexture(GL_TEXTURE_2D,texture);
      glDrawElements(GL_TRIANGLE_STRIP,4, GL_UNSIGNED_BYTE, (GLvoid*)0);
    
      glfwSwapBuffers(childWindow);
    }
    
    int main()
    {
      if (!glfwInit())
        return -1;
      glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
      glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,2);
      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE);
      glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
      glfwWindowHint(GLFW_VISIBLE,GL_FALSE);
      masterWindow=glfwCreateWindow(10,10, "", NULL,NULL);
      glfwWindowHint(GLFW_VISIBLE,GL_TRUE);
      glfwWindowHint(GLFW_SAMPLES, 4);
      glfwMakeContextCurrent(masterWindow);
      glewExperimental = GL_TRUE;
      GLenum err = glewInit();
      if(GLEW_OK!=err)
        return -1;
      glGetError(); // catch benign glewInit() invalid enum error                                                                                            
    
      GLuint texture(0);
      texture=png_texture_load("rose.png");
    
      create_window_with_texture(texture);
    
      std::cin.get();
    
      return 0;
    }
    

1 个答案:

答案 0 :(得分:5)

您必须意识到OpenGL将异步工作。客户端命令排队等待稍后由GL服务器/ GPU处理。通常,如果您访问不可用的数据,GL将通过隐含同步来隐藏用户的这一事实。但是,在处理多个上下文时,必须手动明确地同步操作。调用glFinish()将刷新命令队列并等待命令实际处理完毕。 你的情况有点特殊,通常这种情况出现在多线程程序中,其中一个线程创建/更新GL对象并将hande传输到另一个线程以使用该对象。

我不确定是否会创建另一个上下文是否会或应该导致旧上下文的隐式同步,所以我的猜测是它可能没有(但我没有阅读相关的API文档),并添加了此处可能需要glFinish(或使用其他一些同步方式)。