source: OGRE/trunk/ogrenew/PlugIns/BSPSceneManager/src/OgreQuake3ShaderManager.cpp @ 692

Revision 692, 17.5 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

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