【发布时间】:2015-10-16 20:26:24
【问题描述】:
我目前正在学习 OpenGL 3.X,我正在使用 ubuntu 14.04。 我正在使用 C 语言创建我的应用程序和 SDL2 库。
命令
glxinfo | grep "OpenGL version"
给我以下输出
OpenGL version string: 3.0 Mesa 10.1.3
我的着色器创建有问题,这里是加载/编译/链接着色器的代码:
typedef struct s_shader
{
GLuint vertex_id;
GLuint fragment_id;
GLuint program_id;
} t_shader;
t_shader *create_shader(const char *vertex_file, const char *fragment_file)
{
t_shader *new_shader;
new_shader = (t_shader *)malloc(sizeof(t_shader));
if (new_shader)
{
new_shader->vertex_id = glCreateShader(GL_VERTEX_SHADER);
new_shader->fragment_id = glCreateShader(GL_FRAGMENT_SHADER);
new_shader->program_id = glCreateProgram();
load_shader(new_shader, vertex_file, fragment_file);
glCompileShader(new_shader->vertex_id);
glCompileShader(new_shader->fragment_id);
glAttachShader(new_shader->program_id, new_shader->vertex_id);
glAttachShader(new_shader->program_id, new_shader->fragment_id);
glLinkProgram(new_shader->program_id);
}
return (new_shader);
}
void load_shader(t_shader *shader,const char *vertex_file,const char *fragment_file)
{
char *vertex_file_content;
char *fragment_file_content;
int vertex_len;
int fragment_len;
vertex_file_content = NULL;
fragment_file_content = NULL;
vertex_file_content = get_file_content(vertex_file);
fragment_file_content = get_file_content(fragment_file);
vertex_len = strlen(vertex_file_content);
fragment_len = strlen(fragment_file_content);
glShaderSource(shader->vertex_id, 1, (const GLchar **)&vertex_file_content, &vertex_len);
glShaderSource(shader->fragment_id, 1, (const GLchar **)&fragment_file_content, &fragment_len);
}
我在每次 gl 调用后使用 glGetError(),我得到的第一个错误代码是 glLinkProgram() 调用,它给了我一个 GL_INVALID_OPERATION(错误 1282)。 我试图用这样的方式输出日志错误:
GLchar buff[1024];
GLsizei length;
glGetProgramInfoLog(new_shader->program_id, 1024, &length, buff);
printf("length:%i\nlog:'%s'\n", length, buff);
但是日志是空的。
我对片段和顶点着色器都使用了 glIsShader(),它返回 GL_TRUE。 我还在 glCompileShader() 之后使用 glGetShaderInfoLog() 并且片段和顶点着色器的日志都是空的。 我在文档中读到:
如果程序不是程序对象,则生成GL_INVALID_OPERATION。
如果 program 是当前活动的程序对象并且转换反馈模式处于活动状态,则生成 GL_INVALID_OPERATION。
我的程序似乎是一个程序对象,因为 glCreateProgram 返回一个非空值。 此时代码中没有活动的程序对象。
窗口和 OpenGL 上下文:
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow("My OpenGl", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (window)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
gl_context = SDL_GL_CreateContext(window);
这里是读取文件内容的函数:
char *get_file_content(const char *file_name)
{
FILE *file;
char *file_content;
long file_size;
file = NULL;
file_content = NULL;
file_size = 0;
file = fopen(file_name, "r");
if (file)
{
fseek(file, 0, SEEK_END);
file_size = ftell(file);
fseek(file, 0, SEEK_SET);
file_content = (char *)malloc(sizeof(char) * file_size + 1);
if (file_content)
{
memset(file_content, '\0', file_size);
fread(file_content, sizeof(char), file_size, file);
file_content[file_size + 1] = '\0';
}
fclose(file);
}
return (file_content);
}
片段着色器来源:
#version 150 core
in vec3 color;
out vec4 out_Color;
void main()
{
out_Color = vec4(1.0f, 1.0f, 1.0f, 1.0);
}
顶点着色器来源:
#version 150 core
in vec3 in_Vertex;
in vec3 in_Color;
uniform mat4 projection;
uniform mat4 modelview;
out vec3 color;
void main()
{
gl_Position = projection * modelview * vec4(in_Vertex, 1.0);
color = in_Color;
}
还有其他方法可以调试 glLinkProgram 吗?
【问题讨论】:
-
还有许多其他条件可能会触发该错误。检查着色器编译状态和日志。如果您真的 oosted 着色器源代码,它也可能会有所帮助。
-
你能发布顶点和片段着色器的源代码吗?你用 glGetShaderInfoLog 检查过他们的编译日志吗?
-
我编辑了问题,并添加了片段和顶点着色器源。我还使用 glGetShaderInfoLog() 和 glIsShader() 进行调试。
-
这不太可能导致您的问题,但您正在写入超出
get_file_content()中分配内存的一个字节。零终止符应指定为file_content[file_size] = '\0';。