feat: establish stable OpenGL 3.3 core graphics conxtext

initializes the full graphics context pipeline required for modern OpenGL rendering
This commit is contained in:
Natsirt867
2025-10-17 12:40:25 -05:00
parent c9c5fc428f
commit 65e7d1b401
8 changed files with 353 additions and 44 deletions

View File

@@ -0,0 +1,18 @@
#version 330 core
// Outputs colors in RGBA
out vec4 FragColor;
// Inputs the color from the vertex shader
in vec3 color;
// Inputs the texture coordinates from the vertex shader
in vec2 texCoord;
// get the texture unit from the main function
uniform sampler2D tex0;
void main()
{
FragColor = texture(tex0, texCoord);
}

View File

@@ -0,0 +1,22 @@
#version 330 core
layout (location = 0) in vec3 aPos; // Vertex Position
layout (location = 1) in vec3 aColor; // Vertex Color
layout (location = 2) in vec2 aTex; // Texture coordinates
// Outputs the color for the Fragment shader
out vec3 color;
// Outputs the texture coordinates for the Fragment shader
out vec2 texCoord;
// Imports the camera matrix from the main function
uniform mat4 camMatrix;
void main()
{
// Apply the combined P*V matrix to transform the vertex position.
gl_Position = camMatrix * vec4(aPos, 1.0);
// Assigns the colors from the Vertex Data to "color"
color = aColor;
// Assigns the texture coordinates from the Vertex Data to "texCoord"
texCoord = aTex;
}

View File

@@ -3,3 +3,115 @@
//
#include "shader.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "../../core/logger/log.h"
// reads entire file contents into a string
char *get_file_contents(const char *filename) {
FILE *fp;
long length;
char *buffer = NULL;
fp = fopen(filename, "rb");
if (!fp) {
log_error("Could not open file '%s'. Reason: %s\n", filename, strerror(errno));
return NULL;
}
fseek(fp, 0, SEEK_END);
length = ftell(fp);
fseek(fp, 0, SEEK_SET);
buffer = (char *)malloc(length + 1);
if (!buffer) {
log_error("Memory allocation failed for file '%s'.\n", filename);
fclose(fp);
return NULL;
}
fread(buffer, 1, length, fp);
buffer[length] = '\0';
fclose(fp);
return buffer;
}
// check if the different shaders have compiled properly
void compile_errors(unsigned int shader, const char *type) {
GLint hasCompiled;
char infoLog[1024];
if (strcmp(type, "PROGRAM") != 0) {
glGetShaderiv(shader, GL_COMPILE_STATUS, &hasCompiled);
if (hasCompiled == GL_FALSE) {
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
log_error("SHADER_COMPILATION_ERROR for: %s\n%s", type, infoLog);
}
} else {
glGetProgramiv(shader, GL_LINK_STATUS, &hasCompiled);
if (hasCompiled == GL_FALSE) {
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
log_error("SHADER_LINKING_ERROR for %s\n%s", type, infoLog);
}
}
}
// build the shader program from 2 different shaders
Shader shader_create(const char *vertexFile, const char *fragmentFile) {
// read shader source files
char *vertexSource = get_file_contents(vertexFile);
char *fragmentSource = get_file_contents(fragmentFile);
if (!vertexSource || !fragmentSource) {
log_error("Failed to load shader files. Returning empty shader\n");
Shader emptyShader = { .ID = 0};
if (vertexSource)
free(vertexSource);
if (fragmentSource)
free(fragmentSource);
return emptyShader;
}
// compile vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const char *const *)&vertexSource, NULL);
glCompileShader(vertexShader);
compile_errors(vertexShader, "VERTEX");
// compile fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, (const char *const *)&fragmentSource, NULL);
glCompileShader(fragmentShader);
compile_errors(fragmentShader, "FRAGMENT");
// cleanup strings after compilation
free(vertexSource);
free(fragmentSource);
// link shaders into a program
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShader);
glAttachShader(programID, fragmentShader);
glLinkProgram(programID);
compile_errors(programID, "PROGRAM");
// cleanup temporary shaders now that we've linked into the program
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
Shader newShader = { .ID = programID };
return newShader;
}
// activates the shader program
void shader_activate(Shader *self) {
glUseProgram(self->ID);
}
// deletes the shader program
void shader_delete(Shader *self) {
glDeleteProgram(self->ID);
self->ID = 0; // just in-case
}