| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- #include <string.h>
- #include "material.h"
- #include "resource.h"
- #include "scanner.h"
- #include "parser.h"
- #include "texture.h"
- #include "shader_prog.h"
- #include "renderer.h"
- #define MTL_ERROR( x ) ERROR( "Material (" << GetPath() << GetName() << "): " << x );
- /*
- =======================================================================================================================================
- Blending dtuff =
- =======================================================================================================================================
- */
- struct blend_param_t
- {
- int gl_enum;
- const char* str;
- };
- static blend_param_t bparams [] =
- {
- {GL_ZERO, "GL_ZERO"},
- {GL_ONE, "GL_ONE"},
- {GL_DST_COLOR, "GL_DST_COLOR"},
- {GL_ONE_MINUS_DST_COLOR, "GL_ONE_MINUS_DST_COLOR"},
- {GL_SRC_ALPHA, "GL_SRC_ALPHA"},
- {GL_ONE_MINUS_SRC_ALPHA, "GL_ONE_MINUS_SRC_ALPHA"},
- {GL_DST_ALPHA, "GL_DST_ALPHA"},
- {GL_ONE_MINUS_DST_ALPHA, "GL_ONE_MINUS_DST_ALPHA"},
- {GL_SRC_ALPHA_SATURATE, "GL_SRC_ALPHA_SATURATE"},
- {GL_SRC_COLOR, "GL_SRC_COLOR"},
- {GL_ONE_MINUS_SRC_COLOR, "GL_ONE_MINUS_SRC_COLOR"}
- };
- const int BLEND_PARAMS_NUM = 11;
- static bool SearchBlendEnum( const char* str, int& gl_enum )
- {
- for( int i=0; i<BLEND_PARAMS_NUM; i++ )
- {
- if( !strcmp( bparams[i].str, str) )
- {
- gl_enum = bparams[i].gl_enum;
- return true;
- }
- }
- return false;
- }
- /*
- =======================================================================================================================================
- Load =
- =======================================================================================================================================
- */
- bool material_t::Load( const char* filename )
- {
- scanner_t scanner;
- if( !scanner.LoadFile( filename ) ) return false;
- const scanner_t::token_t* token;
- do
- {
- token = &scanner.GetNextToken();
- //** SHADER_PROG **
- if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "SHADER_PROG" ) )
- {
- if( shader_prog ) ERROR( "Shader program allready loaded" );
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- shader_prog = rsrc::shaders.Load( token->value.string );
- }
- /*//** DEPTH_SHADER_PROG **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "DEPTH_SHADER_PROG" ) )
- {
- if( depth.shader_prog ) ERROR( "Depth shader program allready loaded" );
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- depth.shader_prog = rsrc::shaders.Load( token->value.string );
- }*/
- //** DEPTH_MATERIAL **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "DEPTH_PASS_MATERIAL" ) )
- {
- if( dp_mtl ) ERROR( "Depth material already loaded" );
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- dp_mtl = rsrc::materials.Load( token->value.string );
- }
- //** BLENDS **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "BLENDS" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- blends = token->value.int_;
- }
- //** REFRACTS **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "REFRACTS" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- refracts = token->value.int_;
- }
- //** BLENDING_SFACTOR **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "BLENDING_SFACTOR" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_IDENTIFIER )
- {
- PARSE_ERR_EXPECTED( "identifier" );
- return false;
- }
- int gl_enum;
- if( !SearchBlendEnum(token->value.string, gl_enum) )
- {
- PARSE_ERR( "Incorrect blending factor \"" << token->value.string << "\"" );
- return false;
- }
- blending_sfactor = gl_enum;
- }
- //** BLENDING_DFACTOR **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "BLENDING_DFACTOR" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_IDENTIFIER )
- {
- PARSE_ERR_EXPECTED( "identifier" );
- return false;
- }
- int gl_enum;
- if( !SearchBlendEnum(token->value.string, gl_enum) )
- {
- PARSE_ERR( "Incorrect blending factor \"" << token->value.string << "\"" );
- return false;
- }
- blending_dfactor = gl_enum;
- }
- //** DEPTH_TESTING **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "DEPTH_TESTING" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- depth_testing = token->value.int_;
- }
- //** GRASS_MAP **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "GRASS_MAP" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- grass_map = rsrc::textures.Load( token->value.string );
- }
- //** WIREFRAME **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "WIREFRAME" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- wireframe = token->value.int_;
- }
- //** CASTS_SHADOW **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "CASTS_SHADOW" ) )
- {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- casts_shadow = token->value.int_;
- }
- //** USER_DEFINED_VARS **
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "USER_DEFINED_VARS" ) )
- {
- // read {
- token = &scanner.GetNextToken();
- if( token->code != scanner_t::TC_LBRACKET )
- {
- PARSE_ERR_EXPECTED( "{" );
- return false;
- }
- // loop all the vars
- do
- {
- // read var type
- user_defined_var_t::type_e type;
- token = &scanner.GetNextToken();
- if( token->code == scanner_t::TC_RBRACKET )
- break;
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "TEXTURE" ) )
- type = user_defined_var_t::VT_TEXTURE;
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "FLOAT" ) )
- type = user_defined_var_t::VT_FLOAT;
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "VEC3" ) )
- type = user_defined_var_t::VT_VEC3;
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "VEC4" ) )
- type = user_defined_var_t::VT_VEC4;
- else
- {
- PARSE_ERR_EXPECTED( "TEXTURE or FLOAT or VEC3 or VEC4 or }" );
- return false;
- }
- user_defined_vars.push_back( user_defined_var_t() ); // create new var
- user_defined_var_t& var = user_defined_vars.back();
- var.type = type;
- // read the name
- token = &scanner.GetNextToken();
- if( token->code == scanner_t::TC_IDENTIFIER )
- var.name = token->value.string;
- else
- {
- PARSE_ERR_EXPECTED( "identifier" );
- return false;
- }
- // read the values
- switch( type )
- {
- // texture
- case user_defined_var_t::VT_TEXTURE:
- token = &scanner.GetNextToken();
- if( token->code == scanner_t::TC_STRING )
- {
- var.value.texture = rsrc::textures.Load( token->value.string );
- }
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "IS_FAI" ) )
- {
- var.value.texture = &r::is::fai;
- }
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "MS_NORMAL_FAI" ) )
- {
- var.value.texture = &r::ms::normal_fai;
- }
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "MS_DEPTH_FAI" ) )
- {
- var.value.texture = &r::ms::depth_fai;
- }
- else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "PPS_FAI" ) )
- {
- var.value.texture = &r::pps::fai;
- }
- else
- {
- PARSE_ERR_EXPECTED( "string or IS_FAI or MS_NORMAL_FAI or MS_DEPTH_FAI or PPS_FAI" );
- return false;
- }
- break;
- // float
- case user_defined_var_t::VT_FLOAT:
- token = &scanner.GetNextToken();
- if( token->code == scanner_t::TC_NUMBER && token->type == scanner_t::DT_FLOAT )
- var.value.float_ = token->value.float_;
- else
- {
- PARSE_ERR_EXPECTED( "float" );
- return false;
- }
- break;
- // vec2
- case user_defined_var_t::VT_VEC2:
- ERROR( "Unimplemented" );
- break;
- // vec3
- case user_defined_var_t::VT_VEC3:
- if( !ParseArrOfNumbers<float>( scanner, true, true, 3, &var.value.vec3[0] ) ) return false;
- break;
- // vec4
- case user_defined_var_t::VT_VEC4:
- if( !ParseArrOfNumbers<float>( scanner, true, true, 4, &var.value.vec4[0] ) ) return false;
- break;
- };
- }while(true); // end loop for all the vars
- }
- // end of file
- else if( token->code == scanner_t::TC_EOF )
- {
- break;
- }
- // other crap
- else
- {
- PARSE_ERR_UNEXPECTED();
- return false;
- }
- }while( true );
- return AdditionalInit();
- }
- //=====================================================================================================================================
- // AdditionalInit =
- //=====================================================================================================================================
- bool material_t::AdditionalInit()
- {
- // sanity checks
- if( !shader_prog )
- {
- MTL_ERROR( "Without shader is like cake without sugar (missing SHADER_PROG)" );
- return false;
- }
- /*if( !depth.shader_prog )
- {
- MTL_ERROR( "Without depth shader is like cake without shadow (missing DEPTH_SHADER_PROG)" );
- return false;
- }*/
- // for all user defined vars get their location
- shader_prog->Bind();
- for( uint i=0; i<user_defined_vars.size(); i++ )
- {
- int loc = shader_prog->GetUniformLocation( user_defined_vars[i].name.c_str() );
- if( loc == -1 )
- {
- MTL_ERROR( "Shader \"" << shader_prog->GetName() << "\" and user defined var \"" << user_defined_vars[i].name <<
- "\" do not combine. Incorrect location" );
- return false;
- }
- user_defined_vars[i].uniform_location = loc;
- }
- shader_prog->Unbind();
- // init the attribute locations
- attrib_locs.tanget = shader_prog->GetAttributeLocationSilently( "tangent" );
- attrib_locs.position = shader_prog->GetAttributeLocationSilently( "position" );
- attrib_locs.normal = shader_prog->GetAttributeLocationSilently( "normal" );
- attrib_locs.tex_coords = shader_prog->GetAttributeLocationSilently( "tex_coords" );
- // vertex weights
- attrib_locs.vert_weight_bones_num = shader_prog->GetAttributeLocationSilently( "vert_weight_bones_num" );
- if( attrib_locs.vert_weight_bones_num != -1 )
- {
- attrib_locs.vert_weight_bone_ids = shader_prog->GetAttributeLocation( "vert_weight_bone_ids" );
- attrib_locs.vert_weight_weights = shader_prog->GetAttributeLocation( "vert_weight_weights" );
- uni_locs.skinning_rotations = shader_prog->GetUniformLocation( "skinning_rotations" );
- uni_locs.skinning_translations = shader_prog->GetUniformLocation( "skinning_translations" );
- }
- return true;
- }
- /*
- =======================================================================================================================================
- Unload =
- =======================================================================================================================================
- */
- void material_t::Unload()
- {
- rsrc::shaders.Unload( shader_prog );
- // loop all user defined vars and unload the textures
- for( uint i=0; i<user_defined_vars.size(); i++ )
- {
- if( user_defined_vars[i].type == user_defined_var_t::VT_TEXTURE )
- rsrc::textures.Unload( user_defined_vars[i].value.texture );
- }
- // the grass map
- if( grass_map )
- rsrc::textures.Unload( grass_map );
- }
- /*
- =======================================================================================================================================
- SetToDefault =
- =======================================================================================================================================
- */
- void material_t::SetToDefault()
- {
- shader_prog = NULL;
- blends = false;
- blending_sfactor = GL_ONE;
- blending_dfactor = GL_ZERO;
- depth_testing = true;
- wireframe = false;
- grass_map = NULL;
- casts_shadow = true;
- refracts = false;
- dp_mtl = NULL;
- /*depth.shader_prog = NULL;
- depth.alpha_testing_map = NULL;*/
- }
- //=====================================================================================================================================
- // Setup =
- //=====================================================================================================================================
- void material_t::Setup()
- {
- shader_prog->Bind();
- if( blends )
- {
- glEnable( GL_BLEND );
- //glDisable( GL_BLEND );
- glBlendFunc( blending_sfactor, blending_dfactor );
- }
- else
- glDisable( GL_BLEND );
- if( depth_testing ) glEnable( GL_DEPTH_TEST );
- else glDisable( GL_DEPTH_TEST );
- if( wireframe ) glPolygonMode( GL_FRONT, GL_LINE );
- else glPolygonMode( GL_FRONT, GL_FILL );
- // now loop all the user defined vars and set them
- uint texture_unit = 0;
- vec_t<user_defined_var_t>::iterator udv;
- for( udv=user_defined_vars.begin(); udv!=user_defined_vars.end(); udv++ )
- {
- switch( udv->type )
- {
- // texture
- case user_defined_var_t::VT_TEXTURE:
- shader_prog->LocTexUnit( udv->uniform_location, *udv->value.texture, texture_unit++ );
- break;
- // float
- case user_defined_var_t::VT_FLOAT:
- glUniform1f( udv->uniform_location, udv->value.float_ );
- break;
- // vec2
- case user_defined_var_t::VT_VEC2:
- glUniform2fv( udv->uniform_location, 1, &udv->value.vec2[0] );
- break;
- // vec3
- case user_defined_var_t::VT_VEC3:
- glUniform3fv( udv->uniform_location, 1, &udv->value.vec3[0] );
- break;
- // vec4
- case user_defined_var_t::VT_VEC4:
- glUniform4fv( udv->uniform_location, 1, &udv->value.vec4[0] );
- break;
- }
- }
- }
|