| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- #include <string.h>
- #include "Material.h"
- #include "Resource.h"
- #include "Scanner.h"
- #include "parser.h"
- #include "Texture.h"
- #include "ShaderProg.h"
- #include "Renderer.h"
- #define MTL_ERROR( x ) ERROR( "Material (" << getRsrcPath() << getRsrcName() << "): " << 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::load( const char* filename )
- {
- Scanner scanner;
- if( !scanner.loadFile( filename ) ) return false;
- const Scanner::Token* token;
- do
- {
- token = &scanner.getNextToken();
- //** SHADER_PROG **
- if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "SHADER_PROG" ) )
- {
- if( shaderProg ) ERROR( "Shader program already loaded" );
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- shaderProg = rsrc::shaders.load( token->value.string );
- }
- /*//** DEPTH_SHADER_PROG **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "DEPTH_SHADER_PROG" ) )
- {
- if( depth.shaderProg ) ERROR( "Depth shader program already loaded" );
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- depth.shaderProg = rsrc::shaders.load( token->value.string );
- }*/
- //** DEPTH_MATERIAL **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "DEPTH_PASS_MATERIAL" ) )
- {
- if( dpMtl ) ERROR( "Depth material already loaded" );
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- dpMtl = rsrc::materials.load( token->value.string );
- }
- //** BLENDS **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "BLENDS" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- blends = token->value.int_;
- }
- //** REFRACTS **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "REFRACTS" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- refracts = token->value.int_;
- }
- //** BLENDING_SFACTOR **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "BLENDING_SFACTOR" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::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;
- }
- blendingSfactor = gl_enum;
- }
- //** BLENDING_DFACTOR **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "BLENDING_DFACTOR" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::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;
- }
- blendingDfactor = gl_enum;
- }
- //** DEPTH_TESTING **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "DEPTH_TESTING" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- depthTesting = token->value.int_;
- }
- //** GRASS_MAP **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "GRASS_MAP" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_STRING )
- {
- PARSE_ERR_EXPECTED( "string" );
- return false;
- }
- grassMap = rsrc::textures.load( token->value.string );
- }
- //** WIREFRAME **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "WIREFRAME" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- wireframe = token->value.int_;
- }
- //** CASTS_SHADOW **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "CASTS_SHADOW" ) )
- {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_NUMBER )
- {
- PARSE_ERR_EXPECTED( "number" );
- return false;
- }
- castsShadow = token->value.int_;
- }
- //** USER_DEFINED_VARS **
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "USER_DEFINED_VARS" ) )
- {
- // read {
- token = &scanner.getNextToken();
- if( token->code != Scanner::TC_LBRACKET )
- {
- PARSE_ERR_EXPECTED( "{" );
- return false;
- }
- // loop all the vars
- do
- {
- // read var type
- UserDefinedVar::Type type;
- token = &scanner.getNextToken();
- if( token->code == Scanner::TC_RBRACKET )
- break;
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "TEXTURE" ) )
- type = UserDefinedVar::VT_TEXTURE;
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "FLOAT" ) )
- type = UserDefinedVar::VT_FLOAT;
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "VEC3" ) )
- type = UserDefinedVar::VT_VEC3;
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "VEC4" ) )
- type = UserDefinedVar::VT_VEC4;
- else
- {
- PARSE_ERR_EXPECTED( "TEXTURE or FLOAT or VEC3 or VEC4 or }" );
- return false;
- }
- userDefinedVars.push_back( UserDefinedVar() ); // create new var
- UserDefinedVar& var = userDefinedVars.back();
- var.type = type;
- // read the name
- token = &scanner.getNextToken();
- if( token->code == Scanner::TC_IDENTIFIER )
- var.name = token->value.string;
- else
- {
- PARSE_ERR_EXPECTED( "identifier" );
- return false;
- }
- // read the values
- switch( type )
- {
- // texture
- case UserDefinedVar::VT_TEXTURE:
- token = &scanner.getNextToken();
- if( token->code == Scanner::TC_STRING )
- {
- var.value.texture = rsrc::textures.load( token->value.string );
- }
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "IS_FAI" ) )
- {
- var.value.texture = &R::Is::fai;
- }
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "MS_NORMAL_FAI" ) )
- {
- var.value.texture = &R::Ms::normalFai;
- }
- else if( token->code == Scanner::TC_IDENTIFIER && !strcmp( token->value.string, "MS_DEPTH_FAI" ) )
- {
- var.value.texture = &R::Ms::depthFai;
- }
- else if( token->code == Scanner::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 UserDefinedVar::VT_FLOAT:
- token = &scanner.getNextToken();
- if( token->code == Scanner::TC_NUMBER && token->type == Scanner::DT_FLOAT )
- var.value.float_ = token->value.float_;
- else
- {
- PARSE_ERR_EXPECTED( "float" );
- return false;
- }
- break;
- // vec2
- case UserDefinedVar::VT_VEC2:
- ERROR( "Unimplemented" );
- break;
- // vec3
- case UserDefinedVar::VT_VEC3:
- if( !ParseArrOfNumbers<float>( scanner, true, true, 3, &var.value.vec3[0] ) ) return false;
- break;
- // vec4
- case UserDefinedVar::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::TC_EOF )
- {
- break;
- }
- // other crap
- else
- {
- PARSE_ERR_UNEXPECTED();
- return false;
- }
- }while( true );
- return additionalInit();
- }
- //=====================================================================================================================================
- // additionalInit =
- //=====================================================================================================================================
- bool Material::additionalInit()
- {
- // sanity checks
- if( !shaderProg )
- {
- MTL_ERROR( "Without shader is like cake without sugar (missing SHADER_PROG)" );
- return false;
- }
- /*if( !depth.shaderProg )
- {
- MTL_ERROR( "Without depth shader is like cake without shadow (missing DEPTH_SHADER_PROG)" );
- return false;
- }*/
- // for all user defined vars get their location
- shaderProg->bind();
- for( uint i=0; i<userDefinedVars.size(); i++ )
- {
- int loc = shaderProg->getUniLoc( userDefinedVars[i].name.c_str() );
- if( loc == -1 )
- {
- MTL_ERROR( "Shader \"" << shaderProg->getRsrcName() << "\" and user defined var \"" << userDefinedVars[i].name <<
- "\" do not combine. Incorrect location" );
- return false;
- }
- userDefinedVars[i].uniLoc = loc;
- }
- shaderProg->unbind();
- // init the attribute locations
- attribLocs.tanget = shaderProg->getAttribLocSilently( "tangent" );
- attribLocs.position = shaderProg->getAttribLocSilently( "position" );
- attribLocs.normal = shaderProg->getAttribLocSilently( "normal" );
- attribLocs.texCoords = shaderProg->getAttribLocSilently( "texCoords" );
- // vertex weights
- attribLocs.vertWeightBonesNum = shaderProg->getAttribLocSilently( "vertWeightBonesNum" );
- if( attribLocs.vertWeightBonesNum != -1 )
- {
- attribLocs.vertWeightBoneIds = shaderProg->getAttribLoc( "vertWeightBoneIds" );
- attribLocs.vertWeightWeights = shaderProg->getAttribLoc( "vertWeightWeights" );
- uniLocs.skinningRotations = shaderProg->getUniLoc( "skinningRotations" );
- uniLocs.skinningTranslations = shaderProg->getUniLoc( "skinningTranslations" );
- }
- return true;
- }
- /*
- =======================================================================================================================================
- unload =
- =======================================================================================================================================
- */
- void Material::unload()
- {
- rsrc::shaders.unload( shaderProg );
- // loop all user defined vars and unload the textures
- for( uint i=0; i<userDefinedVars.size(); i++ )
- {
- if( userDefinedVars[i].type == UserDefinedVar::VT_TEXTURE )
- rsrc::textures.unload( userDefinedVars[i].value.texture );
- }
- // the grass map
- if( grassMap )
- rsrc::textures.unload( grassMap );
- }
- /*
- =======================================================================================================================================
- setToDefault =
- =======================================================================================================================================
- */
- void Material::setToDefault()
- {
- shaderProg = NULL;
- blends = false;
- blendingSfactor = GL_ONE;
- blendingDfactor = GL_ZERO;
- depthTesting = true;
- wireframe = false;
- grassMap = NULL;
- castsShadow = true;
- refracts = false;
- dpMtl = NULL;
- /*depth.shaderProg = NULL;
- depth.alpha_testing_map = NULL;*/
- }
- //=====================================================================================================================================
- // setup =
- //=====================================================================================================================================
- void Material::setup()
- {
- shaderProg->bind();
- if( blends )
- {
- glEnable( GL_BLEND );
- //glDisable( GL_BLEND );
- glBlendFunc( blendingSfactor, blendingDfactor );
- }
- else
- glDisable( GL_BLEND );
- if( depthTesting ) 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<UserDefinedVar>::iterator udv;
- for( udv=userDefinedVars.begin(); udv!=userDefinedVars.end(); udv++ )
- {
- switch( udv->type )
- {
- // texture
- case UserDefinedVar::VT_TEXTURE:
- shaderProg->locTexUnit( udv->uniLoc, *udv->value.texture, texture_unit++ );
- break;
- // float
- case UserDefinedVar::VT_FLOAT:
- glUniform1f( udv->uniLoc, udv->value.float_ );
- break;
- // vec2
- case UserDefinedVar::VT_VEC2:
- glUniform2fv( udv->uniLoc, 1, &udv->value.vec2[0] );
- break;
- // vec3
- case UserDefinedVar::VT_VEC3:
- glUniform3fv( udv->uniLoc, 1, &udv->value.vec3[0] );
- break;
- // vec4
- case UserDefinedVar::VT_VEC4:
- glUniform4fv( udv->uniLoc, 1, &udv->value.vec4[0] );
- break;
- }
- }
- }
|