使用 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),结果第二个窗口显示了三角形,而不是第一个窗口。
编辑1:正如rafix07所回答的,VAO是不可共享的对象,我们需要复制它。
您的问题的所有答案均参考:
最重要的是最后一句。VAO 不可共享。因此,在创建第二个窗口后,将其上下文设为当前上下文,创建新的 VAO 并用先前创建的可共享的 VBO 填充它:
在渲染第二个窗口时,不要忘记在主循环代码中启用第二个 VAO:
这一切都为您提供了两个所需的三角形渲染。