diff options
Diffstat (limited to 'src/shader')
-rw-r--r-- | src/shader/shader.c | 350 | ||||
-rw-r--r-- | src/shader/shader.h | 137 |
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 |