diff --git a/orgfile.org b/orgfile.org index 4e1af20..8da50f2 100644 --- a/orgfile.org +++ b/orgfile.org @@ -39,12 +39,14 @@ while using as few libraries as possible. ** DONE Entity - State "DONE" from "TODO" [2015-09-15 Tue 12:17] ** TODO Positive and negative values for input_maps and returning corresponding values when they are true -** TODO Textures +** DONE Textures +- State "DONE" from "TODO" [2015-10-09 Fri 18:47] ** DONE Camera - State "DONE" from "TODO" [2015-08-19 Wed 13:30] ** DONE Test render - State "DONE" from "TODO" [2015-08-19 Wed 13:30] ** TODO Bounding Boxes +** TODO File extension checking for asset loading ** TODO Materials ** TODO Mesh/Model ** TODO Add modifiers to input maps to enable combinations for example, c-x, m-k etc diff --git a/src/game.c b/src/game.c index 326233a..70640b1 100644 --- a/src/game.c +++ b/src/game.c @@ -19,6 +19,7 @@ #include "scene.h" #include "utils.h" #include "texture.h" +#include "material.h" void run(void); void update(float dt); @@ -41,6 +42,7 @@ void game_init(void) transform_init(); camera_init(); geom_init(); + material_init(); model_init(); entity_init(); scene_init(); @@ -74,7 +76,6 @@ void scene_setup(void) input_map_create("Turn_Up", turn_up_keys, 1); input_map_create("Turn_Down", turn_down_keys, 1); - shader_create("unshaded_textured.vert", "unshaded_textured.frag"); struct Entity* player = scene_add_new("player", "None"); player_node = player->node; vec3 viewer_pos = {0, 0, 10}; @@ -99,7 +100,8 @@ void scene_setup(void) struct Entity* ground = scene_add_new("Ground", NULL); struct Model* ground_model = entity_component_add(ground, C_MODEL, "plane.pamesh"); - ground_model->color.x = 1.f; + vec3 color = {1.f, 0.5f, 0.1 }; + model_set_material_param(ground_model, "diffuse_color", &color); struct Transform* ground_tran = entity_component_get(ground, C_TRANSFORM); vec3 pos = {0, -3, -3}; vec3 scale_ground = {0.5f, 0.5f, 3.f}; @@ -262,6 +264,7 @@ void game_cleanup(void) scene_cleanup(); entity_cleanup(); model_cleanup(); + material_cleanup(); geom_cleanup(); transform_cleanup(); camera_cleanup(); diff --git a/src/linmath.h b/src/linmath.h index e2b8521..86f9675 100644 --- a/src/linmath.h +++ b/src/linmath.h @@ -13,6 +13,13 @@ typedef kmMat3 mat3; typedef kmMat4 mat4; typedef kmQuaternion quat; +/* vec2 */ +#define vec2_fill kmVec2Fill +#define vec2_add kmVec2Add +#define vec2_assign kmVec2Assign +#define vec2_norm kmVec2Normalize +#define vec2_mul kmVec2Mul + /* vec3 */ #define vec3_fill kmVec3Fill #define vec3_add kmVec3Add @@ -52,6 +59,8 @@ typedef kmQuaternion quat; #define mat4_rot_x kmMat4RotationX #define mat4_rot_y kmMat4RotationY #define mat4_rot_z kmMat4RotationZ +#define mat4_assign kmMat4Assign +#define mat4_assign_mat3 kmMat4AssignMat3 /* quat */ #define quat_identity kmQuaternionIdentity diff --git a/src/material.c b/src/material.c new file mode 100644 index 0000000..9b52897 --- /dev/null +++ b/src/material.c @@ -0,0 +1,172 @@ +#include "material.h" +#include "array.h" +#include "shader.h" +#include "string_utils.h" +#include "log.h" +#include "model.h" + +#include +#include + +static struct Material* material_list; +static int* empty_indices; + +void material_init(void) +{ + material_list = array_new(struct Material); + empty_indices = array_new(int); + + /* TODO: implement reading material definitions from files */ + /* Simple unshaded material */ + struct Material* unshaded_mat = array_grow(material_list, struct Material); + unshaded_mat->name = str_new("Unshaded"); + unshaded_mat->shader = shader_create("unshaded.vert", "unshaded.frag"); + unshaded_mat->registered_models = array_new(int); + unshaded_mat->model_params = array_new(struct Uniform); + unshaded_mat->pipeline_params = array_new(struct Uniform); + unshaded_mat->active = 1; + + struct Uniform* uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); + uniform->name = str_new("mvp"); + uniform->type = UT_MAT4; + uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); + + uniform = array_grow(unshaded_mat->model_params, struct Uniform); + uniform->name = str_new("diffuse_color"); + uniform->type = UT_VEC4; + uniform->location = shader_get_uniform_location(unshaded_mat->shader, "diffuse_color"); +} + +struct Material* material_get_all_materials(void) +{ + return material_list; +} + +void material_cleanup(void) +{ + for(int i = 0; i < array_len(material_list); i++) + material_remove(i); + array_free(empty_indices); +} + +int material_register_model(struct Model* model, int model_index, const char* material_name) +{ + assert(material_name && model); + int success = 0; + int index = material_get_index(material_name); + if(index < -1) + { + log_error("material:register_model", "Material '%s' not found", material_name); + return success; + } + + struct Material* material = &material_list[index]; + model->material = index; + model->material_params = array_new(struct Material_Param); + for(int i = 0; i < array_len(material->model_params); i++) + { + /* set up parameters */ + struct Uniform* uniform = &material->model_params[i]; + struct Material_Param* param = array_grow(model->material_params, struct Material_Param); + param->uniform_index = i; + switch(uniform->type) + { + case UT_INT: + param->value = malloc(sizeof(int)); + *((int*)param->value) = -1; + break; + case UT_FLOAT: + param->value = malloc(sizeof(float)); + *((float*)param->value) = -1.f; + break; + case UT_VEC2: + param->value = malloc(sizeof(vec2)); + vec2_fill((vec2*)param->value, 0.f, 0.f); + break; + case UT_VEC3: + param->value = malloc(sizeof(vec3)); + vec3_fill((vec3*)param->value, 0.f, 0.f, 0.f); + break; + case UT_VEC4: + param->value = malloc(sizeof(vec4)); + vec4_fill((vec4*)param->value, 0.f, 0.f, 0.f, 0.f); + break; + case UT_MAT4: + param->value = malloc(sizeof(mat4)); + mat4_identity((mat4*)param->value); + break; + } + } + array_push(material->registered_models, model_index, int); + success = 1; + return success; +} + +void material_unregister_model(struct Model* model, int model_index) +{ + assert(model); + struct Material* material = &material_list[model->material]; + /* Remove model index from material registry*/ + for(int i = 0; i < array_len(material->registered_models); i++) + { + if(material->registered_models[i] == model_index) + { + array_remove_at(material->registered_models, i); + break; + } + } +} + +struct Material* material_find(const char* material_name) +{ + struct Material* material = NULL; + int index = material_get_index(material_name); + if(index > -1) material = &material_list[index]; + return material; +} + +int material_get_index(const char* material_name) +{ + int index = -1; + for(int i = 0; i < array_len(material_list); i++) + { + if(!material_list[i].name) continue; + + if(strcmp(material_name, material_list[i].name) == 0) + { + index = i; + break; + } + } + return index; +} + +struct Material* material_get(int index) +{ + struct Material* material = NULL; + if(index > -1 && index < array_len(material_list)) + material = &material_list[index]; + return material; +} + +void material_remove(int index) +{ + assert(index > -1 && index < array_len(material_list)); + struct Material* material = &material_list[index]; + if(!material->active) + return; + material->active = 0; + array_free(material->registered_models); + for(int i = 0; i < array_len(material->model_params); i++) + free(material->model_params[i].name); + array_free(material->model_params); + + for(int i = 0; i < array_len(material->pipeline_params); i++) + free(material->pipeline_params[i].name); + array_free(material->pipeline_params); + + log_message("Removed material '%s'", material->name); + free(material->name); + array_push(empty_indices, index, int); +} + diff --git a/src/material.h b/src/material.h new file mode 100644 index 0000000..679f73c --- /dev/null +++ b/src/material.h @@ -0,0 +1,39 @@ +#ifndef material_H +#define material_H + +struct Model; + +struct Uniform +{ + int location; + int type; + char* name; +}; + +struct Material_Param +{ + int uniform_index; /* Index of the corresponding uniform in the material's model_params */ + void* value; /* Actual value of the uniform */ +}; + +struct Material +{ + char* name; + int shader; + int* registered_models; + int active; + struct Uniform* model_params; /* uniforms related to models */ + struct Uniform* pipeline_params; /* general uniforms like matrices etc */ +}; + +struct Material* material_get_all_materials(void); +struct Material* material_find(const char* material_name); +struct Material* material_get(int index); +int material_get_index(const char* material_name); +void material_init(void); +void material_cleanup(void); +int material_register_model(struct Model* model, int model_index, const char* material_name); +void material_unregister_model(struct Model* model, int model_index); +void material_remove(int index); + +#endif diff --git a/src/model.c b/src/model.c index e3703fc..ea868ae 100644 --- a/src/model.c +++ b/src/model.c @@ -8,11 +8,14 @@ #include "transform.h" #include "texture.h" #include "renderer.h" +#include "material.h" #include "GL/glew.h" #include "GLFW/glfw3.h" #include +#include +#include static struct Model* model_list; static int* empty_indices; @@ -53,8 +56,12 @@ int model_create(int node, const char* geo_name) } new_model->node = node; new_model->geometry_index = geo_index; - new_model->shader = 0; /* Temporary, for test run only till materials are added */ - vec4_fill(&new_model->color, 0.7f, 0.7f, 0.5f, 1.f); + if(!material_register_model(new_model, index, "Unshaded")) + { + log_error("model:create", "Unable to register model with Unshaded material, component not added"); + model_remove(index); + index = -1; + } } else { @@ -71,7 +78,11 @@ void model_remove(int index) model->node = -1; geom_remove(model->geometry_index); model->geometry_index = -1; - model->shader = -1; + material_unregister_model(model, index); + /* deallocate all params */ + for(int i = 0; i < array_len(model->material_params); i++) + free(&model->material_params[i]); + array_free(model->material_params); array_push(empty_indices, index, int); } else @@ -93,24 +104,143 @@ void model_cleanup(void) void model_render_all(struct Camera* camera) { - int texture = texture_find("test_comp.tga"); - mat4 mvp; - for(int i = 0; i < array_len(model_list); i++) + static mat4 mvp; + struct Material* material_list = material_get_all_materials(); + for(int i = 0; i < array_len(material_list); i++) { - struct Model* model = &model_list[i]; - struct Entity* entity = entity_get(model->node); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); - mat4_identity(&mvp); - - shader_bind(model->shader); - shader_set_uniform_int(model->shader, "sampler", (GL_TEXTURE0 + 4) - GL_TEXTURE0); - texture_bind(texture, 4); - renderer_check_glerror("model:render_all"); - mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); - shader_set_uniform_mat4(model->shader, "mvp", &mvp); - shader_set_uniform_vec4(model->shader, "diffuseColor", &model->color); - geom_render(model->geometry_index); - texture_unbind(4); + /* for each material, get all the registered models and render them */ + struct Material* material = &material_list[i]; + if(!material->active) + continue; + + shader_bind(material->shader); + renderer_check_glerror("model:render_all:shader_bind"); + for(int j = 0; j < array_len(material->registered_models); j++) + { + /* for each registered model, set up uniforms and render */ + struct Model* model = &model_list[material->registered_models[j]]; + struct Entity* entity = entity_get(model->node); + struct Transform* transform = entity_component_get(entity, C_TRANSFORM); + for(int k = 0; k < array_len(model->material_params); k++) + { + /* set material params for the model */ + struct Material_Param* param = &model->material_params[k]; + struct Uniform* uniform = &material->model_params[param->uniform_index]; + shader_set_uniform(uniform->type, uniform->location, param->value); + renderer_check_glerror("model:render_all:material_param"); + } + + for(int k = 0; k < array_len(material->pipeline_params); k++) + { + /* TODO: change this into something better */ + /* Set pipeline uniforms */ + struct Uniform* uniform = &material->pipeline_params[k]; + if(strcmp(uniform->name, "mvp") == 0) + { + mat4_identity(&mvp); + mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); + shader_set_uniform(uniform->type, uniform->location, &mvp); + renderer_check_glerror("model:render_all:material_pipeline"); + } + } + /* Render the geometry */ + geom_render(model->geometry_index); + } shader_unbind(); } + /* for(int i = 0; i < array_len(model_list); i++) */ + /* { */ + /* struct Model* model = &model_list[i]; */ + /* struct Entity* entity = entity_get(model->node); */ + /* struct Transform* transform = entity_component_get(entity, C_TRANSFORM); */ + + /* shader_bind(model->shader); */ + /* shader_set_uniform_int(model->shader, "sampler", (GL_TEXTURE0 + 4) - GL_TEXTURE0); */ + /* texture_bind(texture, 4); */ + /* renderer_check_glerror("model:render_all"); */ + /* mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); */ + /* shader_set_uniform_mat4(model->shader, "mvp", &mvp); */ + /* shader_set_uniform_vec4(model->shader, "diffuseColor", &model->color); */ + /* geom_render(model->geometry_index); */ + /* texture_unbind(4); */ + /* shader_unbind(); */ + /* } */ +} + +int model_set_material_param(struct Model* model, const char* name, void* value) +{ + assert(model && name && value); + int success = 0; + struct Material* material = material_get(model->material); + for(int i = 0; i < array_len(model->material_params); i++) + { + struct Material_Param* param = &model->material_params[i]; + struct Uniform* uniform = &material->model_params[param->uniform_index]; + if(strcmp(uniform->name, name) == 0) + { + switch(uniform->type) + { + case UT_INT: + *((int*)param->value) = *((int*)value); + break; + case UT_FLOAT: + *((float*)param->value) = *((float*)value); + break; + case UT_VEC2: + vec2_assign((vec2*)param->value, (vec2*)value); + break; + case UT_VEC3: + vec3_assign((vec3*)param->value, (vec3*)value); + break; + case UT_VEC4: + vec4_assign((vec4*)param->value, (vec4*)value); + break; + case UT_MAT4: + mat4_assign((mat4*)param->value, (mat4*)value); + break; + } + break; /* break for */ + success = 1; + } + } + return success; +} + +int model_get_material_param(struct Model* model, const char* name, void* value_out) +{ + assert(model && name && value_out); + int success = 0; + struct Material* material = material_get(model->material); + for(int i = 0; i < array_len(model->material_params); i++) + { + struct Material_Param* param = &model->material_params[i]; + struct Uniform* uniform = &material->model_params[param->uniform_index]; + if(strcmp(uniform->name, name) == 0) + { + switch(uniform->type) + { + case UT_INT: + *((int*)value_out) = *((int*)param->value); + break; + case UT_FLOAT: + *((float*)value_out) = *((float*)param->value); + break; + case UT_VEC2: + vec2_assign((vec2*)value_out, (vec2*)param->value); + break; + case UT_VEC3: + vec3_assign((vec3*)value_out, (vec3*)param->value); + break; + case UT_VEC4: + vec4_assign((vec4*)value_out, (vec4*)param->value); + break; + case UT_MAT4: + mat4_assign((mat4*)value_out, (mat4*)param->value); + break; + } + break; /* break for */ + success = 1; + } + } + return success; } diff --git a/src/model.h b/src/model.h index 0eed075..d8c115f 100644 --- a/src/model.h +++ b/src/model.h @@ -4,13 +4,14 @@ #include "linmath.h" struct Camera; +struct Material_Param; struct Model { int node; int geometry_index; - int shader; /* Temporary, replace with material */ - vec4 color; + int material; + struct Material_Param* material_params; }; struct Model* model_get(int index); @@ -19,5 +20,7 @@ int model_create(int node, const char* geo_name); void model_remove(int index); void model_cleanup(void); void model_render_all(struct Camera* camera); +int model_set_material_param(struct Model* model, const char* name, void* value); +int model_get_material_param(struct Model* model, const char* name, void* value_out); #endif diff --git a/src/shader.c b/src/shader.c index 2aa002a..9bd8054 100644 --- a/src/shader.c +++ b/src/shader.c @@ -300,3 +300,44 @@ void shader_cleanup(void) array_free(shader_list); array_free(empty_indices); } + +void shader_set_uniform(const int uniform_type, const int uniform_loc, void* value) +{ + assert(value); + switch(uniform_type) + { + case UT_INT: + { + glUniform1i(uniform_loc, *((int*)value)); + break; + } + case UT_FLOAT: + { + glUniform1f(uniform_loc, *((float*)value)); + break; + } + case UT_VEC2: + { + vec2* vector = (vec2*)value; + glUniform2fv(uniform_loc, 1, &vector->x); + break; + } + case UT_VEC3: + { + vec3* vector = (vec3*)value; + glUniform3fv(uniform_loc, 1, &vector->x); + break; + } + case UT_VEC4: + { + vec4* vector = (vec4*)value; + glUniform4fv(uniform_loc, 1, &vector->x); + break; + } + case UT_MAT4: + { + mat4* mat = (mat4*)value; + glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, &mat->mat[0]); + } + } +} diff --git a/src/shader.h b/src/shader.h index 6c91ffd..d36cc53 100644 --- a/src/shader.h +++ b/src/shader.h @@ -2,19 +2,30 @@ #define shader_H #include "linmath.h" - + +enum Uniform_Type +{ + UT_FLOAT = 0, + UT_INT, + UT_VEC3, + UT_VEC2, + UT_VEC4, + UT_MAT4 +}; + int shader_create(const char* vert_shader_name, const char* frag_shader_name); void shader_init(void); void shader_bind(const int shader_index); void shader_remove(const int shader_index); void shader_unbind(void); -void shader_set_uniform_int(const int shaderIndex, const char* name, const int value); -void shader_set_uniform_float(const int shaderIndex, const char* name, const float value); -void shader_set_uniform_vec2(const int shaderIndex, const char* name, const vec2* value); -void shader_set_uniform_vec3(const int shaderIndex, const char* name, const vec3* value); -void shader_set_uniform_vec4(const int shaderIndex, const char* name, const vec4* value); -void shader_set_uniform_mat4(const int shaderIndex, const char* name, const mat4* value); +void shader_set_uniform_int(const int shader_index, const char* name, const int value); +void shader_set_uniform_float(const int shader_index, const char* name, const float value); +void shader_set_uniform_vec2(const int shader_index, const char* name, const vec2* value); +void shader_set_uniform_vec3(const int shader_index, const char* name, const vec3* value); +void shader_set_uniform_vec4(const int shader_index, const char* name, const vec4* value); +void shader_set_uniform_mat4(const int shader_index, const char* name, const mat4* value); +void shader_set_uniform(const int uniform_type, const int uniform_loc, void* value); void shader_cleanup(void); -int shader_uniform_location_get(const int shader_index, const char* name); +int shader_get_uniform_location(const int shader_index, const char* name); #endif