SFML 中 2 个窗口之间的上下文共享

问题描述 投票:0回答:1

当使用 sfml 创建 2 个窗口时,我发现只有其中一个窗口显示三角形,具体取决于下面代码中调用的 window.setActive() 函数。其中一个窗口完全是纯色的。这是复制问题的代码

#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <iostream>

// Vertex Shader Source
const char* vertexShaderSource = R"(
#version 460 core
layout (location = 0) in vec3 position;
void main()
{
    gl_Position = vec4(position, 1.0);
}
)";

// Fragment Shader Source
const char* fragmentShaderSource = R"(
#version 460 core
out vec4 color;
void main()
{
    color = vec4(0.2, 0.8, 0.2, 1.0); // Green color
}
)";

// Triangle Vertex Data
const float triangleVertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

// Compile and link shaders
GLuint CompileShaderProgram() {
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    GLint success;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        std::cerr << "Vertex Shader Compilation Error: " << infoLog << std::endl;
        return 0;
    }

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        std::cerr << "Fragment Shader Compilation Error: " << infoLog << std::endl;
        return 0;
    }

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        char infoLog[512];
        glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        std::cerr << "Shader Program Linking Error: " << infoLog << std::endl;
        return 0;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return shaderProgram;
}

int main() {
    // Context settings for OpenGL 4.6
    sf::ContextSettings settings;
    settings.majorVersion = 4;
    settings.minorVersion = 6;
    settings.attributeFlags = sf::ContextSettings::Core;

    // Create the first window
    sf::Window window1(sf::VideoMode(800, 600), "Window 1", sf::Style::Default, settings);
    
    // Set the first window's context as active
    window1.setActive(true);

    // Initialize GLEW after activating the first context
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        std::cerr << "GLEW Initialization Error: " << glewGetErrorString(err) << std::endl;
        return -1;
    }

    // OpenGL Initialization
    GLuint shaderProgram = CompileShaderProgram();
    if (!shaderProgram) return -1;

    GLuint VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // Create the second window, sharing the context of the first window
    sf::Window window2(sf::VideoMode(800, 600), "Window 2", sf::Style::Default, settings);
    window1.setActive(true); // Ensure the second window's context is active after creation

    bool running1 = true, running2 = true;
    sf::Event event;

    while (running1 || running2) {
        if (running1) {
            window1.setActive(true);

            // Event handling
            while (window1.pollEvent(event)) {
                if (event.type == sf::Event::Closed) {
                    running1 = false;
                    window1.close();
                }
            }

            // Render triangle in window 1
            glClearColor(0.1f, 0.1f, 0.4f, 1.0f); // Blue background
            glClear(GL_COLOR_BUFFER_BIT);

            glUseProgram(shaderProgram);
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, 3);

            window1.display();
        }

        if (running2) {
            window2.setActive(true);

            // Event handling
            while (window2.pollEvent(event)) {
                if (event.type == sf::Event::Closed) {
                    running2 = false;
                    window2.close();
                }
            }

            // Render triangle in window 2
            glClearColor(0.4f, 0.1f, 0.1f, 1.0f); // Red background
            glClear(GL_COLOR_BUFFER_BIT);

            glUseProgram(shaderProgram);
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, 3);

            window2.display();
        }
    }

    // Cleanup
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);

    return 0;
}

我原本希望在两个窗口中都绘制三角形,但只显示了其中一个。我将 window1.setActive(true) 更改为 window2.setActive(true) ,这导致第二个窗口显示三角形,而不是第一个窗口。

c++ opengl window sfml
1个回答
0
投票

所有问题的答案都在参考中:

另一件事要知道的是 SFML 创建的所有 OpenGL 上下文 分享他们的资源。这意味着您可以创建纹理或 任何上下文处于活动状态的顶点缓冲区,并将其与任何其他上下文一起使用。这 也意味着您不必重新加载所有 OpenGL 资源 当您重新创建窗口时。只能共享可共享的 OpenGL 资源 在上下文之间共享。不可共享资源的一个示例是 顶点数组对象。

最重要的是最后一句话。 VAO 不可共享。因此,在创建第二个窗口后,将其上下文设为当前上下文,创建新的 VAO 并用之前创建的可共享的 VBO 填充它:

// Create the second window, sharing the context of the first window
sf::Window window2(sf::VideoMode(800, 600), "Window 2", sf::Style::Default, settings);
window2.setActive(true);

GLuint VAO2;
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
    
window1.setActive(true); // Ensure the second window's context is active after creation

在渲染第二个窗口时,不要忘记在主循环代码中启用第二个 VAO:

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO2);
        glDrawArrays(GL_TRIANGLES, 0, 3);

这一切都会根据需要为您提供两个正在渲染的三角形。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.