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