我有一个方法,可以从两个给定的字符串(顶点和片段着色器文件名)创建并返回着色器程序。起初,它工作得很好,编译和链接成功,然后随机失败,给我一个Unicode表情符号的错误信息。
示例代码:
# define GLEW_STATIC
# define NO_SDL_GLEXT
# include <GL/glew.h>
# include <SDL2/SDL.h>
# include <SDL2/SDL_opengl.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define BUFFSIZE 1024
# define MAXSIZE 1048576
typedef struct Shader {
unsigned int data;
} Shader;
char* loadshader(char*);
Shader* createShader(char* vertexfile, char* fragmentfile) {
const char* vertexcode = loadshader(vertexfile);
unsigned int vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vertexcode, NULL);
glCompileShader(vertex);
{
char log[512]; int success; glGetProgramiv(vertex, GL_COMPILE_STATUS, &success);
printf("Vertex File Name: %sn", vertexfile); printf("Vertex Code: %dn", vertexcode); printf("Vertex Value: %dn", vertex);
glGetProgramInfoLog(vertex, 512, NULL, log);
printf("Vertex Shader Failed to Compile!n> OpenGL Error: %snn - - - - - nn", log);
}
const char* fragmentcode = loadshader(fragmentfile);
unsigned int fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fragmentcode, NULL);
glCompileShader(fragment);
{
char log[512]; int success; glGetProgramiv(fragment, GL_COMPILE_STATUS, &success);
printf("Fragment File Name: %sn", fragmentfile); printf("Fragment Code: %dn", fragmentcode); printf("Fragment Value: %dn", fragment);
glGetProgramInfoLog(fragment, 512, NULL, log);
printf("Fragment Shader Failed to Compile!n> OpenGL Error: %snn - - - - - nn", log);
}
unsigned int data = glCreateProgram();
glAttachShader(data, vertex);
glAttachShader(data, fragment);
glLinkProgram(data);
{
char log[512]; int success; glGetProgramiv(data, GL_LINK_STATUS, &success);
printf("Program Value: %dn", data); glGetProgramInfoLog(data, 512, NULL, log);
printf("Shader Failed to Link!n> OpenGL Error: %s", log);
}
glDeleteShader(vertex);
glDeleteShader(fragment);
free((void*) vertexcode);
free((void*) fragmentcode);
Shader* shader = (Shader*) malloc(sizeof(Shader));
shader -> data = data;
return shader;
}
int WinMain(int argc, char const *argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Basic Window", 660, 240, 600, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
SDL_GLContext context = SDL_GL_CreateContext(window);
glewInit();
Shader* shader = createShader("data/test.vs", "data/test.fs");
return 0;
}
char* loadshader(char* filename) {
FILE* file = fopen(filename, "r");
if (!file)
return NULL;
int flag = 0;
char* shader = (char*) malloc(MAXSIZE);
char* buffer = (char*) malloc(BUFFSIZE);
while (fgets(buffer, BUFFSIZE, file) != NULL)
strcat(shader, buffer);
free(buffer);
fclose(file);
printf(""%s" Content:n%sn", filename, shader);
return shader;
}
打印语句的输出如下所示:
"data/test.vs" Content:
# version 330 core
layout (location = 0) in vec3 POSITION;
void main() {
gl_Position = vec4(POSITION, 1.0);
}
Vertex File Name: data/test.vs
Vertex Code: -1521078208
Vertex Value: 1
Vertex Shader Failed to Compile!
> OpenGL Error: ░╗x¥j☻
- - - - -
"data/test.fs" Content:
# version 330 core
out vec4 COLOR;
void main() {
COLOR = vec4((1.0f, 0.5f, 0.2f, 1.0f);
}
Fragment File Name: data/test.fs
Fragment Code: -1486147520
Fragment Value: 2
Fragment Shader Failed to Compile!
> OpenGL Error: ░╗x¥j☻
- - - - -
Program Value: 3
Shader Failed to Link!
> OpenGL Error: Fragment shader(s) were not successfully compiled before glLinkProgram() was called. Link failed.
解决方案:错误出现在我的GLSL着色器代码中,而不是我用来编译着色器的代码中。话虽如此,我还是进行了修改,根据@Rabbit76和@David Sullivan的响应正确检查编译和链接错误。
Shader* createShader(char* vertexfile, char* fragmentfile) {
const char* vertexcode = loadshader(vertexfile);
unsigned int vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vertexcode, NULL);
glCompileShader(vertex);
{
char log[1024]; int success; glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex, 1024, NULL, log);
printf("Vertex Shader Failed to Compile!n> OpenGL Error: %sn", log);
}
}
const char* fragmentcode = loadshader(fragmentfile);
unsigned int fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fragmentcode, NULL);
glCompileShader(fragment);
{
char log[1024]; int success; glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment, 1024, NULL, log);
printf("Fragment Shader Failed to Compile!n> OpenGL Error: %sn", log);
}
}
unsigned int data = glCreateProgram();
glAttachShader(data, vertex);
glAttachShader(data, fragment);
glLinkProgram(data);
{
char log[1024]; int success; glGetProgramiv(data, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(data, 1024, NULL, log);
printf("Shader Failed to Link!n> OpenGL Error: %s", log);
}
}
glDeleteShader(vertex);
glDeleteShader(fragment);
free((void*) vertexcode);
free((void*) fragmentcode);
Shader* shader = (Shader*) malloc(sizeof(Shader));
shader -> data = data;
return shader;
}
2条答案
按热度按时间sqougxex1#
如果着色器编译成功,则必须通过
glGetShaderiv
和参数GL_COMPILE_STATUS
而不是glGetProgramiv
进行检查。可以使用glGetShaderInfoLog
而不是glGetProgramInfoLog
获取日志,例如:vohkndzv2#
glGetProgramInfoLog
不是用于检查着色器是否已正确编译的适当函数。着色器对象和程序对象不是一回事(程序由着色器组成)。因此,将vertex
传递给glGetProgramInfoLog
不会得到您想要的结果,调用glGetError()
可能会返回GL_INVALID_OPERATION
。docs表示写入日志的是以空结尾的字符串,但由于不支持函数的不变量(即,不是传递给它的程序),因此其输出很可能是垃圾。您实际需要的是glGetShaderInfoLog()
2。这将有助于进一步的调试。LearnOpenGL在本页的“编译着色器”一节中有一个验证着色器的示例。