#include "material.h" #include "../common/array.h" #include "shader.h" #include "entity.h" #include "../common/string_utils.h" #include "../common/log.h" #include "texture.h" #include "light.h" #include #include #include bool material_init(struct Material* material, int material_type) { assert(material && material_type > -1 && material_type < MAT_MAX); material->type = material_type; memset(material->registered_static_meshes, '\0', sizeof(struct Static_Mesh*) * MAX_MATERIAL_REGISTERED_STATIC_MESHES); memset(material->model_params, 0, sizeof(struct Uniform) * MMP_MAX); memset(material->pipeline_params, 0, sizeof(struct Uniform) * MPP_MAX); switch(material_type) { case MAT_BLINN: { material->lit = true; material->shader = shader_create("blinn_phong.vert", "blinn_phong.frag"); material->pipeline_params[MPP_INV_MODEL_MAT].type = UT_MAT4; material->pipeline_params[MPP_INV_MODEL_MAT].location = shader_get_uniform_location(material->shader, "inv_model_mat"); material->pipeline_params[MPP_VIEW_MAT].type = UT_MAT4; material->pipeline_params[MPP_VIEW_MAT].location = shader_get_uniform_location(material->shader, "view_mat"); material->pipeline_params[MPP_CAM_POS].type = UT_VEC3; material->pipeline_params[MPP_CAM_POS].location = shader_get_uniform_location(material->shader, "camera_pos"); material->pipeline_params[MPP_TOTAL_LIGHTS].type = UT_INT; material->pipeline_params[MPP_TOTAL_LIGHTS].location = shader_get_uniform_location(material->shader, "total_active_lights"); material->model_params[MMP_DIFFUSE_TEX].type = UT_TEX; material->model_params[MMP_DIFFUSE_TEX].location = shader_get_uniform_location(material->shader, "diffuse_texture"); material->model_params[MMP_DIFFUSE_COL].type = UT_VEC4; material->model_params[MMP_DIFFUSE_COL].location = shader_get_uniform_location(material->shader, "diffuse_color"); material->model_params[MMP_DIFFUSE].type = UT_FLOAT; material->model_params[MMP_DIFFUSE].location = shader_get_uniform_location(material->shader, "diffuse"); material->model_params[MMP_SPECULAR].type = UT_FLOAT; material->model_params[MMP_SPECULAR].location = shader_get_uniform_location(material->shader, "specular"); material->model_params[MMP_SPECULAR_STRENGTH].type = UT_FLOAT; material->model_params[MMP_SPECULAR_STRENGTH].location = shader_get_uniform_location(material->shader, "specular_strength"); } break; case MAT_UNSHADED: { material->lit = false; material->shader = shader_create("unshaded.vert", "unshaded.frag"); material->model_params[MMP_DIFFUSE_TEX].type = UT_TEX; material->model_params[MMP_DIFFUSE_TEX].location = shader_get_uniform_location(material->shader, "diffuse_texture"); material->model_params[MMP_DIFFUSE_COL].type = UT_VEC4; material->model_params[MMP_DIFFUSE_COL].location = shader_get_uniform_location(material->shader, "diffuse_color"); }; break; default: log_error("material:init", "Invalid material type"); return false; } // Setup common pipeline parameters material->pipeline_params[MPP_FOG_MODE].type = UT_INT; material->pipeline_params[MPP_FOG_MODE].location = shader_get_uniform_location(material->shader, "fog.mode"); material->pipeline_params[MPP_FOG_DENSITY].type = UT_FLOAT; material->pipeline_params[MPP_FOG_DENSITY].location = shader_get_uniform_location(material->shader, "fog.density"); material->pipeline_params[MPP_FOG_START_DIST].type = UT_FLOAT; material->pipeline_params[MPP_FOG_START_DIST].location = shader_get_uniform_location(material->shader, "fog.start_dist"); material->pipeline_params[MPP_FOG_MAX_DIST].type = UT_FLOAT; material->pipeline_params[MPP_FOG_MAX_DIST].location = shader_get_uniform_location(material->shader, "fog.max_dist"); material->pipeline_params[MPP_FOG_COLOR].type = UT_VEC3; material->pipeline_params[MPP_FOG_COLOR].location = shader_get_uniform_location(material->shader, "fog.color"); material->pipeline_params[MPP_MVP].type = UT_MAT4; material->pipeline_params[MPP_MVP].location = shader_get_uniform_location(material->shader, "mvp"); material->pipeline_params[MPP_MODEL_MAT].type = UT_MAT4; material->pipeline_params[MPP_MODEL_MAT].location = shader_get_uniform_location(material->shader, "model_mat"); material->pipeline_params[MPP_AMBIENT_LIGHT].type = UT_VEC3; material->pipeline_params[MPP_AMBIENT_LIGHT].location = shader_get_uniform_location(material->shader, "ambient_light"); return true; } void material_reset(struct Material* material) { assert(material); material->type = -1; memset(material->registered_static_meshes, '\0', sizeof(struct Static_Mesh*) * MAX_MATERIAL_REGISTERED_STATIC_MESHES); memset(material->model_params, 0, sizeof(struct Uniform) * MMP_MAX); memset(material->pipeline_params, 0, sizeof(struct Uniform) * MPP_MAX); } bool material_register_static_mesh(struct Material* material, struct Static_Mesh* mesh) { assert(material); for(int i = 0; i < MAX_MATERIAL_REGISTERED_STATIC_MESHES; i++) { if(!material->registered_static_meshes[i]) { material->registered_static_meshes[i] = mesh; // Set default values for instance parameters switch(material->type) { case MAT_BLINN: { variant_assign_vec4f(&mesh->model.material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f); variant_assign_float(&mesh->model.material_params[MMP_DIFFUSE], 1.f); variant_assign_int(&mesh->model.material_params[MMP_DIFFUSE_TEX], texture_create_from_file("default.tga", TU_DIFFUSE)); variant_assign_float(&mesh->model.material_params[MMP_SPECULAR], 1.f); variant_assign_float(&mesh->model.material_params[MMP_SPECULAR_STRENGTH], 50.f); mesh->model.material = material; } break; case MAT_UNSHADED: { variant_assign_vec4f(&mesh->model.material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f); variant_assign_int(&mesh->model.material_params[MMP_DIFFUSE_TEX], texture_create_from_file("default.tga", TU_DIFFUSE)); mesh->model.material = material; } break; default: log_error("material:register_model", "Invalid material type"); break; } return true; } } return false; } void material_unregister_static_mesh(struct Material* material, struct Static_Mesh* mesh) { assert(material); for(int i = 0; i < MAX_MATERIAL_REGISTERED_STATIC_MESHES; i++) { if(material->registered_static_meshes[i] == mesh) { material->registered_static_meshes[i] = NULL; for(int i = 0; i < MMP_MAX; i++) variant_free(&mesh->model.material_params[i]); break; } } }