summaryrefslogtreecommitdiff
path: root/src/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader')
-rw-r--r--src/shader/shader.c224
-rw-r--r--src/shader/shader.h117
2 files changed, 341 insertions, 0 deletions
diff --git a/src/shader/shader.c b/src/shader/shader.c
new file mode 100644
index 0000000..817d451
--- /dev/null
+++ b/src/shader/shader.c
@@ -0,0 +1,224 @@
+#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);
+}
+
+
diff --git a/src/shader/shader.h b/src/shader/shader.h
new file mode 100644
index 0000000..07cc22d
--- /dev/null
+++ b/src/shader/shader.h
@@ -0,0 +1,117 @@
+/** @file shader.h
+ *
+ * @brief Functions to create, manipulate, and destroy GLSL shaders.
+ */
+
+#ifndef HONEY_SHADER_H
+#define HONEY_SHADER_H
+
+#include "../common.h"
+#include "../light/light.h"
+
+typedef int honey_shader;
+
+/** @brief Load a shader.
+ *
+ * @param[out] shader Pointer to the shader destination
+ *
+ * @param[in] vertex_shader_path The path to the vertex shader source code
+ * @param[in] fragment_shader_path The path to the fragment shader source code
+ *
+ * @return The result of the shader load.
+ */
+honey_result honey_shader_load(honey_shader* shader,
+ char* vertex_shader_path,
+ char* fragment_shader_path);
+
+/** @brief Create a shader from code strings.
+ *
+ * @param[out] shader Pointer to the shader destination.
+ * @param[in] vertex_shader_code Zero-terminated string containing the vertex shader code to compile
+ * @param[in] fragment_shader_code Zero-terminated string containing the fragment shader code to compile
+ *
+ * @return The result of the shader creation.
+ */
+honey_result honey_shader_new(honey_shader* shader,
+ char* vertex_shader_code,
+ char* fragment_shader_code);
+
+/** @brief Set an integer uniform.
+ *
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] int_name The name of the integer uniform
+ * @param[in] value The value of the integer uniform
+ */
+void honey_shader_set_int(honey_shader shader,
+ char* int_name,
+ int value);
+
+/** @brief Set a float uniform.
+ *
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] float_name The name of the float uniform
+ * @param[in] value The value of the float uniform
+ */
+void honey_shader_set_float(honey_shader shader,
+ char* float_name,
+ float value);
+
+/** @brief Set a vec3 uniform.
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] vector_name The name of the vec3 uniform
+ * @param[in] value The value of the vector uniform
+ */
+void honey_shader_set_vec3(honey_shader shader,
+ char* vector_name,
+ vec3 value);
+
+
+/** @brief Set a mat3 uniform.
+ *
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] matrix_name The name of the matrix uniform
+ * @param[in] value The value of the matrix uniform
+ */
+void honey_shader_set_mat3(honey_shader shader,
+ char* matrix_name,
+ mat3 value);
+
+/** @brief Set a mat4 uniform.
+ *
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] matrix_name The name of the matrix uniform
+ * @param[in] value The value of the matrix uniform
+ */
+void honey_shader_set_mat4(honey_shader shader,
+ char* matrix_name,
+ mat4 value);
+
+/** @brief Set a point_light uniform.
+ *
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] point_light_index The index of the light to set
+ * @param[in] light The honey_point_light to set
+ */
+void honey_shader_set_point_light(honey_shader shader,
+ int point_light_index,
+ honey_point_light light);
+
+/** @brief Set a directional_light uniform.
+ *
+ * @param[in] shader The shader to which the uniform belongs
+ * @param[in] directional_light_index The index of the light to set
+ * @param[in] light The honey_directional_light to set
+ */
+void honey_shader_set_directional_light(honey_shader shader,
+ int directional_light_index,
+ honey_directional_light light);
+
+/** @brief Use a shader.
+ */
+#define honey_shader_use glUseProgram
+
+/** @brief delete a shader.
+ */
+#define honey_shader_delete glDeleteProgram
+
+#endif