Files
Server_Monitor/code/render/shader.cpp

194 lines
6.4 KiB
C++
Raw Normal View History

2023-09-26 19:40:16 +02:00
#include "shader.h"
#include "../debug/logger.h"
#define STB_INCLUDE_IMPLEMENTATION
#define STB_INCLUDE_LINE_GLSL
#include "stb_include.h"
// Internal functions
void r_shader_set_uniform_locations(r_shader *shader);
bool r_shader_from_files(r_shader *shader, const char *vertex, const char *fragment, const char *geometry, const char *tesseletion_control, const char *tesseletion_evaluation, const char *compute)
{
const int count = 6;
char *source[count] = {NULL, NULL, NULL, NULL, NULL, NULL};
const char *filename[count] = {vertex, fragment, geometry, tesseletion_control, tesseletion_evaluation, compute};
const char *type[count] = {"vertex", "fragment", "geometry", "tesseletion_control", "tesseletion_evaluation", "compute"};
// Load sources
bool has_error = false;
char error[256];
for(int i = 0; i < count; i++)
{
if(filename[i])
{
char path[4096];
u32 len = strlen(filename[i]);
memcpy(path, filename[i], len+1);
int last_slash = len;
while(last_slash > 0)
{
if(filename[i][last_slash] == '/')
break;
last_slash--;
}
path[last_slash] = '\0';
source[i] = stb_include_file((char*)filename[i], NULL, path, error);
if(!source[i])
{
has_error = true;
LOG(LOG_ERROR, "Error loading %s shader: %s", type[i], error);
break;
}
}
}
// Compile shader
if(!has_error)
{
has_error = !r_shader_from_text(shader, source[0], source[1], source[2], source[3], source[5], source[5]);
}
// Cleanup
for(int i = 0; i < count; i++)
{
if(source[i])
free(source[i]);
}
return !has_error;
}
bool r_shader_from_text(r_shader *shader, const char *vertex, const char *fragment, const char *geometry, const char *tesseletion_control, const char *tesseletion_evaluation, const char *compute)
{
int count = 6;
GLuint type[count] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, GL_COMPUTE_SHADER};
const char *source[count] = {vertex, fragment, geometry, tesseletion_control, tesseletion_evaluation, compute};
// Create shader program
shader->id = glCreateProgram();
bool has_error = false;
for(int i = 0; i < count; i++)
{
if(!source[i])
continue;
// Compile current shader source
GLuint source_id = glCreateShader(type[i]);
GLint size = strlen(source[i]);
glShaderSource(source_id, 1, &source[i], &size);
glCompileShader(source_id);
// Check for success/errors
char build_info[2048];
GLint build_success;
glGetShaderiv(source_id, GL_COMPILE_STATUS, &build_success);
if (!build_success)
{
glGetShaderInfoLog(source_id, 2048, NULL, build_info);
LOG(LOG_ERROR, "Cannot compile shader %.*s: %s", (int)size, source, build_info);
glDeleteShader(source_id);
has_error = true;
break;
}
// Attach compiler shader to program
glAttachShader(shader->id, source_id);
}
// @Correctness: Clean up shader sources after fail
if(has_error)
return false;
// Link program
glLinkProgram(shader->id);
// Check for success/error
GLint build_success;
char build_info[512];
glGetProgramiv(shader->id, GL_LINK_STATUS, &build_success);
if(!build_success) {
glGetProgramInfoLog(shader->id, 512, NULL, build_info);
LOG(LOG_ERROR, "Cannot link shader program: %s", build_info);
glDeleteShader(shader->id);
has_error = true;
}
// Load uniform locations
if(!has_error)
r_shader_set_uniform_locations(shader);
return !has_error;
}
void r_shader_delete(r_shader *shader)
{
glDeleteProgram(shader->id);
}
// Internal functions
void r_shader_set_uniform_locations(r_shader *shader)
{
shader->time = glGetUniformLocation(shader->id, "time");
shader->width = glGetUniformLocation(shader->id, "width");
shader->height = glGetUniformLocation(shader->id, "height");
shader->view_matrix = glGetUniformLocation(shader->id, "view_matrix");
shader->view_matrix_inverse = glGetUniformLocation(shader->id, "view_matrix_inverse");
shader->model_matrix = glGetUniformLocation(shader->id, "model_matrix");
shader->camera_position = glGetUniformLocation(shader->id, "camera_position");
for(int i = 0; i < R_SHADER_COLOR_MAX; i++)
{
char uniform_name[32]; sprintf(uniform_name, "color%d", i);
shader->color[i] = glGetUniformLocation(shader->id, uniform_name);
}
for(int i = 0; i < R_SHADER_TEXTURES_MAX; i++)
{
char uniform_name[32];
sprintf(uniform_name, "has_texture%d", i);
shader->has_texture [i] = glGetUniformLocation(shader->id, uniform_name);
sprintf(uniform_name, "texture%d", i);
shader->texture [i] = glGetUniformLocation(shader->id, uniform_name);
sprintf(uniform_name, "texture_channels%d", i);
shader->texture_channels[i] = glGetUniformLocation(shader->id, uniform_name);
}
shader->lights = glGetUniformBlockIndex(shader->id, "lights");
if(shader->lights != GL_INVALID_INDEX)
glUniformBlockBinding(shader->id, shader->lights, 0);
shader->has_shadow_map = glGetUniformLocation(shader->id, "has_shadow_map");
shader->shadow_map = glGetUniformLocation(shader->id, "shadow_map");
shader->shadow_matrix = glGetUniformLocation(shader->id, "shadow_matrix");
shader->has_environment_map = glGetUniformLocation(shader->id, "has_environment_map");
shader->environment_map = glGetUniformLocation(shader->id, "environment_map");
shader->has_albedo_texture = glGetUniformLocation(shader->id, "has_albedo_texture");
shader->albedo_texture = glGetUniformLocation(shader->id, "albedo_texture");
shader->albedo_factor = glGetUniformLocation(shader->id, "albedo_factor");
shader->has_metallic_texture = glGetUniformLocation(shader->id, "has_metallic_texture");
shader->metallic_texture = glGetUniformLocation(shader->id, "metallic_texture");
shader->metallic_factor = glGetUniformLocation(shader->id, "metallic_factor");
shader->has_roughness_texture = glGetUniformLocation(shader->id, "has_roughness_texture");
shader->roughness_texture = glGetUniformLocation(shader->id, "roughness_texture");
shader->roughness_factor = glGetUniformLocation(shader->id, "roughness_factor");
shader->has_normal_texture = glGetUniformLocation(shader->id, "has_normal_texture");
shader->normal_texture = glGetUniformLocation(shader->id, "normal_texture");
shader->has_emissive_texture = glGetUniformLocation(shader->id, "has_emissive_texture");
shader->emissive_texture = glGetUniformLocation(shader->id, "emissive_texture");
shader->emissive_factor = glGetUniformLocation(shader->id, "emissive_factor");
}