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