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.
273 lines
8.9 KiB
273 lines
8.9 KiB
#include "material.h"
|
|
#include "array.h"
|
|
#include "shader.h"
|
|
#include "string_utils.h"
|
|
#include "log.h"
|
|
#include "model.h"
|
|
#include "texture.h"
|
|
#include "light.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
|
|
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;
|
|
unshaded_mat->lit = 0;
|
|
|
|
/* Pipeline params/uniforms */
|
|
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->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("model_mat");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("view_mat");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("inv_model_mat");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
|
|
|
|
/* Material params */
|
|
uniform = array_grow(unshaded_mat->model_params, struct Uniform);
|
|
uniform->name = str_new("diffuse_color");
|
|
uniform->type = UT_VEC4;
|
|
vec4_fill(&uniform->d_vec4, 1.0f, 1.0f, 1.0f, 1.0f);
|
|
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_texture");
|
|
uniform->type = UT_TEX;
|
|
uniform->d_int = texture_find("default.tga");
|
|
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
|
|
|
|
/* Simple blinn_phong material */
|
|
struct Material* blinn_phong_mat = array_grow(material_list, struct Material);
|
|
blinn_phong_mat->name = str_new("Blinn_Phong");
|
|
blinn_phong_mat->shader = shader_create("blinn_phong.vert", "blinn_phong.frag");
|
|
blinn_phong_mat->registered_models = array_new(int);
|
|
blinn_phong_mat->model_params = array_new(struct Uniform);
|
|
blinn_phong_mat->pipeline_params = array_new(struct Uniform);
|
|
blinn_phong_mat->active = 1;
|
|
blinn_phong_mat->lit = 1;
|
|
|
|
/* Pipeline params/uniforms */
|
|
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("mvp");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("model_mat");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("view_mat");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
|
|
uniform->name = str_new("inv_model_mat");
|
|
uniform->type = UT_MAT4;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
/* Material params */
|
|
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
|
|
uniform->name = str_new("diffuse_color");
|
|
uniform->type = UT_VEC4;
|
|
vec4_fill(&uniform->d_vec4, 1.0f, 1.0f, 1.0f, 1.0f);
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
|
|
uniform->name = str_new("diffuse_texture");
|
|
uniform->type = UT_TEX;
|
|
uniform->d_int = texture_find("default.tga");
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
|
|
uniform->name = str_new("specular");
|
|
uniform->type = UT_FLOAT;
|
|
uniform->d_float = 1.f;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
|
|
uniform->name = str_new("diffuse");
|
|
uniform->type = UT_FLOAT;
|
|
uniform->d_float = 1.f;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
|
|
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
|
|
uniform->name = str_new("specular_strength");
|
|
uniform->type = UT_FLOAT;
|
|
uniform->d_float = 50.f;
|
|
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
|
|
}
|
|
|
|
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) = uniform->d_int;
|
|
break;
|
|
case UT_FLOAT:
|
|
param->value = malloc(sizeof(float));
|
|
*((float*)param->value) = uniform->d_float;
|
|
break;
|
|
case UT_VEC2:
|
|
param->value = malloc(sizeof(vec2));
|
|
vec2_assign((vec2*)param->value, &uniform->d_vec2);
|
|
break;
|
|
case UT_VEC3:
|
|
param->value = malloc(sizeof(vec3));
|
|
vec3_assign((vec3*)param->value, &uniform->d_vec3);
|
|
break;
|
|
case UT_VEC4:
|
|
param->value = malloc(sizeof(vec4));
|
|
vec4_assign((vec4*)param->value, &uniform->d_vec4);
|
|
break;
|
|
case UT_MAT4:
|
|
param->value = malloc(sizeof(mat4));
|
|
mat4_identity((mat4*)param->value);
|
|
break;
|
|
case UT_TEX:
|
|
param->value = malloc(sizeof(int));
|
|
*((int*)param->value) = texture_create_from_file("default.tga", TU_DIFFUSE);
|
|
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 textures, if any */
|
|
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(uniform->type == UT_TEX)
|
|
texture_remove(*(int*)param->value);
|
|
}
|
|
/* 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);
|
|
}
|
|
|