System info & network
This commit is contained in:
193
code/render/shader.cpp
Normal file
193
code/render/shader.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
#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");
|
||||
}
|
||||
Reference in New Issue
Block a user