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:
18
src/engine/renderer/shaders/default.frag
Normal file
18
src/engine/renderer/shaders/default.frag
Normal 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);
|
||||
}
|
||||
22
src/engine/renderer/shaders/default.vert
Normal file
22
src/engine/renderer/shaders/default.vert
Normal 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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user