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.
196 lines
7.7 KiB
196 lines
7.7 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 "scene.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;
|
|
char custom_defines[64];
|
|
snprintf(custom_defines, 64, "#define MAX_LIGHTS %d", MAX_SCENE_LIGHTS);
|
|
material->shader = shader_create("blinn_phong.vert", "blinn_phong.frag", custom_defines);
|
|
|
|
if(material->shader == -1)
|
|
{
|
|
log_error("material:init", "Failed to compile shader for Blinn, resetting material");
|
|
material_reset(material);
|
|
return false;
|
|
}
|
|
|
|
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");
|
|
|
|
material->model_params[MMP_UV_SCALE].type = UT_VEC2;
|
|
material->model_params[MMP_UV_SCALE].location = shader_get_uniform_location(material->shader, "uv_scale");
|
|
}
|
|
break;
|
|
case MAT_UNSHADED:
|
|
{
|
|
material->lit = false;
|
|
material->shader = shader_create("unshaded.vert", "unshaded.frag", NULL);
|
|
|
|
if(material->shader == -1)
|
|
{
|
|
log_error("material:init", "Failed to compile shader for Unshaded, resetting material");
|
|
material_reset(material);
|
|
return false;
|
|
}
|
|
|
|
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_UV_SCALE].type = UT_VEC2;
|
|
material->model_params[MMP_UV_SCALE].location = shader_get_uniform_location(material->shader, "uv_scale");
|
|
};
|
|
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;
|
|
|
|
for(int j = 0; j < MMP_MAX; j++)
|
|
variant_init_empty(&mesh->model.material_params[j]);
|
|
|
|
// 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);
|
|
variant_assign_vec2f(&mesh->model.material_params[MMP_UV_SCALE], 1.f, 1.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));
|
|
variant_assign_vec2f(&mesh->model.material_params[MMP_UV_SCALE], 1.f, 1.f);
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|