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