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