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

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:36 2004