我正在使用 OpenGL 和 SDL2 在屏幕上绘制一个三角形。
我的问题出在着色器编译阶段。
以下是我遇到的错误:
错误::着色器::顶点::编译失败 0:1(10):错误:不支持 GLSL 3.30。支持的版本有:1.10、1.20、1.30、1.40、1.00 ES 和 3.00 ES
错误::着色器::片段::编译失败 0:1(10):错误:不支持 GLSL 3.30。支持的版本有:1.10、1.20、1.30、1.40、1.00 ES 和 3.00 ES
错误::着色器::程序::LINKING_FAILED 错误:与未编译/非专业着色器链接错误:与未编译/非专业着色器链接
我在一些论坛上看到人们有相同的错误消息,他们被告知默认情况下 MESA 将切换到兼容性配置文件而不是核心配置文件,但问题是我已经明确告诉 SDL2 创建核心上下文配置文件:
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
顺便说一句,我已经在同一台计算机上使用了 OpenGL 版本 3.30 和 GLSL 3.30,将其与 GLFW 和 GLAD 一起使用,没有任何问题,但现在我只想让它与 SDL2 和 GLEW 一起使用。
这是
glxinfo | grep "version"
命令的结果:
server glx version string: 1.4
client glx version string: 1.4
GLX version: 1.4
Max core profile version: 3.3
Max compat profile version: 3.1
Max GLES1 profile version: 1.1
Max GLES[23] profile version: 3.1
OpenGL core profile version string: 3.3 (Core Profile) Mesa 19.1.7
OpenGL core profile shading language version string: 3.30
OpenGL version string: 3.1 Mesa 19.1.7
OpenGL shading language version string: 1.40
OpenGL ES profile version string: OpenGL ES 3.1 Mesa 19.1.7
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10
GL_EXT_shader_implicit_conversions, GL_EXT_shader_integer_mix,
以及我的主要功能的内容:
int main(int argc, char* argv[])
{
// =====> INIT VARS
SDL_Window* window;
SDL_Renderer* renderer;
SDL_GLContext glContext;
GLenum err;
// INIT VARS <=====
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << SDL_GetError() << std::endl;
return -1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = createWindow(WIDTH, HEIGHT, "TP_PROGRAMMATION_3D");
if(window == nullptr)
{
std::cout << SDL_GetError() << std::endl;
SDL_Quit();
return -1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(renderer == nullptr)
{
std::cout << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// OPENGL CONTEXT FOR THE WINDOW
glContext = SDL_GL_CreateContext(window);
// GLEW INIT
err = glewInit();
if(err != GLEW_OK)
{
std::cout << glewGetErrorString(err) << std::endl;
SDL_GL_DeleteContext(glContext);
SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// EVERYTHING'S FINE : TIME TO PAINT IT GREY
glViewport(0, 0, WIDTH, HEIGHT);
SDL_GL_SetSwapInterval(1);
glClearColor(Color::LIGHT_GREY[0], Color::LIGHT_GREY[1], Color::LIGHT_GREY[2], Color::LIGHT_GREY[3]);
// OPENGL DRAWING CALLS AND MAIN DRAWING LOOP
draw_gl(window);
// END
SDL_GL_DeleteContext(glContext);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
和着色器代码:
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
" color = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}";
好吧,我已经开始工作了,但说实话,我不知道为什么现在我做了一些小改动就可以工作了,因为它看起来几乎是一样的。
这是代码:
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <iostream>
#include "color.hpp"
#define WIDTH 800
#define HEIGHT 600
float triangle[] =
{
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
" color = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}";
SDL_Window* createWindow(int w, int h, std::string title)
{
SDL_Window* window = nullptr;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << SDL_GetError() << std::endl;
return nullptr;
}
// OPENGL VERSION
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
// DOUBLE BUFFER
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
if(w == 0 and h == 0)
{
window = SDL_CreateWindow(
title.c_str(),
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
w,
h,
SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN);
}
window = SDL_CreateWindow(
title.c_str(),
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
w,
h,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if(window == nullptr)
{
std::cout << SDL_GetError() << std::endl;
return nullptr;
}
return window;
}
int processInput()
{
SDL_Event event;
if(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
return -1;
if(event.type == SDL_WINDOWEVENT_RESIZED)
glViewport(0, 0, event.window.data1, event.window.data2);
}
return 1;
}
void draw_gl(SDL_Window* window)
{
// VAO
GLuint vao1;
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
// VBO for a triangle
GLuint vbo1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);
// VertexAttribPointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
// Fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
// Check for compile errors if any
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(! success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(! success)
{
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if(! success)
{
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glUseProgram(shaderProgram);
while(true)
{
if(processInput() == -1)
break;
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(window);
}
}
int main(int argc, char* argv[])
{
// =====> INIT VARS
SDL_Window* window;
SDL_Renderer* renderer;
SDL_GLContext glContext;
GLenum err;
// INIT VARS <=====
window = createWindow(WIDTH, HEIGHT, "OPENGL");
if(window == nullptr)
{
SDL_Quit();
return -1;
}
// OPENGL CONTEXT FOR THE WINDOW
glContext = SDL_GL_CreateContext(window);
// GLEW INIT
glewExperimental = true;
err = glewInit();
if(err != GLEW_OK)
{
std::cout << glewGetErrorString(err) << std::endl;
SDL_GL_DeleteContext(glContext);
SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// EVERYTHING'S FINE : TIME TO PAINT IT GREY
glViewport(0, 0, WIDTH, HEIGHT);
SDL_GL_SetSwapInterval(1);
glClearColor(Color::LIGHT_GREY[0], Color::LIGHT_GREY[1], Color::LIGHT_GREY[2], Color::LIGHT_GREY[3]);
// OPENGL DRAWING CALLS AND MAIN DRAWING LOOP
draw_gl(window);
// END
SDL_GL_DeleteContext(glContext);
//SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
对于仍然遇到此问题的任何人,因为 OP 不确定到底发生了什么变化:
我发现在 MacOS Ventura 上,我必须在运行 SDL_Init 之前指定主要/次要,并且必须在之后设置配置文件掩码。尝试在 init 之后设置版本将导致无法绑定正确的 OpenGL 版本,而尝试在 init 之前设置配置文件掩码将导致 OP 的错误。
示例片段:
int main() {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window * window = SDL_CreateWindow(...