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

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:23 2004