Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/PlugIns/BSPSceneManager/src/OgreQuake3ShaderManager.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 17.2 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreQuake3ShaderManager.h"
30#include "OgreQuake3Shader.h"
31#include "OgreStringVector.h"
32#include "OgreException.h"
33
34namespace Ogre {
35
36    //-----------------------------------------------------------------------
37    template<> Quake3ShaderManager *Singleton<Quake3ShaderManager>::ms_Singleton = 0;
38    Quake3ShaderManager* Quake3ShaderManager::getSingletonPtr(void)
39    {
40        return ms_Singleton;
41    }
42    Quake3ShaderManager& Quake3ShaderManager::getSingleton(void)
43    { 
44        assert( ms_Singleton );  return ( *ms_Singleton ); 
45    }
46    //-----------------------------------------------------------------------
47
48    //-----------------------------------------------------------------------
49    Quake3ShaderManager::Quake3ShaderManager()
50    {
51        mScriptPatterns.push_back("*.shader");
52        ResourceGroupManager::getSingleton()._registerScriptLoader(this);
53    }
54    //-----------------------------------------------------------------------
55    Quake3ShaderManager::~Quake3ShaderManager()
56    {
57        // delete all shaders
58        clear();
59        ResourceGroupManager::getSingleton()._unregisterScriptLoader(this);
60    }
61    //-----------------------------------------------------------------------
62    const StringVector& Quake3ShaderManager::getScriptPatterns(void) const
63    {
64        return mScriptPatterns;
65    }
66    //-----------------------------------------------------------------------
67    Real Quake3ShaderManager::getLoadingOrder(void) const
68    {
69        return 110.0f;
70    }
71    //-----------------------------------------------------------------------
72    void Quake3ShaderManager::clear(void)
73    {
74        for (Quake3ShaderMap::iterator i = mShaderMap.begin();
75            i != mShaderMap.end(); ++i)
76        {
77            delete i->second;
78        }
79        mShaderMap.clear();
80    }
81    //-----------------------------------------------------------------------
82    Quake3Shader* Quake3ShaderManager::getByName(const String& name)
83    {
84        Quake3ShaderMap::iterator i = mShaderMap.find(name);
85        if (i == mShaderMap.end())
86        {
87            return 0;
88        }
89        return i->second;
90    }
91    //-----------------------------------------------------------------------
92    void Quake3ShaderManager::parseScript(DataStreamPtr& stream, const String& group)
93    {
94        String line;
95        Quake3Shader* pShader;
96        char tempBuf[512];
97
98        pShader = 0;
99        bool dummy = false;
100
101        while(!stream->eof())
102        {
103            line = stream->getLine();
104            // Ignore comments & blanks
105            if (!(line.length() == 0 || line.substr(0,2) == "//"))
106            {
107                if (pShader == 0)
108                {
109                    // No current shader
110                    if (getByName(line) == 0)
111                    {
112                        dummy = false;
113                    }
114                    else
115                    {
116                        // Defined before, parse but ignore
117                        // Q3A has duplicates in shaders, doh
118                        dummy = true;
119                    }
120
121                    // So first valid data should be a shader name
122                    pShader = create(line);
123                    // Skip to and over next {
124                    stream->readLine(tempBuf, 511, "{");
125                }
126                else
127                {
128                    // Already in a shader
129                    if (line == "}")
130                    {
131                        // Finished shader
132                        if (dummy && pShader)
133                        {
134                            delete pShader;
135                        }
136                        pShader = 0;
137                    }
138                    else if (line == "{")
139                    {
140                        // new pass
141                        parseNewShaderPass(stream, pShader);
142
143                    }
144                    else
145                    {
146                        // Attribute
147                                                StringUtil::toLowerCase(line);
148                        parseShaderAttrib(line, pShader);
149                    }
150
151                }
152
153            }
154
155
156        }
157
158    }
159    //-----------------------------------------------------------------------
160    Quake3Shader* Quake3ShaderManager::create( const String& name)
161    {
162        // Gah, Q3A shader scripts include some duplicates - grr
163        Quake3Shader* s = new Quake3Shader(name);
164        if (mShaderMap.find(name) == mShaderMap.end())
165        {
166            mShaderMap[name] = s;
167        }
168        else
169        {
170            // deliberately ignore, will get parsed again but will not be used
171        }
172        return s;
173    }
174    //-----------------------------------------------------------------------
175    void Quake3ShaderManager::parseNewShaderPass(DataStreamPtr& stream, Quake3Shader* pShader)
176    {
177        String line;
178        int passIdx;
179
180        passIdx = pShader->numPasses;
181        pShader->numPasses++;
182        pShader->pass.resize(pShader->numPasses);
183
184        // Default pass details
185        pShader->pass[passIdx].animNumFrames = 0;
186        pShader->pass[passIdx].blend = LBO_REPLACE;
187        pShader->pass[passIdx].blendDest = SBF_ZERO;
188        pShader->pass[passIdx].blendSrc = SBF_ONE;
189        pShader->pass[passIdx].depthFunc = CMPF_LESS_EQUAL;
190        pShader->pass[passIdx].flags = 0;
191        pShader->pass[passIdx].rgbGenFunc = SHADER_GEN_IDENTITY;
192        pShader->pass[passIdx].tcModRotate = 0;
193        pShader->pass[passIdx].tcModScale[0] = pShader->pass[passIdx].tcModScale[1] = 1.0;
194        pShader->pass[passIdx].tcModScroll[0] = pShader->pass[passIdx].tcModScroll[1] = 0;
195        pShader->pass[passIdx].tcModStretchWave = SHADER_FUNC_NONE;
196        pShader->pass[passIdx].tcModTransform[0] = pShader->pass[passIdx].tcModTransform[1] = 0;
197        pShader->pass[passIdx].tcModTurbOn = false;
198        pShader->pass[passIdx].tcModTurb[0] = pShader->pass[passIdx].tcModTurb[1] =
199            pShader->pass[passIdx].tcModTurb[2] = pShader->pass[passIdx].tcModTurb[3] = 0;
200        pShader->pass[passIdx].texGen = TEXGEN_BASE;
201        pShader->pass[passIdx].addressMode = TextureUnitState::TAM_WRAP;
202        pShader->pass[passIdx].customBlend = false;
203        pShader->pass[passIdx].alphaVal = 0;
204        pShader->pass[passIdx].alphaFunc = CMPF_ALWAYS_PASS;
205
206        while (!stream->eof())
207        {
208            line = stream->getLine();
209            // Ignore comments & blanks
210            if (line.length() != 0 && line.substr(0,2) != "//")
211            {
212                if (line == "}")
213                {
214                    // end of shader
215                    return;
216                }
217                else
218                {
219                    parseShaderPassAttrib(line, pShader, &pShader->pass[passIdx]);
220                }
221            }
222
223
224        }
225    }
226    //-----------------------------------------------------------------------
227    void Quake3ShaderManager::parseShaderAttrib( const String& line, Quake3Shader* pShader)
228    {
229        StringVector vecparams;
230
231        vecparams = StringUtil::split(line, " \t");
232        StringVector::iterator params = vecparams.begin();
233
234        if (params[0] == "skyparms")
235        {
236            if (params[1] != "-")
237            {
238                pShader->farbox = true;
239                pShader->farboxName = params[1];
240            }
241            if (params[2] != "-")
242            {
243                pShader->skyDome = true;
244                pShader->cloudHeight = atof(params[2].c_str());
245            }
246            // nearbox not supported
247        }
248        else if (params[0] == "cull")
249        {
250            if (params[1] == "disable" || params[1] == "none")
251            {
252                pShader->cullMode = MANUAL_CULL_NONE;
253            }
254            else if (params[1] == "front")
255            {
256                pShader->cullMode = MANUAL_CULL_FRONT;
257            }
258            else if (params[1] == "back")
259            {
260                pShader->cullMode = MANUAL_CULL_BACK;
261            }
262        }
263        else if (params[0] == "deformvertexes")
264        {
265            // TODO
266        }
267        else if (params[0] == "fogparms")
268        {
269            Real r,g,b;
270            r = atof(params[1].c_str());
271            g = atof(params[2].c_str());
272            b = atof(params[3].c_str());
273            pShader->fog = true;
274            pShader->fogColour = ColourValue(r,g,b);
275            pShader->fogDistance = atof(params[4].c_str());
276
277        }
278    }
279    //-----------------------------------------------------------------------
280    void Quake3ShaderManager::parseShaderPassAttrib( const String& line, Quake3Shader* pShader, Quake3Shader::Pass* pPass)
281    {
282        StringVector vecparams;
283
284        vecparams = StringUtil::split(line, " \t");
285        StringVector::iterator params = vecparams.begin();
286
287        StringUtil::toLowerCase(params[0]);
288        if (params[0] != "map" && params[0] != "clampmap" && params[0] != "animmap")
289        {
290            // lower case all except textures
291            for (size_t i = 1; i < vecparams.size(); ++i)
292                StringUtil::toLowerCase(params[i]);
293        }
294
295
296        // MAP
297        if (params[0] == "map")
298        {
299            pPass->textureName = params[1];
300                        StringUtil::toLowerCase(params[1]);
301            if (params[1] == "$lightmap")
302                pPass->texGen = TEXGEN_LIGHTMAP;
303        }
304        // CLAMPMAP
305        if (params[0] == "clampmap")
306        {
307            pPass->textureName = params[1];
308                        StringUtil::toLowerCase(params[1]);
309            if (params[1] == "$lightmap")
310                pPass->texGen = TEXGEN_LIGHTMAP;
311            pPass->addressMode = TextureUnitState::TAM_CLAMP;
312        }
313        // ANIMMAP
314        else if (params[0] == "animmap")
315        {
316            pPass->animFps = atof(params[1].c_str());
317            pPass->animNumFrames = static_cast<unsigned int>( vecparams.size() - 2 );
318            for (unsigned int frame = 0; frame < pPass->animNumFrames; ++frame)
319            {
320                pPass->frames[frame] = params[frame+2];
321            }
322        }
323        // BLENDFUNC
324        else if (params[0] == "blendfunc")
325        {
326            if (params[1] == "add" || params[1] == "gl_add")
327            {
328                pPass->blend = LBO_ADD;
329                pPass->blendDest = SBF_ONE;
330                pPass->blendSrc = SBF_ONE;
331            }
332            else if (params[1] == "filter" || params[1] == "gl_filter")
333            {
334                pPass->blend = LBO_MODULATE;
335                pPass->blendDest = SBF_ZERO;
336                pPass->blendSrc = SBF_DEST_COLOUR;
337            }
338            else if (params[1] == "blend" || params[1] == "gl_blend")
339            {
340                pPass->blend = LBO_ALPHA_BLEND;
341                pPass->blendDest = SBF_ONE_MINUS_SOURCE_ALPHA;
342                pPass->blendSrc = SBF_SOURCE_ALPHA;
343            }
344            else
345            {
346                // Manual blend
347                pPass->blendSrc = convertBlendFunc(params[1]);
348                pPass->blendDest = convertBlendFunc(params[2]);
349                // Detect common blends
350                if (pPass->blendSrc == SBF_ONE && pPass->blendDest == SBF_ZERO)
351                    pPass->blend = LBO_REPLACE;
352                else if (pPass->blendSrc == SBF_ONE && pPass->blendDest == SBF_ONE)
353                    pPass->blend = LBO_ADD;
354                else if ((pPass->blendSrc == SBF_ZERO && pPass->blendDest == SBF_SOURCE_COLOUR) ||
355                    (pPass->blendSrc == SBF_DEST_COLOUR && pPass->blendDest == SBF_ZERO))
356                    pPass->blend = LBO_MODULATE;
357                else if (pPass->blendSrc == SBF_SOURCE_ALPHA && pPass->blendDest == SBF_ONE_MINUS_SOURCE_ALPHA)
358                    pPass->blend = LBO_ALPHA_BLEND;
359                else
360                    pPass->customBlend = true;
361
362
363                // NB other custom blends might not work due to OGRE trying to use multitexture over multipass
364            }
365        }
366        // RGBGEN
367        else if (params[0] == "rgbgen")
368        {
369            // TODO
370        }
371        // ALPHAGEN
372        else if (params[0] == "alphagen")
373        {
374            // TODO
375        }
376        // TCGEN
377        else if (params[0] == "tcgen")
378        {
379            if (params[1] == "base")
380            {
381                pPass->texGen = TEXGEN_BASE;
382            }
383            else if (params[1] == "lightmap")
384            {
385                pPass->texGen = TEXGEN_LIGHTMAP;
386            }
387            else if (params[1] == "environment")
388            {
389                pPass->texGen = TEXGEN_ENVIRONMENT;
390            }
391        }
392        // TCMOD
393        else if (params[0] == "tcmod")
394        {
395            if (params[1] == "rotate")
396            {
397                pPass->tcModRotate = -atof(params[2].c_str()) / 360; // +ve is clockwise degrees in Q3 shader, anticlockwise complete rotations in Ogre
398            }
399            else if (params[1] == "scroll")
400            {
401                pPass->tcModScroll[0] = atof(params[2].c_str());
402                pPass->tcModScroll[1] = atof(params[3].c_str());
403            }
404            else if (params[1] == "scale")
405            {
406                pPass->tcModScale[0] = atof(params[2].c_str());
407                pPass->tcModScale[1] = atof(params[3].c_str());
408            }
409            else if (params[1] == "stretch")
410            {
411                if (params[2] == "sin")
412                    pPass->tcModStretchWave = SHADER_FUNC_SIN;
413                else if (params[2] == "triangle")
414                    pPass->tcModStretchWave = SHADER_FUNC_TRIANGLE;
415                else if (params[2] == "square")
416                    pPass->tcModStretchWave = SHADER_FUNC_SQUARE;
417                else if (params[2] == "sawtooth")
418                    pPass->tcModStretchWave = SHADER_FUNC_SAWTOOTH;
419                else if (params[2] == "inversesawtooth")
420                    pPass->tcModStretchWave = SHADER_FUNC_INVERSESAWTOOTH;
421
422                pPass->tcModStretchParams[0] = atof(params[3].c_str());
423                pPass->tcModStretchParams[1] = atof(params[4].c_str());
424                pPass->tcModStretchParams[2] = atof(params[5].c_str());
425                pPass->tcModStretchParams[3] = atof(params[6].c_str());
426
427            }
428        }
429        // TURB
430        else if (params[0] == "turb")
431        {
432            pPass->tcModTurbOn = true;
433            pPass->tcModTurb[0] = atof(params[2].c_str());
434            pPass->tcModTurb[1] = atof(params[3].c_str());
435            pPass->tcModTurb[2] = atof(params[4].c_str());
436            pPass->tcModTurb[3] = atof(params[5].c_str());
437        }
438        // DEPTHFUNC
439        else if (params[0] == "depthfunc")
440        {
441            // TODO
442        }
443        // DEPTHWRITE
444        else if (params[0] == "depthwrite")
445        {
446            // TODO
447        }
448        // ALPHAFUNC
449        else if (params[0] == "alphafunc")
450        {
451            if (params[1] == "gt0")
452            {
453                pPass->alphaVal = 0;
454                pPass->alphaFunc = CMPF_GREATER;
455            }
456            else if (params[1] == "ge128")
457            {
458                pPass->alphaVal = 128;
459                pPass->alphaFunc = CMPF_GREATER_EQUAL;
460            }
461            else if (params[1] == "lt128")
462            {
463                pPass->alphaVal = 128;
464                pPass->alphaFunc = CMPF_LESS;
465            }
466        }
467
468
469
470    }
471    //-----------------------------------------------------------------------
472    SceneBlendFactor Quake3ShaderManager::convertBlendFunc( const String& q3func)
473    {
474        if (q3func == "gl_one")
475        {
476            return SBF_ONE;
477        }
478        else if (q3func == "gl_zero")
479        {
480            return SBF_ZERO;
481        }
482        else if (q3func == "gl_dst_color")
483        {
484            return SBF_DEST_COLOUR;
485        }
486        else if (q3func == "gl_src_color")
487        {
488            return SBF_SOURCE_COLOUR;
489        }
490        else if (q3func == "gl_one_minus_dest_color")
491        {
492            return SBF_ONE_MINUS_DEST_COLOUR;
493        }
494        else if (q3func == "gl_src_alpha")
495        {
496            return SBF_SOURCE_ALPHA;
497        }
498        else if (q3func == "gl_one_minus_src_alpha")
499        {
500            return SBF_ONE_MINUS_SOURCE_ALPHA;
501        }
502
503        // Default if unrecognised
504        return SBF_ONE;
505
506    }
507
508}
Note: See TracBrowser for help on using the repository browser.