关闭一个窗口并在新窗口中绘制相同的内容

时间:2014-10-22 08:11:47

标签: opengl glfw

为了创造一种屏保 我希望能够:

  1. 在GLFW窗口中全屏绘制内容
  2. 关闭窗口
  3. 等一会儿
  4. 在新窗口中重绘相同的内容
  5. 我可以轻松地做到这一点,但效率不高。事实上,我必须再次进行所有初始化(上下文创建,vao,vbo,编译着色器......),我不重用任何东西。 如果窗口刚刚被用户隐藏,那就好了,但显然,你不能用GLFW隐藏全屏窗口。

    有谁知道什么可以安全再次使用,以及如何使用?


    也许代码(不重新打开新窗口)可以帮助您回答我的问题:

    ...
    
    int main (int argc, char *argv[])
    {   
        GLFWwindow* window;
        const GLFWvidmode *mode;
        GLenum glew_status;
    
        float vertices[] = {
            -1.0f,  1.0f,
             1.0f,  1.0f,
            -1.0f, -1.0f,
             1.0f, -1.0f
        };
        GLuint vao;
        GLuint vbo;
        GLuint vertexShader;
        GLuint fragmentShader;
        GLuint shaderProgram;
    
        GLint posAttrib;
        GLint Resolution;
        GLint Time;
    
    
        glfwSetErrorCallback(error_callback);
    
        if (!glfwInit())
            return 1;
    
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    
        mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        window = glfwCreateWindow(mode->width, mode->height, "OpenGL", glfwGetPrimaryMonitor(), NULL); // Fullscreen
    
        if (!window) {
            glfwTerminate();
            return 2;
        }
    
        glfwMakeContextCurrent(window);
    
        glfwSetKeyCallback(window, key_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_HIDDEN);
    
        // Initialize GLEW
        glewExperimental = GL_TRUE;
        glew_status = glewInit();
        if (glew_status != GLEW_OK) {
            //Problem: glewInit failed, something is seriously wrong.
            fprintf(stderr,"glewInit failed, Error: %s\n", glewGetErrorString(glew_status));
            return 3;
        }
    
        // Create Vertex Array Object
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
    
        // Create a Vertex Buffer Object and copy the vertex data to it
        glGenBuffers(1, &vbo);
    
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
        // Create and compile the vertex shader
        vertexShader = LoadShader("/home/celestin/Documents/C/OpenGL/my_openGL/simple_shader/triangle.v.glsl",GL_VERTEX_SHADER);
        fragmentShader = LoadShader("/home/celestin/Documents/C/OpenGL/my_openGL/simple_shader/triangle.f.glsl",GL_FRAGMENT_SHADER);
    
        // Link the vertex and fragment shader into a shader program
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
        glBindFragDataLocation(shaderProgram, 0, "outColor");
        glLinkProgram(shaderProgram);
        glUseProgram(shaderProgram);
    
        // Specify the layout of the vertex data
        posAttrib = glGetAttribLocation(shaderProgram, "position");
        glEnableVertexAttribArray(posAttrib);
        glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
    
        Resolution = glGetUniformLocation(shaderProgram, "resolution");
        Time = glGetUniformLocation(shaderProgram, "time");
    
        // Clear the screen to black
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glfwSetTime(0.0);
    
        // Loop until the user closes the window
        while (!glfwWindowShouldClose(window))
        {
    
            glUniform1f(Time,glfwGetTime());
            glUniform2f(Resolution,mode->width,mode->height);
    
            glClear(GL_COLOR_BUFFER_BIT);
    
            // Draw a triangle from the 3 vertices
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
            // Swap front and back buffers
            glfwSwapBuffers(window);
    
            // Poll for and process events
            glfwPollEvents();
        }
    
        glDeleteProgram(shaderProgram);
        glDeleteShader(fragmentShader);
        glDeleteShader(vertexShader);
    
        glDeleteBuffers(1, &vbo);
        glDeleteVertexArrays(1, &vao);
    
        glfwDestroyWindow(window);
        glfwTerminate();
        return 0;
    }
    

1 个答案:

答案 0 :(得分:0)

确实无法创建最初隐藏的全屏GLFW窗口。但是,如果您使用的是足够现代的OpenGL,您可以假设支持framebuffer对象,则可以使用隐藏的窗口模式窗口渲染到纹理。窗口默认帧缓冲区的大小无关紧要。

如果您想在窗口之间等待,可以将此纹理的图像数据保存到RAM中并保留以供日后使用。

如果你不介意生命重叠,你可以通过上下文共享将这个纹理分享到新窗口的上下文中。这是通过glfwCreateWindow的最后一个参数完成的。上下文共享还将承载许多其他对象类型:

  

可以在上下文之间共享的对象包括缓冲对象,程序   和着色器对象,渲染缓冲对象,采样器对象,同步对象和纹理   对象(名为零的纹理对象除外)。    - OpenGL 4.5 Specification, chapter 5