|
|
|
@ -0,0 +1,252 @@
|
|
|
|
|
#ifndef _SHADERLOADER_H_
|
|
|
|
|
#define _SHADERLOADER_H_
|
|
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
|
|
#include <glad/glad.h>
|
|
|
|
|
#include <GLFW/glfw3.h>
|
|
|
|
|
|
|
|
|
|
enum ShaderType {
|
|
|
|
|
vertex = GL_VERTEX_SHADER,
|
|
|
|
|
fragment = GL_FRAGMENT_SHADER,
|
|
|
|
|
geometry = GL_GEOMETRY_SHADER,
|
|
|
|
|
//tesselation = GL_TESS_CONTROL_SHADER, // GL4.0 || ARB_tesselation_shader
|
|
|
|
|
//valuation = GL_TESS_EVALUATION_SHADER,
|
|
|
|
|
//compute = GL_COMPUTE_SHADER, // GL4.3 || ARB_compute_shader
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct RegisteredShader {
|
|
|
|
|
char *shaderName;
|
|
|
|
|
int shaderType;
|
|
|
|
|
GLuint shaderID;
|
|
|
|
|
} RegisteredShader;
|
|
|
|
|
|
|
|
|
|
struct RegisteredShaderProgram {
|
|
|
|
|
char *programName;
|
|
|
|
|
GLuint programID;
|
|
|
|
|
} RegisteredShaderProgram;
|
|
|
|
|
|
|
|
|
|
struct ShaderRegistry {
|
|
|
|
|
struct RegisteredShader *list = 0;
|
|
|
|
|
int size = 0;
|
|
|
|
|
} ShaderRegistry;
|
|
|
|
|
|
|
|
|
|
void register_shader(struct ShaderRegistry *r, char *name, int type, GLuint id) {
|
|
|
|
|
// Allocate storage for the name
|
|
|
|
|
int name_size = strlen(name);
|
|
|
|
|
char *n = (char*) malloc(name_size * sizeof(char));
|
|
|
|
|
|
|
|
|
|
// Grow and copy
|
|
|
|
|
int new_size = r->size + 1;
|
|
|
|
|
struct RegisteredShader *list = (struct RegisteredShader *) malloc(new_size * sizeof(RegisteredShader));
|
|
|
|
|
memcpy(list, r->list, r->size * sizeof(RegisteredShader));
|
|
|
|
|
|
|
|
|
|
// Add new element
|
|
|
|
|
list[new_size-1].shaderName = n;
|
|
|
|
|
list[new_size-1].shaderType = type;
|
|
|
|
|
list[new_size-1].shaderID = id;
|
|
|
|
|
|
|
|
|
|
// Replace in registry
|
|
|
|
|
r->size = new_size;
|
|
|
|
|
free(r->list);
|
|
|
|
|
r->list = list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct RegisteredShader* find_shader(struct ShaderRegistry *r, char *name) {
|
|
|
|
|
int i = 0;
|
|
|
|
|
struct RegisteredShader *s = 0;
|
|
|
|
|
for(i; i < r->size; i++) {
|
|
|
|
|
s = (r->list) + (i * sizeof(struct RegisteredShader));
|
|
|
|
|
if(strcmp(s->shaderName, name) == 0) {
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void remove_shader(struct ShaderRegistry *r, struct RegisteredShader *s) {
|
|
|
|
|
if(s == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
int index = (s - (r->list)) / sizeof(struct RegisteredShader);
|
|
|
|
|
int new_size = r->size - 1;
|
|
|
|
|
struct RegisteredShader *list;
|
|
|
|
|
list = (struct RegisteredShader*) malloc(new_size * sizeof(struct RegisteredShader));
|
|
|
|
|
// Copy the first half
|
|
|
|
|
memcpy(list, r->list, index * sizeof(struct RegisteredShader));
|
|
|
|
|
// Copy the second half
|
|
|
|
|
memcpy(list, r->list + ((index + 1) * sizeof(struct RegisteredShader)), (r->size - 1 - index) * sizeof(struct RegisteredShader));
|
|
|
|
|
// Deallocate the string of the registered shader
|
|
|
|
|
free(s->shaderName);
|
|
|
|
|
// Deallocate the old list
|
|
|
|
|
free(r->list);
|
|
|
|
|
r->list = list;
|
|
|
|
|
r->size = new_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void remove_shader_by_name(struct ShaderRegistry *r, char *name) {
|
|
|
|
|
remove_shader(r, find_shader(r, name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct ShaderProgramRegistry {
|
|
|
|
|
struct RegisteredShareProgram *list = 0;
|
|
|
|
|
int size = 0;
|
|
|
|
|
} ShaderProgramRegistry;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GLuint compile_shader(const char* file_path, int t) {
|
|
|
|
|
GLuint shader_id = glCreateShader(t);
|
|
|
|
|
|
|
|
|
|
// From: https://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
|
|
|
|
|
// Read the Vertex Shader code from the file
|
|
|
|
|
std::string code;
|
|
|
|
|
std::ifstream stream(file_path, std::ios::in);
|
|
|
|
|
if(stream.is_open()){
|
|
|
|
|
std::stringstream sstr;
|
|
|
|
|
sstr << stream.rdbuf();
|
|
|
|
|
code = sstr.str();
|
|
|
|
|
stream.close();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// @TODO Inform user.
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLint Result = GL_FALSE;
|
|
|
|
|
int InfoLogLength;
|
|
|
|
|
|
|
|
|
|
// Compile Vertex Shader
|
|
|
|
|
printf("Compiling shader : %s\n", file_path);
|
|
|
|
|
char const *source = code.c_str();
|
|
|
|
|
glShaderSource(shader_id, 1, &source , NULL);
|
|
|
|
|
glCompileShader(shader_id);
|
|
|
|
|
|
|
|
|
|
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &Result);
|
|
|
|
|
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
|
|
|
|
if ( InfoLogLength > 0 ){
|
|
|
|
|
std::vector<char> error_message(InfoLogLength+1);
|
|
|
|
|
glGetShaderInfoLog(shader_id, InfoLogLength, NULL, &error_message[0]);
|
|
|
|
|
printf("%s\n", &error_message[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return shader_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int loadShadersFromFile(const char* file_path, struct ShaderRegistry *registry) {
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char *line;
|
|
|
|
|
size_t size = 0;
|
|
|
|
|
const char *delim = ",";
|
|
|
|
|
fp = fopen(file_path, "r");
|
|
|
|
|
if (fp == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
char *name;
|
|
|
|
|
char *type;
|
|
|
|
|
char *path;
|
|
|
|
|
while((size = getline(&line, &size, fp)) != -1) {
|
|
|
|
|
if(size == 0) {
|
|
|
|
|
// Skipping, line length 0
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(line[0] == '#') {
|
|
|
|
|
// Skipping, line is a comment
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
char *line_copy = (char*) malloc((size) * sizeof(char*));
|
|
|
|
|
strncpy(line_copy, line, size);
|
|
|
|
|
// Format <name>,<type>,<filepath>
|
|
|
|
|
name = strtok(line_copy, delim);
|
|
|
|
|
type = strtok(NULL, delim);
|
|
|
|
|
path = strtok(NULL, delim);
|
|
|
|
|
if (name == NULL || type == NULL || path == NULL) {
|
|
|
|
|
// Invalid line, not enough elements.
|
|
|
|
|
// @TODO Inform the user.
|
|
|
|
|
free(line_copy);
|
|
|
|
|
name = type = path = NULL;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate type
|
|
|
|
|
enum ShaderType shader_type;
|
|
|
|
|
if(strcmp("fragment", type) == 0) {
|
|
|
|
|
shader_type = fragment;
|
|
|
|
|
}
|
|
|
|
|
else if(strcmp("vertex", type) == 0) {
|
|
|
|
|
shader_type = vertex;
|
|
|
|
|
}
|
|
|
|
|
else if(strcmp("geometry", type) == 0) {
|
|
|
|
|
shader_type = geometry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(shader_type == 0) {
|
|
|
|
|
// Invalid line, unknown type.
|
|
|
|
|
// @TODO Inform the user.
|
|
|
|
|
free(line_copy);
|
|
|
|
|
name = type = path = NULL;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint shader_id = compile_shader(path, shader_type);
|
|
|
|
|
if(shader_id == 0) {
|
|
|
|
|
// Error in compilation of the shader
|
|
|
|
|
// @TODO Inform the user.
|
|
|
|
|
free(line_copy);
|
|
|
|
|
name = type = path = NULL;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Check Vertex Shader
|
|
|
|
|
// glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
|
|
|
|
|
// glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
|
|
|
|
// if ( InfoLogLength > 0 ){
|
|
|
|
|
// std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
|
|
|
|
|
// glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
|
|
|
|
|
// printf("%s\n", &VertexShaderErrorMessage[0]);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // Compile Fragment Shader
|
|
|
|
|
// printf("Compiling shader : %s\n", fragment_file_path);
|
|
|
|
|
// char const * FragmentSourcePointer = FragmentShaderCode.c_str();
|
|
|
|
|
// glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
|
|
|
|
|
// glCompileShader(FragmentShaderID);
|
|
|
|
|
|
|
|
|
|
// // Check Fragment Shader
|
|
|
|
|
|
|
|
|
|
// // Link the program
|
|
|
|
|
// printf("Linking program\n");
|
|
|
|
|
// GLuint ProgramID = glCreateProgram();
|
|
|
|
|
// glAttachShader(ProgramID, VertexShaderID);
|
|
|
|
|
// glAttachShader(ProgramID, FragmentShaderID);
|
|
|
|
|
// glLinkProgram(ProgramID);
|
|
|
|
|
|
|
|
|
|
// // Check the program
|
|
|
|
|
// glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
|
|
|
|
// glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
|
|
|
|
// if ( InfoLogLength > 0 ){
|
|
|
|
|
// std::vector<char> ProgramErrorMessage(InfoLogLength+1);
|
|
|
|
|
// glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
|
|
|
|
|
// printf("%s\n", &ProgramErrorMessage[0]);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// glDetachShader(ProgramID, VertexShaderID);
|
|
|
|
|
// glDetachShader(ProgramID, FragmentShaderID);
|
|
|
|
|
|
|
|
|
|
// glDeleteShader(VertexShaderID);
|
|
|
|
|
// glDeleteShader(FragmentShaderID);
|
|
|
|
|
|
|
|
|
|
// return ProgramID;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
#endif // _SHADERLOADER_H_
|