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