Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreQuake3ShaderManager.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreQuake3ShaderManager.h"
00026 #include "OgreQuake3Shader.h"
00027 #include "OgreStringVector.h"
00028 #include "OgreException.h"
00029 
00030 namespace Ogre {
00031 
00032     //-----------------------------------------------------------------------
00033     template<> Quake3ShaderManager *Singleton<Quake3ShaderManager>::ms_Singleton = 0;
00034     Quake3ShaderManager* Quake3ShaderManager::getSingletonPtr(void)
00035     {
00036         return ms_Singleton;
00037     }
00038     Quake3ShaderManager& Quake3ShaderManager::getSingleton(void)
00039     {  
00040         assert( ms_Singleton );  return ( *ms_Singleton );  
00041     }
00042     //-----------------------------------------------------------------------
00043 
00044     //-----------------------------------------------------------------------
00045     Quake3ShaderManager::Quake3ShaderManager()
00046     {
00047     }
00048     //-----------------------------------------------------------------------
00049     Quake3ShaderManager::~Quake3ShaderManager()
00050     {
00051     }
00052     //-----------------------------------------------------------------------
00053     void Quake3ShaderManager::parseShaderFile(DataChunk& chunk)
00054     {
00055         String line;
00056         Quake3Shader* pShader;
00057         char tempBuf[512];
00058 
00059         pShader = 0;
00060 
00061         while(!chunk.isEOF())
00062         {
00063             line = chunk.getLine();
00064             // Ignore comments & blanks
00065             if (!(line.length() == 0 || line.substr(0,2) == "//"))
00066             {
00067                 if (pShader == 0)
00068                 {
00069                     // No current shader
00070                     // So first valid data should be a shader name
00071                     pShader = (Quake3Shader*)create(line);
00072                     // Skip to and over next {
00073                     chunk.readUpTo(tempBuf, 511, "{");
00074                 }
00075                 else
00076                 {
00077                     // Already in a shader
00078                     if (line == "}")
00079                     {
00080                         // Finished shader
00081                         pShader = 0;
00082                     }
00083                     else if (line == "{")
00084                     {
00085                         // new pass
00086                         parseNewShaderPass(chunk, pShader);
00087 
00088                     }
00089                     else
00090                     {
00091                         // Attribute
00092                         StringUtil::toLowerCase(line);
00093                         parseShaderAttrib(line, pShader);
00094                     }
00095 
00096                 }
00097 
00098             }
00099 
00100 
00101         }
00102 
00103     }
00104     //-----------------------------------------------------------------------
00105     void Quake3ShaderManager::parseAllSources(const String& extension)
00106     {
00107         StringVector shaderFiles;
00108         DataChunk* pChunk;
00109 
00110         std::vector<ArchiveEx*>::iterator i = mVFS.begin();
00111 
00112         // Specific archives
00113         for (; i != mVFS.end(); ++i)
00114         {
00115             shaderFiles = (*i)->getAllNamesLike( "./", extension);
00116             for (StringVector::iterator si = shaderFiles.begin(); si!=shaderFiles.end(); ++si)
00117             {
00118                 DataChunk dat; pChunk = &dat;
00119                 (*i)->fileRead(si[0], &pChunk );
00120                 parseShaderFile(dat);
00121             }
00122 
00123         }
00124         // search common archives
00125         for (i = mCommonVFS.begin(); i != mCommonVFS.end(); ++i)
00126         {
00127             shaderFiles = (*i)->getAllNamesLike( "./", extension);
00128             for (StringVector::iterator si = shaderFiles.begin(); si!=shaderFiles.end(); ++si)
00129             {
00130                 DataChunk dat; pChunk = &dat;
00131                 (*i)->fileRead(si[0], &pChunk );
00132                 parseShaderFile(dat);
00133             }
00134         }
00135 
00136 
00137     }
00138     //-----------------------------------------------------------------------
00139     Resource* Quake3ShaderManager::create( const String& name)
00140     {
00141         Quake3Shader* s = new Quake3Shader(name);
00142         try {
00143             // Gah, Q3A shader scripts include some duplicates - grr
00144             this->add(s);
00145         }
00146         catch (Exception& e)
00147         {
00148             if (e.getNumber() == Exception::ERR_DUPLICATE_ITEM)
00149             {
00150                 // deliberately ignore, will get parsed again but will not be used
00151             }
00152             else
00153             {
00154                 throw;
00155             }
00156         }
00157         return s;
00158     }
00159     //-----------------------------------------------------------------------
00160     void Quake3ShaderManager::parseNewShaderPass(DataChunk& chunk, Quake3Shader* pShader)
00161     {
00162         String line;
00163         int passIdx;
00164 
00165         passIdx = pShader->numPasses;
00166         pShader->numPasses++;
00167         pShader->pass.resize(pShader->numPasses);
00168 
00169         // Default pass details
00170         pShader->pass[passIdx].animNumFrames = 0;
00171         pShader->pass[passIdx].blend = LBO_REPLACE;
00172         pShader->pass[passIdx].blendDest = SBF_ZERO;
00173         pShader->pass[passIdx].blendSrc = SBF_ONE;
00174         pShader->pass[passIdx].depthFunc = CMPF_LESS_EQUAL;
00175         pShader->pass[passIdx].flags = 0;
00176         pShader->pass[passIdx].rgbGenFunc = SHADER_GEN_IDENTITY;
00177         pShader->pass[passIdx].tcModRotate = 0;
00178         pShader->pass[passIdx].tcModScale[0] = pShader->pass[passIdx].tcModScale[1] = 1.0;
00179         pShader->pass[passIdx].tcModScroll[0] = pShader->pass[passIdx].tcModScroll[1] = 0;
00180         pShader->pass[passIdx].tcModStretchWave = SHADER_FUNC_NONE;
00181         pShader->pass[passIdx].tcModTransform[0] = pShader->pass[passIdx].tcModTransform[1] = 0;
00182         pShader->pass[passIdx].tcModTurbOn = false;
00183         pShader->pass[passIdx].tcModTurb[0] = pShader->pass[passIdx].tcModTurb[1] =
00184             pShader->pass[passIdx].tcModTurb[2] = pShader->pass[passIdx].tcModTurb[3] = 0;
00185         pShader->pass[passIdx].texGen = TEXGEN_BASE;
00186         pShader->pass[passIdx].addressMode = TextureUnitState::TAM_WRAP;
00187         pShader->pass[passIdx].customBlend = false;
00188         pShader->pass[passIdx].alphaVal = 0;
00189         pShader->pass[passIdx].alphaFunc = CMPF_ALWAYS_PASS;
00190 
00191         while (!chunk.isEOF())
00192         {
00193             line = chunk.getLine();
00194             // Ignore comments & blanks
00195             if (line.length() != 0 && line.substr(0,2) != "//")
00196             {
00197                 if (line == "}")
00198                 {
00199                     // end of shader
00200                     return;
00201                 }
00202                 else
00203                 {
00204                     parseShaderPassAttrib(line, pShader, &pShader->pass[passIdx]);
00205                 }
00206             }
00207 
00208 
00209         }
00210     }
00211     //-----------------------------------------------------------------------
00212     void Quake3ShaderManager::parseShaderAttrib( const String& line, Quake3Shader* pShader)
00213     {
00214         StringVector vecparams;
00215 
00216         vecparams = StringUtil::split(line, " \t");
00217         StringVector::iterator params = vecparams.begin();
00218 
00219         if (params[0] == "skyparms")
00220         {
00221             if (params[1] != "-")
00222             {
00223                 pShader->farbox = true;
00224                 pShader->farboxName = params[1];
00225             }
00226             if (params[2] != "-")
00227             {
00228                 pShader->skyDome = true;
00229                 pShader->cloudHeight = atof(params[2].c_str());
00230             }
00231             // nearbox not supported
00232         }
00233         else if (params[0] == "cull")
00234         {
00235             if (params[1] == "diable" || params[1] == "none")
00236             {
00237                 pShader->cullMode = MANUAL_CULL_NONE;
00238             }
00239             else if (params[1] == "front")
00240             {
00241                 pShader->cullMode = MANUAL_CULL_FRONT;
00242             }
00243             else if (params[1] == "back")
00244             {
00245                 pShader->cullMode = MANUAL_CULL_BACK;
00246             }
00247         }
00248         else if (params[0] == "deformvertexes")
00249         {
00250             // TODO
00251         }
00252         else if (params[0] == "fogparms")
00253         {
00254             Real r,g,b;
00255             r = atof(params[1].c_str());
00256             g = atof(params[2].c_str());
00257             b = atof(params[3].c_str());
00258             pShader->fog = true;
00259             pShader->fogColour = ColourValue(r,g,b);
00260             pShader->fogDistance = atof(params[4].c_str());
00261 
00262         }
00263     }
00264     //-----------------------------------------------------------------------
00265     void Quake3ShaderManager::parseShaderPassAttrib( const String& line, Quake3Shader* pShader, Quake3Shader::Pass* pPass)
00266     {
00267         StringVector vecparams;
00268 
00269         vecparams = StringUtil::split(line, " \t");
00270         StringVector::iterator params = vecparams.begin();
00271 
00272         StringUtil::toLowerCase(params[0]);
00273         if (params[0] != "map" && params[0] != "clampmap" && params[0] != "animmap")
00274         {
00275             // lower case all except textures
00276             for (size_t i = 1; i < vecparams.size(); ++i)
00277                 StringUtil::toLowerCase(params[i]);
00278         }
00279 
00280 
00281         // MAP
00282         if (params[0] == "map")
00283         {
00284             pPass->textureName = params[1];
00285             StringUtil::toLowerCase(params[1]);
00286             if (params[1] == "$lightmap")
00287                 pPass->texGen = TEXGEN_LIGHTMAP;
00288         }
00289         // CLAMPMAP
00290         if (params[0] == "clampmap")
00291         {
00292             pPass->textureName = params[1];
00293             StringUtil::toLowerCase(params[1]);
00294             if (params[1] == "$lightmap")
00295                 pPass->texGen = TEXGEN_LIGHTMAP;
00296             pPass->addressMode = TextureUnitState::TAM_CLAMP;
00297         }
00298         // ANIMMAP
00299         else if (params[0] == "animmap")
00300         {
00301             pPass->animFps = atof(params[1].c_str());
00302             pPass->animNumFrames = static_cast<unsigned int>( vecparams.size() - 2 );
00303             for (unsigned int frame = 0; frame < pPass->animNumFrames; ++frame)
00304             {
00305                 pPass->frames[frame] = params[frame+2];
00306             }
00307         }
00308         // BLENDFUNC
00309         else if (params[0] == "blendfunc")
00310         {
00311             if (params[1] == "add" || params[1] == "gl_add")
00312             {
00313                 pPass->blend = LBO_ADD;
00314                 pPass->blendDest = SBF_ONE;
00315                 pPass->blendSrc = SBF_ONE;
00316             }
00317             else if (params[1] == "filter" || params[1] == "gl_filter")
00318             {
00319                 pPass->blend = LBO_MODULATE;
00320                 pPass->blendDest = SBF_ZERO;
00321                 pPass->blendSrc = SBF_DEST_COLOUR;
00322             }
00323             else if (params[1] == "blend" || params[1] == "gl_blend")
00324             {
00325                 pPass->blend = LBO_ALPHA_BLEND;
00326                 pPass->blendDest = SBF_ONE_MINUS_SOURCE_ALPHA;
00327                 pPass->blendSrc = SBF_SOURCE_ALPHA;
00328             }
00329             else
00330             {
00331                 // Manual blend
00332                 pPass->blendSrc = convertBlendFunc(params[1]);
00333                 pPass->blendDest = convertBlendFunc(params[2]);
00334                 // Detect common blends
00335                 if (pPass->blendSrc == SBF_ONE && pPass->blendDest == SBF_ZERO)
00336                     pPass->blend = LBO_REPLACE;
00337                 else if (pPass->blendSrc == SBF_ONE && pPass->blendDest == SBF_ONE)
00338                     pPass->blend = LBO_ADD;
00339                 else if ((pPass->blendSrc == SBF_ZERO && pPass->blendDest == SBF_SOURCE_COLOUR) ||
00340                     (pPass->blendSrc == SBF_DEST_COLOUR && pPass->blendDest == SBF_ZERO))
00341                     pPass->blend = LBO_MODULATE;
00342                 else if (pPass->blendSrc == SBF_SOURCE_ALPHA && pPass->blendDest == SBF_ONE_MINUS_SOURCE_ALPHA)
00343                     pPass->blend = LBO_ALPHA_BLEND;
00344                 else
00345                     pPass->customBlend = true;
00346 
00347 
00348                 // NB other custom blends might not work due to OGRE trying to use multitexture over multipass
00349             }
00350         }
00351         // RGBGEN
00352         else if (params[0] == "rgbgen")
00353         {
00354             // TODO
00355         }
00356         // ALPHAGEN
00357         else if (params[0] == "alphagen")
00358         {
00359             // TODO
00360         }
00361         // TCGEN
00362         else if (params[0] == "tcgen")
00363         {
00364             if (params[1] == "base")
00365             {
00366                 pPass->texGen = TEXGEN_BASE;
00367             }
00368             else if (params[1] == "lightmap")
00369             {
00370                 pPass->texGen = TEXGEN_LIGHTMAP;
00371             }
00372             else if (params[1] == "environment")
00373             {
00374                 pPass->texGen = TEXGEN_ENVIRONMENT;
00375             }
00376         }
00377         // TCMOD
00378         else if (params[0] == "tcmod")
00379         {
00380             if (params[1] == "rotate")
00381             {
00382                 pPass->tcModRotate = -atof(params[2].c_str()) / 360; // +ve is clockwise degrees in Q3 shader, anticlockwise complete rotations in Ogre
00383             }
00384             else if (params[1] == "scroll")
00385             {
00386                 pPass->tcModScroll[0] = atof(params[2].c_str());
00387                 pPass->tcModScroll[1] = atof(params[3].c_str());
00388             }
00389             else if (params[1] == "scale")
00390             {
00391                 pPass->tcModScale[0] = atof(params[2].c_str());
00392                 pPass->tcModScale[1] = atof(params[3].c_str());
00393             }
00394             else if (params[1] == "stretch")
00395             {
00396                 if (params[2] == "sin")
00397                     pPass->tcModStretchWave = SHADER_FUNC_SIN;
00398                 else if (params[2] == "triangle")
00399                     pPass->tcModStretchWave = SHADER_FUNC_TRIANGLE;
00400                 else if (params[2] == "square")
00401                     pPass->tcModStretchWave = SHADER_FUNC_SQUARE;
00402                 else if (params[2] == "sawtooth")
00403                     pPass->tcModStretchWave = SHADER_FUNC_SAWTOOTH;
00404                 else if (params[2] == "inversesawtooth")
00405                     pPass->tcModStretchWave = SHADER_FUNC_INVERSESAWTOOTH;
00406 
00407                 pPass->tcModStretchParams[0] = atof(params[3].c_str());
00408                 pPass->tcModStretchParams[1] = atof(params[4].c_str());
00409                 pPass->tcModStretchParams[2] = atof(params[5].c_str());
00410                 pPass->tcModStretchParams[3] = atof(params[6].c_str());
00411 
00412             }
00413         }
00414         // TURB
00415         else if (params[0] == "turb")
00416         {
00417             pPass->tcModTurbOn = true;
00418             pPass->tcModTurb[0] = atof(params[2].c_str());
00419             pPass->tcModTurb[1] = atof(params[3].c_str());
00420             pPass->tcModTurb[2] = atof(params[4].c_str());
00421             pPass->tcModTurb[3] = atof(params[5].c_str());
00422         }
00423         // DEPTHFUNC
00424         else if (params[0] == "depthfunc")
00425         {
00426             // TODO
00427         }
00428         // DEPTHWRITE
00429         else if (params[0] == "depthwrite")
00430         {
00431             // TODO
00432         }
00433         // ALPHAFUNC
00434         else if (params[0] == "alphafunc")
00435         {
00436             if (params[1] == "gt0")
00437             {
00438                 pPass->alphaVal = 0;
00439                 pPass->alphaFunc = CMPF_GREATER;
00440             }
00441             else if (params[1] == "ge128")
00442             {
00443                 pPass->alphaVal = 128;
00444                 pPass->alphaFunc = CMPF_GREATER_EQUAL;
00445             }
00446             else if (params[1] == "lt128")
00447             {
00448                 pPass->alphaVal = 128;
00449                 pPass->alphaFunc = CMPF_LESS;
00450             }
00451         }
00452 
00453 
00454 
00455     }
00456     //-----------------------------------------------------------------------
00457     SceneBlendFactor Quake3ShaderManager::convertBlendFunc( const String& q3func)
00458     {
00459         if (q3func == "gl_one")
00460         {
00461             return SBF_ONE;
00462         }
00463         else if (q3func == "gl_zero")
00464         {
00465             return SBF_ZERO;
00466         }
00467         else if (q3func == "gl_dst_color")
00468         {
00469             return SBF_DEST_COLOUR;
00470         }
00471         else if (q3func == "gl_src_color")
00472         {
00473             return SBF_SOURCE_COLOUR;
00474         }
00475         else if (q3func == "gl_one_minus_dest_color")
00476         {
00477             return SBF_ONE_MINUS_DEST_COLOUR;
00478         }
00479         else if (q3func == "gl_src_alpha")
00480         {
00481             return SBF_SOURCE_ALPHA;
00482         }
00483         else if (q3func == "gl_one_minus_src_alpha")
00484         {
00485             return SBF_ONE_MINUS_SOURCE_ALPHA;
00486         }
00487 
00488         // Default if unrecognised
00489         return SBF_ONE;
00490 
00491     }
00492 
00493 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:40 2004