16 #include <boost/smart_ptr.hpp>
24 using namespace XMLDOM;
46 explicit Exception(
const std::string &message ) : _message( message ) {}
47 virtual const char *
what()
const throw ()
49 return _message.c_str();
65 template <
typename T >
66 static T
parseEnum(
const string &s,
const map< string, T > &enumMap )
68 typename map< string, T >::const_iterator it = enumMap.find( s );
69 if ( it != enumMap.end() )
74 template <
typename T >
75 static T
parseEnum(
const string &s,
const map< string, T > &enumMap, T deflt )
77 typename map< string, T >::const_iterator it = enumMap.find( s );
78 if ( it != enumMap.end() )
86 static map< string, Technique::Pass::TextureUnit::SourceType >enumMap;
87 if ( enumMap.empty() ) {
98 static map< string, Technique::Pass::TextureUnit::Kind >enumMap;
99 if ( enumMap.empty() ) {
111 static map< string, Technique::Pass::Type >enumMap;
112 if ( enumMap.empty() ) {
128 static map< string, Technique::Pass::Tristate >enumMap;
129 if ( enumMap.empty() ) {
139 static map<string, Technique::Pass::BlendMode> enumMap;
140 if (enumMap.empty()) {
154 static map< string, Technique::Pass::Face >enumMap;
155 if ( enumMap.empty() ) {
167 static map< string, Technique::Pass::DepthFunction >enumMap;
168 if ( enumMap.empty() ) {
182 static map<string, Technique::Pass::PolyMode> enumMap;
183 if (enumMap.empty()) {
193 static map< string, Technique::Pass::ShaderParam::Semantic >enumMap;
194 if ( enumMap.empty() ) {
203 enumMap[
"ApparentLightSizeArray"] =
212 static string once(
"once" );
227 static int parseInt(
const std::string &s,
int deflt )
244 string::size_type ini = 0, end;
246 while (i < 4 && ini != string::npos) {
247 value[i++] =
parseFloat( s.substr( ini, end = s.find_first_of(
',', ini ) ) );
248 ini = ( (end == string::npos) ? end : (end+1) );
250 if (i >= 4 && ini != string::npos)
259 using namespace __impl;
266 , perLightIteration( 0 )
268 , blendMode( Default )
269 , depthFunction( LEqual )
270 , cullMode( DefaultFace )
285 vertexProgram = vertex;
286 fragmentProgram = fragment;
293 const string ¶mName,
296 textureUnits.resize( textureUnits.size()+1 );
299 string::size_type ssep = string::npos, dsep = string::npos;
309 case TextureUnit::Decal:
310 case TextureUnit::Detail:
311 if (ssep == string::npos)
throw InvalidParameters(
"Decal/Detail reference missing source index" );
314 case TextureUnit::File:
315 if (ssep == string::npos)
throw InvalidParameters(
"File reference missing path" );
316 newTU.
sourcePath.assign( source, ssep+1, string::npos );
318 case TextureUnit::Environment:
324 case TextureUnit::Decal:
325 case TextureUnit::Detail:
326 if (dsep == string::npos)
throw InvalidParameters(
"Decal/Detail reference missing source index" );
329 case TextureUnit::File:
330 if (dsep == string::npos)
throw InvalidParameters(
"File reference missing path" );
331 newTU.
defaultPath.assign( deflt, dsep+1, string::npos );
333 case TextureUnit::None:
334 case TextureUnit::Environment:
342 shaderParams.resize( shaderParams.size()+1 );
343 ShaderParam &newSP = shaderParams.back();
347 newSP.semantic = ShaderParam::Constant;
348 newSP.optional = optional;
349 for (
int i = 0;
i < 4; ++
i)
350 newSP.value[i] = value[i];
355 shaderParams.resize( shaderParams.size()+1 );
356 ShaderParam &newSP = shaderParams.back();
360 newSP.semantic = semantic;
361 newSP.optional = optional;
367 if (type == ShaderPass) {
381 defines +=
"#define SRGB_FRAMEBUFFER 1\n";
383 defines +=
"#define SRGB_FRAMEBUFFER 0\n";
386 defines +=
"#define VGL_NV_fragment_program2 1\n";
390 (defines.empty() ? NULL : defines.c_str()) );
393 "Error compiling program vp:\""+vertexProgram
394 +
"\" fp:\""+fragmentProgram+
"\"" );
397 vertexProgram.c_str(), fragmentProgram.c_str() );
400 for (ShaderParamList::iterator it = shaderParams.begin(); it != shaderParams.end(); ++it) {
407 it->name.c_str(), vertexProgram.c_str(), fragmentProgram.c_str() );
411 for (TextureUnitList::iterator tit = textureUnits.begin(); tit != textureUnits.end(); ++tit) {
412 if (tit->sourceType == TextureUnit::File) {
414 if (tit->texture.get() == 0) {
415 tit->texture.reset(
new Texture( tit->sourcePath.c_str() ) );
417 "Cannot load texture file \""+tit->sourcePath+
"\"" );
419 }
else if (tit->defaultType == TextureUnit::File) {
421 if (tit->texture.get() == 0) {
422 tit->texture.reset(
new Texture( tit->defaultPath.c_str() ) );
424 "Cannot load texture file \""+tit->defaultPath+
"\"" );
427 if (!tit->targetParamName.empty()) {
429 if (tit->targetParamId < 0) {
430 if (tit->origTargetIndex >= 0)
432 "Cannot resolve shader constant \""+tit->targetParamName+
"\"" );
434 tit->targetIndex = -1;
436 if (tit->origTargetIndex < 0)
437 tit->targetIndex = lastTU+1;
438 lastTU =
std::max( tit->targetIndex, lastTU );
452 return (type != ShaderPass) || (program != 0);
458 return (type != ShaderPass) || (program != 0 && this->programVersion == programVersion);
464 , programVersion( 0 )
466 static string passTag(
"pass" );
467 static string techniqueTag(
"technique" );
468 static string vpTag(
"vertex_program" );
469 static string fpTag(
"fragment_program" );
470 static string tuTag(
"texture_unit" );
471 static string paramTag(
"param" );
472 static string autoParamTag(
"auto_param" );
483 +name+
".technique" );
489 +name+
".technique" );
492 auto_ptr< XMLDOM::XMLDocument >doc( serializer.
close() );
497 for (XMLElement::const_child_iterator it = doc->root.childrenBegin(); it != doc->root.childrenEnd(); ++it) {
499 if (el->
type() == XMLElement::XET_TAG && el->
tagName() == techniqueTag) {
507 fallback = techniqueNode->getAttributeValue(
"fallback",
"" );
509 unsigned int nextSequence = 0;
510 for (XMLElement::const_child_iterator it = techniqueNode->childrenBegin(); it != techniqueNode->childrenEnd(); ++it) {
512 if (el->
type() == XMLElement::XET_TAG) {
513 if (el->
tagName() == passTag) {
531 nextSequence = pass.sequence+1;
536 if (el->
type() == XMLElement::XET_TAG) {
539 "Duplicate vertex program reference in technique \""+name+
"\"" );
541 }
else if (el->
tagName() == fpTag) {
543 "Duplicate fragment program reference in technique \""+name+
"\"" );
545 }
else if (el->
tagName() == tuTag) {
558 pass.getNumTextureUnits(),
560 }
else if (el->
tagName() == paramTag) {
568 pass.getNumShaderParams(),
570 value[0], value[1], value[2], value[3],
572 }
else if (el->
tagName() == autoParamTag) {
578 pass.getNumShaderParams(),
589 throw InvalidParameters(
"Missing vertex program reference in technique \""+name+
"\"" );
591 throw InvalidParameters(
"Missing fragment program reference in technique \""+name+
"\"" );
592 pass.setProgram( vp, fp );
603 , fallback( src.fallback )
605 , programVersion( 0 )
621 for (PassList::iterator it =
passes.begin(); it !=
passes.end(); ++it)
638 while ( !ptr->isCompiled() ) {
642 "Compilation of technique %s successful\n",
643 ptr->getName().c_str() );
646 std::string fallback = ptr->getFallback();
648 "Compilation of technique %s failed... trying %s\n"
650 ptr->getName().c_str(),
653 if (!fallback.empty() && fallback != name)
659 if ( ptr->isCompiled() )