A 3d fps game made in OpenGL
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Symmetry/src/libsymmetry/material.c

166 lines
6.3 KiB

#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 <string.h>
#include <stdlib.h>
#include <assert.h>
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);
}
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));
}
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;
}
}
}