Home > Net >  OpenGL Shader Compilation and Linking Error
OpenGL Shader Compilation and Linking Error

Time:07-30

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
#include <GL/glew.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) {
  char msg[512]; char log[512]; int success;

  const char* vertexcode = loadshader(vertexfile);
  unsigned int vertex = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertex, 1, &vertexcode, NULL);
  glCompileShader(vertex);

  {
    glGetProgramiv(vertex, GL_LINK_STATUS, &success);
    if (!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(strcat(strcpy(msg, "Vertex Shader Failed to Compile!\n> OpenGL Error: "), log));
    }
  }

  const char* fragmentcode = loadshader(fragmentfile);
  unsigned int fragment = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragment, 1, &fragmentcode, NULL);
  glCompileShader(fragment);

  {
    glGetProgramiv(fragment, GL_LINK_STATUS, &success);
    if (!success) {
      printf("\n\nFragment File Name: %s\n", fragmentfile); printf("Fragment Code: %d\n", fragmentcode);
      printf("Fragment Value: %d\n", fragment); glGetProgramInfoLog(fragment, 512, NULL, log);
      printf(strcat(strcpy(msg, "Fragment Shader Failed to Link!\n> OpenGL Error"), log));
    }
  }

  unsigned int data = glCreateProgram();
  glAttachShader(data, vertex);
  glAttachShader(data, fragment);
  glLinkProgram(data);

  {
    glGetProgramiv(data, GL_LINK_STATUS, &success);
    if (!success) {
      printf("Program Value: %d\n", data); glGetProgramInfoLog(data, 512, NULL, log);
      printf(strcat(strcpy(msg, "\n\nShader Program Failed to Link!\n> OpenGL Error: "), log));
    }
  }

  glDeleteShader(vertex);
  glDeleteShader(fragment);
  free((void*) vertexcode);
  free((void*) fragmentcode);

  Shader* shader = (Shader*) malloc(sizeof(Shader));
  shader -> data = data;
  return shader;
}

int main(int argc, char const *argv[]) {
  glewInit();
  Shader* shader = createShader("data/test.vs", "data/test.fs");
  printf("%s\n", shader ? "Shader Successfully Created!" : "Failed to Create Shader!");
  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);
  return shader;
}

The output of the print statements are as follows:

Vertex File Name: data/test.vs
Vertex Code: 81465408
Vertex Value: 1
Vertex Shader Failed to Compile!
> OpenGL Error: ░☻

Fragment File Name: data/test.fs
Fragment Code: 82587712
Fragment Value: 2
Fragment Shader Failed to Compile!
> OpenGL Error: ░☻

[process exited with code 4294967295 (0xffffffff)]

CodePudding user response:

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));
    }
}

CodePudding user response:

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.

  • Related