#include "../include/shader.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ static honey_result read_file(char** destination, char* file_path) { FILE* f = fopen(file_path, "r"); if (f == NULL) { honey_error_set_string1(file_path); return HONEY_FILE_READ_ERROR; } fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); *destination = malloc(fsize + 1); if (*destination == NULL) { return HONEY_MEMORY_ALLOCATION_ERROR; } fread(*destination, 1, fsize, f); fclose(f); (*destination)[fsize] = 0; return HONEY_OK; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ honey_result honey_shader_load(honey_shader* shader, char* vertex_shader_path, char* fragment_shader_path) { /* load vertex shader code */ char* vertex_shader_code; honey_result result = read_file(&vertex_shader_code, vertex_shader_path); if (result != HONEY_OK) return result; /* load fragment shader code */ char* fragment_shader_code; result = read_file(&fragment_shader_code, fragment_shader_path); if (result != HONEY_OK) return result; result = honey_shader_new(shader, vertex_shader_code, fragment_shader_code); if (result == HONEY_VERTEX_SHADER_COMPILATION_ERROR) honey_error_set_string2(vertex_shader_path); if (result == HONEY_FRAGMENT_SHADER_COMPILATION_ERROR) honey_error_set_string2(fragment_shader_path); free(vertex_shader_code); free(fragment_shader_code); return result; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ honey_result honey_shader_new(honey_shader* shader, char* vertex_shader_code, char* fragment_shader_code) { /* compile shaders */ int success; char error[512]; int vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, ((const char**)&vertex_shader_code), NULL); glCompileShader(vertex_shader); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); if (!success) { honey_error_clear_strings(); char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; glGetShaderInfoLog(vertex_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); honey_error_set_string1(compiler_error); return HONEY_VERTEX_SHADER_COMPILATION_ERROR; } int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment_shader, 1, ((const char**)&fragment_shader_code), NULL); glCompileShader(fragment_shader); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success); if (!success) { honey_error_clear_strings(); char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; glGetShaderInfoLog(fragment_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); honey_error_set_string1(compiler_error); return HONEY_FRAGMENT_SHADER_COMPILATION_ERROR; } /* link shaders */ *shader = glCreateProgram(); glAttachShader(*shader, vertex_shader); glAttachShader(*shader, fragment_shader); glLinkProgram(*shader); glGetShaderiv(*shader, GL_LINK_STATUS, &success); if (!success) { honey_error_clear_strings(); char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; glGetShaderInfoLog(vertex_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); honey_error_set_string1(compiler_error); return HONEY_SHADER_LINK_ERROR; } glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); return HONEY_OK; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_int(honey_shader shader, char* int_name, int value) { honey_shader_use(shader); unsigned int int_location = glGetUniformLocation(shader, int_name); glUniform1i(int_location, value); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_float(honey_shader shader, char* float_name, float value) { honey_shader_use(shader); unsigned int float_location = glGetUniformLocation(shader, float_name); glUniform1f(float_location, value); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_vec3(honey_shader shader, char* vector_name, vec3 value) { honey_shader_use(shader); unsigned int vector_location = glGetUniformLocation(shader, vector_name); glUniform3fv(vector_location, 1, (float*) value); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_mat3(honey_shader shader, char* matrix_name, mat3 value) { glUseProgram(shader); unsigned int matrix_location = glGetUniformLocation(shader, matrix_name); glUniformMatrix3fv(matrix_location, 1, GL_FALSE, (float*) value); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_mat4(honey_shader shader, char* matrix_name, mat4 value) { glUseProgram(shader); unsigned int matrix_location = glGetUniformLocation(shader, matrix_name); glUniformMatrix4fv(matrix_location, 1, GL_FALSE, (float*) value); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_point_light(honey_shader shader, int point_light_index, honey_point_light light) { char name[HONEY_MAX_LIGHT_NAME_LENGTH]; snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "point_lights[%d].position", point_light_index); honey_shader_set_vec3(shader, name, light.position); snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "point_lights[%d].color", point_light_index); honey_shader_set_vec3(shader, name, light.color); snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "point_lights[%d].constant", point_light_index); honey_shader_set_float(shader, name, light.constant); snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "point_lights[%d].linear", point_light_index); honey_shader_set_float(shader, name, light.linear); snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "point_lights[%d].quadratic", point_light_index); honey_shader_set_float(shader, name, light.quadratic); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_shader_set_directional_light(honey_shader shader, int directional_light_index, honey_directional_light light) { char name[HONEY_MAX_LIGHT_NAME_LENGTH]; snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "directional_lights[%d].direction", directional_light_index); honey_shader_set_vec3(shader, name, light.direction); snprintf(name, HONEY_MAX_LIGHT_NAME_LENGTH, "directional_lights[%d].color", directional_light_index); honey_shader_set_vec3(shader, name, light.color); }