2

I have a method that creates and returns a shader program from two given strings (vertex and fragment shader filenames). Initially, it was working perfectly, with the compilation and linking being successful, before randomly failing and giving me an error message of unicode emoji's.

Example Code:

#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: %s\n", vertexfile); printf("Vertex Code: %d\n", vertexcode); printf("Vertex Value: %d\n", vertex); glGetProgramInfoLog(vertex, 512, NULL, log); printf("Vertex Shader Failed to Compile!\n> OpenGL Error: %s\n\n - - - - - \n\n", 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: %s\n", fragmentfile); printf("Fragment Code: %d\n", fragmentcode); printf("Fragment Value: %d\n", fragment); glGetProgramInfoLog(fragment, 512, NULL, log); printf("Fragment Shader Failed to Compile!\n> OpenGL Error: %s\n\n - - - - - \n\n", 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: %d\n", 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%s\n", filename, shader); return shader; } 

The output of the print statements are as follows:

"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. 

Solution: The error was in my GLSL shader code, not the code I was using to compile the shaders. That being said, I also made changes to properly check for compilation and linking errors based on @Rabbid76 and @David Sullivan's responses.

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: %s\n", 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: %s\n", 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
  • 1
    glGetProgramInfoLog() receives an uninitialise buffer log. Without testing the functions return code, you attempt to use log in an error message... there's a funny smell there.... Commented Jul 30, 2022 at 5:10
  • 1
    printf(strcat(strcpy(msg, "Vertex Shader Failed to Compile!\n> OpenGL Error: "), log)); looks like a train wreck. What's wring with something like printf("Vertex Shader Failed to Compile!\n> OpenGL Error: %s", log);? Commented Jul 30, 2022 at 5:11

2 Answers 2

2

If the compiling of a shader succeeded has to be checked by glGetShaderiv and the parameter GL_COMPILE_STATUS instead of glGetProgramiv. THe log can be get with glGetShaderInfoLog instead of glGetProgramInfoLog e.g.:

glCompileShader(vertex); { glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if (!success) { // [...] glGetShaderInfoLog(vertex, 512, NULL, log); printf(strcat(strcpy(msg, "Vertex Shader Failed to Compile!\n> OpenGL Error: "), log)); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, you were right. I cobbled together the example code at 1AM which is why it was so jank, but making the changes you said in my project showed me the errors in my shader code which caused the compilation failure.
2

glGetProgramInfoLog is not the appropriate function for checking if a shader was compiled correctly. Shader objects and program objects are not the same thing (programs are composed of shaders). So passing vertex into glGetProgramInfoLog will not give you what you want, and likely a call to glGetError() would return GL_INVALID_OPERATION. The docs say that what is written to log is a null terminated string, but since the invariants of the function are not upheld (ie, not a program passed to it), its output is likely garbage. What you actually want is glGetShaderInfoLog() 2. The output of this will help debug further. LearnOpenGL has an example of validating a shader in the "Compiling a shader" section of this page.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.