Search code examples
copenglglslshader

Shader Successfully Linked But Doesn't Show on Screen


I have implemented a system that, theoretically, iterates through a list of living entities and draw the shader associated with each entity (provided it has one). However, no matter what I've tried, nothing renders onto the screen.

I have confirmed that each component is properly created/loaded and the data is actually there and I'm not just pointing to NULL.

Here's my Sprite Render system (haven't implemented textures yet) and :

#include "../ECS.h"

#define XTILES 64
#define YTILES 36

void renderSprites(ECS* ecs, int width, int height) {
  if (!ecs)
    return;

  for (Entity entity = 0; entity < (ecs -> entities -> count); entity++) {
    if (isLiving(ecs, entity)) {
      Shader* shader = (Shader*) getComponent(ecs, entity, SHADER);
      Texture* texture = (Texture*) getComponent(ecs, entity, TEXTURE);
      Transform* transform = (Transform*) getComponent(ecs, entity, TRANSFORM);

      if (!shader || !transform)
        continue;

      if (!(shader -> generated)) {
        glGenVertexArrays(1, &(shader -> VAO));
        glGenBuffers(1, &(shader -> VBO));
        glGenBuffers(1, &(shader -> EBO));
        glBindVertexArray(shader -> VAO);
        shader -> generated = 1;
      }

      // Make it changeable for textures
      float vertices[] = {
        (((transform -> position)[0] + 0.5f) / (XTILES / 2)), (((transform -> position)[1] + 0.5f) / (YTILES / 2)), 0.0f,   1.0f, 0.0f, 0.0f,
        (((transform -> position)[0] + 0.5f) / (XTILES / 2)), (((transform -> position)[1] - 0.5f) / (YTILES / 2)), 0.0f,   1.0f, 1.0f, 0.0f,
        (((transform -> position)[0] - 0.5f) / (XTILES / 2)), (((transform -> position)[1] - 0.5f) / (YTILES / 2)), 0.0f,   0.0f, 1.0f, 0.0f,
        (((transform -> position)[0] - 0.5f) / (XTILES / 2)), (((transform -> position)[1] + 0.5f) / (YTILES / 2)), 0.0f,   0.0f, 0.0f, 1.0f,
      };

      unsigned int indices[] = {
        0, 1, 3,
        1, 2, 3
      };

      glBindBuffer(GL_ARRAY_BUFFER, shader -> VBO);
      glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shader -> EBO);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*) 0);
      glEnableVertexAttribArray(0);

      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*) (3 * sizeof(float)));
      glEnableVertexAttribArray(1);

      if (texture)
        glBindTexture(GL_TEXTURE_2D, texture -> data);

      glClear(GL_COLOR_BUFFER_BIT);
      glUseProgram(shader -> data);
      glBindVertexArray(shader -> VAO);
      glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }
  }
}

How I call the method in the main loop:

//...
last = time();
while (!app.quit) {
  resetInput();

  now = time();
  delta = now - last;

  if (delta > (1000 / app.fps)) {
    last = now;
    inputProc(&app);

    frame();
    renderSprites(app.ecs, app.width, app.height);
    SDL_GL_SwapWindow(app -> window);
    SDL_Delay(1);
  }
}
//...

I tried to make a minimal reproducible example using only my shader code but the example code I made actually works and renders a square onto the screen:

#define WIDTH 600
#define HEIGHT 600
#define XTILES 24
#define YTILES 24

#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 {
  int generated;
  unsigned int data;
  unsigned int VBO, VAO, EBO;
} 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[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;
  shader -> generated = 0;
  return shader;
}

void renderSprite(SDL_Window*, Shader*, float*);
int WinMain(int argc, char const *argv[]) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window* window = SDL_CreateWindow("Basic Window", 960, 170, WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
  SDL_GLContext context = SDL_GL_CreateContext(window);
  glewInit();

  Shader* shader = createShader("data/02.vs", "data/02.fs");
  float position[] = {0.0f, 0.0f};
  renderSprite(window, shader, position);
  SDL_Delay(2500);

  position[0] = 0.75f + (XTILES / 3); position[1] = 0.75f + (YTILES / 3);
  renderSprite(window, shader, position);
  SDL_Delay(1250);

  position[0] = 0.75f + (XTILES / 3); position[1] = -0.75f - (YTILES / 3);
  renderSprite(window, shader, position);
  SDL_Delay(1250);

  position[0] = -0.75f - (XTILES / 3); position[1] = -0.75f - (YTILES / 3);
  renderSprite(window, shader, position);
  SDL_Delay(1250);

  position[0] = -0.75f - (XTILES / 3); position[1] = 0.75f + (YTILES / 3);
  renderSprite(window, shader, position);
  SDL_Delay(1250);

  position[0] = 0.0f; position[1] = 0.0f;
  renderSprite(window, shader, position);
  SDL_Delay(2500);
  return 0;
}

void renderSprite(SDL_Window* window, Shader* shader, float position[2]) {
  if (!shader)
    return;

  if (!(shader -> generated)) {
    printf("%s\n", "Generating Shader Buffers");
    glGenVertexArrays(1, &(shader -> VAO));
    glGenBuffers(1, &(shader -> VBO));
    glGenBuffers(1, &(shader -> EBO));
    glBindVertexArray(shader -> VAO);
    shader -> generated = 1;
  }

  float vertices[] = {
    ((position[0] + 0.5f) / (XTILES / 2)), ((position[1] + 0.5f) / (YTILES / 2)), 0.0f,   1.0f, 0.0f, 0.0f,
    ((position[0] + 0.5f) / (XTILES / 2)), ((position[1] - 0.5f) / (YTILES / 2)), 0.0f,   1.0f, 1.0f, 0.0f,
    ((position[0] - 0.5f) / (XTILES / 2)), ((position[1] - 0.5f) / (YTILES / 2)), 0.0f,   0.0f, 1.0f, 0.0f,
    ((position[0] - 0.5f) / (XTILES / 2)), ((position[1] + 0.5f) / (YTILES / 2)), 0.0f,   0.0f, 0.0f, 1.0f,
  };

  unsigned int indices[] = {
    0, 1, 3,
    1, 2, 3
  };

  glBindBuffer(GL_ARRAY_BUFFER, shader -> VBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shader -> EBO);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*) 0);
  glEnableVertexAttribArray(0);

  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*) (3 * sizeof(float)));
  glEnableVertexAttribArray(1);

  glClear(GL_COLOR_BUFFER_BIT);
  glUseProgram(shader -> data);
  glBindVertexArray(shader -> VAO);
  glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  SDL_GL_SwapWindow(window);
  SDL_Delay(1);
}

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

Solution: Apparently the error wasn't in my rendering code but in my shader. I had changed the name of the variables in my vertex and fragment shaders and OpenGL wasn't liking it. After I changed it back to the default names, everything started working.


Solution

  • Solution: Apparently the error wasn't in my rendering code but in my shader. I had changed the name of the variables in my vertex and fragment shaders and OpenGL wasn't liking it. After I changed it back to the default names, everything started working.