summaryrefslogtreecommitdiff
path: root/src/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader')
-rw-r--r--src/shader/shader.c350
-rw-r--r--src/shader/shader.h137
2 files changed, 231 insertions, 256 deletions
diff --git a/src/shader/shader.c b/src/shader/shader.c
index 817d451..3deb5b8 100644
--- a/src/shader/shader.c
+++ b/src/shader/shader.c
@@ -1,224 +1,216 @@
#include "shader.h"
+void honey_setup_shader(lua_State* L)
+{
+ honey_lua_element shader_elements[] = {
+ { "new", HONEY_FUNC, { .function = honey_shader_new } },
+ { "use", HONEY_FUNC, { .function = honey_shader_use } },
+ { "set_int", HONEY_FUNC, { .function = honey_shader_set_int } },
+ { "set_float", HONEY_FUNC, { .function = honey_shader_set_float } },
+ { "set_vec3", HONEY_FUNC, { .function = honey_shader_set_vec3 } },
+ { "set_vec4", HONEY_FUNC, { .function = honey_shader_set_vec4 } },
+ { "set_mat3", HONEY_FUNC, { .function = honey_shader_set_mat3 } },
+ { "set_mat4", HONEY_FUNC, { .function = honey_shader_set_mat4 } },
+ { "delete", HONEY_FUNC, { .function = honey_shader_delete } },
+ };
+
+ honey_lua_create_table(L, shader_elements, 9);
+}
+
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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;
- }
+static bool compile_shader(int* shader,
+ const char* source,
+ int shader_type,
+ char* error_message,
+ size_t error_size)
+{
+ int success;
+
+ *shader = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(*shader, 1, source, NULL);
+ glCompileShader(*shader);
+ glGetShaderiv(*shader, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(*shader, error_size, NULL, error_message);
+ return false;
+ }
+
+ return true;
+}
- 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);
+int honey_shader_new(lua_State* L)
+{
+ if (!honey_lua_validate_types(L, 2, HONEY_STRING, HONEY_STRING))
+ lua_error(L);
- (*destination)[fsize] = 0;
+ const char* vertex_shader_source = lua_tostring(L, 1);
+ const char* fragment_shader_source = lua_tostring(L, 2);
+
+ char error[1024];
- return HONEY_OK;
+ int vertex_shader, fragment_shader;
+
+ if (!compile_shader(&vertex_shader,
+ vertex_shader_source,
+ GL_VERTEX_SHADER,
+ error, 1024)) {
+ lua_pushstring(L, error);
+ lua_error(L);
+ }
+
+ if (!compile_shader(&fragment_shader,
+ fragment_shader_source,
+ GL_FRAGMENT_SHADER,
+ error, 1024)) {
+ lua_pushstring(L, error);
+ lua_error(L);
+ }
+
+ int shader = glCreateProgram();
+ glAttachShader(shader, vertex_shader);
+ glAttachShader(shader, fragment_shader);
+ glLinkProgram(shader);
+
+ int success;
+ glGetShaderiv(shader, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(shader, 1024, NULL, error);
+ lua_pushstring(L, error);
+ lua_error(L);
+ }
+
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+
+ lua_pushinteger(L, shader);
+ return 1;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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;
+int honey_shader_use(lua_State* L)
+{
+ if (!honey_lua_validate_types(L, 1, HONEY_INT))
+ lua_error(L);
+
+ int shader = lua_tointeger(L, 1);
+ glUseProgram(shader);
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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;
+int honey_shader_set_int(lua_State* L)
+{
+ if (!honey_lua_validate_types(L, 2, HONEY_INT, HONEY_STRING, HONEY_INT))
+ lua_error(L);
+
+ int shader = lua_tointeger(L, 1);
+ const char* name = lua_tostring(L, 2);
+ int value = lua_tointeger(L, 3);
+
+ glUseProgram(shader);
+ unsigned int location = glGetUniformLocation(shader, name);
+ glUniform1i(location, value);
+
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
+int honey_shader_set_float(lua_State* L)
+{
+ if (!honey_lua_validate_types(L, 2, HONEY_INT, HONEY_STRING, HONEY_NUM))
+ lua_error(L);
+
+ int shader = lua_tointeger(L, 1);
+ const char* name = lua_tostring(L, 2);
+ float value = lua_tonumber(L, 3);
+
+ glUseProgram(shader);
+ unsigned int location = glGetUniformLocation(shader, name);
+ glUniform1f(location, value);
+
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
+static void get_array(lua_State* L,
+ unsigned int* location,
+ float** value)
+{
+ if (!honey_lua_validate_types(L, 2, HONEY_INT, HONEY_STRING, HONEY_USERDATA))
+ lua_error(L);
+
+ int shader = lua_tointeger(L, 1);
+ const char* name = lua_tostring(L, 2);
+ *value = lua_touserdata(L, 3);
+
+ glUseProgram(shader);
+ *location = glGetUniformLocation(shader, name);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
+int honey_shader_set_vec3(lua_State* L)
+{
+ unsigned int location;
+ float* array;
+ get_array(L, &location, &array);
+
+ glUniform3fv(location, 1, array);
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
+int honey_shader_set_vec4(lua_State* L)
+{
+ unsigned int location;
+ float* array;
+ get_array(L, &location, &array);
+
+ glUniform4fv(location, 1, array);
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
+int honey_shader_set_mat3(lua_State* L)
+{
+ unsigned int location;
+ float* array;
+ get_array(L, &location, &array);
+
+ glUniformMatrix3fv(location, 1, GL_FALSE, array);
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
+int honey_shader_set_mat4(lua_State* L)
+{
+ unsigned int location;
+ float* array;
+ get_array(L, &location, &array);
+
+ glUniformMatrix4fv(location, 1, GL_FALSE, array);
+ return 0;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-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);
-}
+int honey_shader_delete(lua_State* L)
+{
+ if (!honey_lua_validate_types(L, 1, HONEY_INT))
+ lua_error(L);
+
+ int shader = lua_tointeger(L, 1);
-
+ glDeleteProgram(shader);
+ return 0;
+}
diff --git a/src/shader/shader.h b/src/shader/shader.h
index 07cc22d..95956ea 100644
--- a/src/shader/shader.h
+++ b/src/shader/shader.h
@@ -7,111 +7,94 @@
#define HONEY_SHADER_H
#include "../common.h"
-#include "../light/light.h"
-typedef int honey_shader;
+/** @brief Push the shader table to the lua stack.
+ */
+void honey_setup_shader(lua_State* L);
-/** @brief Load a shader.
+/** @brief Create a new shader from source.
*
- * @param[out] shader Pointer to the shader destination
+ * @param[in] vertex_source The GLSL code for the vertex shader.
+ * @param[in] fragment_source The GLSL code for the fragment shader.
*
- * @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.
+ * @returns OpenGL handle for the compiled shader.
*/
-honey_result honey_shader_load(honey_shader* shader,
- char* vertex_shader_path,
- char* fragment_shader_path);
+int honey_shader_new(lua_State* L);
-/** @brief Create a shader from code strings.
+/** @brief Set a shader as the current OpenGL shader.
*
- * @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
+ * @param[in] shader The OpenGL handle to a shader, as generated by honey.shader.new
*
- * @return The result of the shader creation.
+ * @returns Nothing.
*/
-honey_result honey_shader_new(honey_shader* shader,
- char* vertex_shader_code,
- char* fragment_shader_code);
+int honey_shader_use(lua_State* L);
-/** @brief Set an integer uniform.
+/** @brief Set an integer uniform on a shader.
*
- * @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 OpenGL shader handle.
+ * @param[in] name The name of the shader uniform as a string.
+ * @param[in] value The value to set the uniform to.
*
- * @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
+ * @returns Nothing.
*/
-void honey_shader_set_float(honey_shader shader,
- char* float_name,
- float value);
+int honey_shader_set_int(lua_State* L);
-/** @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.
+/** @brief Set a float uniform on a shader.
+ *
+ * @param[in] shader The OpenGL shader handle.
+ * @param[in] name The name of the shader uniform as a string.
+ * @param[in] value The value to set the uniform to.
*
- * @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
+ * @returns Nothing.
*/
-void honey_shader_set_mat3(honey_shader shader,
- char* matrix_name,
- mat3 value);
+int honey_shader_set_float(lua_State* L);
-/** @brief Set a mat4 uniform.
+/** @brief Set a vec3 uniform on a shader.
*
- * @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
+ * @param[in] shader The OpenGL shader handle.
+ * @param[in] name The name of the shader uniform as a string.
+ * @param[in] value The value to set the uniform to.
+ *
+ * @returns Nothing.
*/
-void honey_shader_set_mat4(honey_shader shader,
- char* matrix_name,
- mat4 value);
+int honey_shader_set_vec3(lua_State* L);
-/** @brief Set a point_light uniform.
+/** @brief Set a vec4 uniform on a shader.
+ *
+ * @param[in] shader The OpenGL shader handle.
+ * @param[in] name The name of the shader uniform as a string.
+ * @param[in] value The value to set the uniform to.
*
- * @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
+ * @returns Nothing.
*/
-void honey_shader_set_point_light(honey_shader shader,
- int point_light_index,
- honey_point_light light);
+int honey_shader_set_vec4(lua_State* L);
-/** @brief Set a directional_light uniform.
+/** @brief Set a mat3 uniform on a shader.
*
- * @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
+ * @param[in] shader The OpenGL shader handle.
+ * @param[in] name The name of the shader uniform as a string.
+ * @param[in] value The value to set the uniform to.
+ *
+ * @returns Nothing.
*/
-void honey_shader_set_directional_light(honey_shader shader,
- int directional_light_index,
- honey_directional_light light);
+int honey_shader_set_mat3(lua_State* L);
-/** @brief Use a shader.
+/** @brief Set a mat4 uniform on a shader.
+ *
+ * @param[in] shader The OpenGL shader handle.
+ * @param[in] name The name of the shader uniform as a string.
+ * @param[in] value The value to set the uniform to.
+ *
+ * @returns Nothing.
*/
-#define honey_shader_use glUseProgram
+int honey_shader_set_mat4(lua_State* L);
-/** @brief delete a shader.
+/** @brief Delete a shader.
+ *
+ * @param[in] shader An OpenGL shader handle.
+ *
+ * @returns Nothing.
*/
-#define honey_shader_delete glDeleteProgram
+int honey_shader_delete(lua_State* L);
#endif