Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreRenderSystem.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 22.1 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 "OgreStableHeaders.h"
30// RenderSystem implementation
31// Note that most of this class is abstract since
32//  we cannot know how to implement the behaviour without
33//  being aware of the 3D API. However there are a few
34//  simple functions which can have a base implementation
35
36#include "OgreRenderSystem.h"
37
38#include "OgreRoot.h"
39#include "OgreViewport.h"
40#include "OgreException.h"
41#include "OgreRenderTarget.h"
42#include "OgreRenderWindow.h"
43#include "OgreMeshManager.h"
44#include "OgreMaterial.h"
45#include "OgreTimer.h"
46#include "OgreHardwarePixelBuffer.h"
47#include "OgreHardwareOcclusionQuery.h"
48
49namespace Ogre {
50
51    const PlaneList Renderable::msDummyPlaneList; // FIX ME: temporary
52    static const TexturePtr sNullTexPtr;
53
54    //-----------------------------------------------------------------------
55    RenderSystem::RenderSystem()
56        : mActiveRenderTarget(0)
57        , mTextureManager(0)
58        , mCapabilities(0)
59        , mActiveViewport(0)
60        // This means CULL clockwise vertices, i.e. front of poly is counter-clockwise
61        // This makes it the same as OpenGL and other right-handed systems
62        , mCullingMode(CULL_CLOCKWISE)
63        , mVSync(true)
64                , mWBuffer(false)
65        , mInvertVertexWinding(false)
66        , mDisabledTexUnitsFrom(0)
67        , mCurrentPassIterationCount(0)
68        , mVertexProgramBound(false)
69        , mFragmentProgramBound(false)
70    {
71        // instanciate RenderSystemCapabilities
72        mCapabilities = new RenderSystemCapabilities();
73    }
74
75    //-----------------------------------------------------------------------
76    RenderSystem::~RenderSystem()
77    {
78        shutdown();
79                delete mCapabilities;
80                mCapabilities = 0;
81    }
82    //-----------------------------------------------------------------------
83    void RenderSystem::_initRenderTargets(void)
84    {
85
86        // Init stats
87        for(
88            RenderTargetMap::iterator it = mRenderTargets.begin();
89            it != mRenderTargets.end();
90            ++it )
91        {
92            it->second->resetStatistics();
93        }
94
95    }
96    //-----------------------------------------------------------------------
97    void RenderSystem::_updateAllRenderTargets(void)
98    {
99        // Update all in order of priority
100        // This ensures render-to-texture targets get updated before render windows
101                RenderTargetPriorityMap::iterator itarg, itargend;
102                itargend = mPrioritisedRenderTargets.end();
103                for( itarg = mPrioritisedRenderTargets.begin(); itarg != itargend; ++itarg )
104                {
105                        if( itarg->second->isActive() && itarg->second->isAutoUpdated())
106                                itarg->second->update();
107                }
108    }
109    //-----------------------------------------------------------------------
110    RenderWindow* RenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
111    {
112        // Have I been registered by call to Root::setRenderSystem?
113                /** Don't do this anymore, just allow via Root
114        RenderSystem* regPtr = Root::getSingleton().getRenderSystem();
115        if (!regPtr || regPtr != this)
116            // Register self - library user has come to me direct
117            Root::getSingleton().setRenderSystem(this);
118                */
119
120
121        // Subclasses should take it from here
122        // They should ALL call this superclass method from
123        //   their own initialise() implementations.
124       
125        mVertexProgramBound = false;
126        mFragmentProgramBound = false;
127
128        return 0;
129    }
130        //---------------------------------------------------------------------
131        RenderTexture * RenderSystem::createRenderTexture( const String & name, 
132                unsigned int width, unsigned int height,
133                TextureType texType, PixelFormat internalFormat, const NameValuePairList *miscParams )
134        {
135                /// Create a new 2D texture, and return surface to render to
136        TexturePtr mTexture = TextureManager::getSingleton().createManual( name, 
137                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, texType, 
138                        width, height, 0, internalFormat, TU_RENDERTARGET );
139           
140        // Ensure texture loaded and internal resources created
141        mTexture->load();
142
143        return mTexture->getBuffer()->getRenderTarget();
144        }
145    //---------------------------------------------------------------------------------------------
146    void RenderSystem::destroyRenderWindow(const String& name)
147    {
148        destroyRenderTarget(name);
149    }
150    //---------------------------------------------------------------------------------------------
151    void RenderSystem::destroyRenderTexture(const String& name)
152    {
153        destroyRenderTarget(name);
154    }
155    //---------------------------------------------------------------------------------------------
156    void RenderSystem::destroyRenderTarget(const String& name)
157    {
158        RenderTarget* rt = detachRenderTarget(name);
159        delete rt;
160    }
161    //---------------------------------------------------------------------------------------------
162    void RenderSystem::attachRenderTarget( RenderTarget &target )
163    {
164                assert( target.getPriority() < OGRE_NUM_RENDERTARGET_GROUPS );
165
166        mRenderTargets.insert( RenderTargetMap::value_type( target.getName(), &target ) );
167        mPrioritisedRenderTargets.insert(
168            RenderTargetPriorityMap::value_type(target.getPriority(), &target ));
169    }
170
171    //---------------------------------------------------------------------------------------------
172    RenderTarget * RenderSystem::getRenderTarget( const String &name )
173    {
174        RenderTargetMap::iterator it = mRenderTargets.find( name );
175        RenderTarget *ret = NULL;
176
177        if( it != mRenderTargets.end() )
178        {
179            ret = it->second;
180        }
181
182        return ret;
183    }
184
185    //---------------------------------------------------------------------------------------------
186    RenderTarget * RenderSystem::detachRenderTarget( const String &name )
187    {
188        RenderTargetMap::iterator it = mRenderTargets.find( name );
189        RenderTarget *ret = NULL;
190
191        if( it != mRenderTargets.end() )
192        {
193            ret = it->second;
194                       
195                        /* Remove the render target from the priority groups. */
196            RenderTargetPriorityMap::iterator itarg, itargend;
197            itargend = mPrioritisedRenderTargets.end();
198                        for( itarg = mPrioritisedRenderTargets.begin(); itarg != itargend; ++itarg )
199            {
200                                if( itarg->second == ret ) {
201                                        mPrioritisedRenderTargets.erase( itarg );
202                                        break;
203                                }
204            }
205
206            mRenderTargets.erase( it );
207        }
208        /// If detached render target is the active render target, reset active render target
209        if(ret == mActiveRenderTarget)
210            mActiveRenderTarget = 0;
211
212        return ret;
213    }
214    //-----------------------------------------------------------------------
215    Viewport* RenderSystem::_getViewport(void)
216    {
217        return mActiveViewport;
218    }
219    //-----------------------------------------------------------------------
220    void RenderSystem::_setTextureUnitSettings(size_t texUnit, TextureUnitState& tl)
221    {
222        // This method is only ever called to set a texture unit to valid details
223        // The method _disableTextureUnit is called to turn a unit off
224
225        const TexturePtr& tex = tl._getTexturePtr();
226                // Vertex texture binding?
227                if (mCapabilities->hasCapability(RSC_VERTEX_TEXTURE_FETCH) && 
228                        !mCapabilities->getVertexTextureUnitsShared())
229                {
230                        if (tl.getBindingType() == TextureUnitState::BT_VERTEX)
231                        {
232                                // Bind vertex texture
233                                _setVertexTexture(texUnit, tex);
234                                // bind nothing to fragment unit (hardware isn't shared but fragment
235                                // unit can't be using the same index
236                                _setTexture(texUnit, true, sNullTexPtr);
237                        }
238                        else
239                        {
240                                // vice versa
241                                _setVertexTexture(texUnit, sNullTexPtr);
242                                _setTexture(texUnit, true, tex);
243                        }
244                }
245                else
246                {
247                        // Shared vertex / fragment textures or no vertex texture support
248                        // Bind texture (may be blank)
249                        _setTexture(texUnit, true, tex);
250                }
251
252        // Set texture coordinate set
253        _setTextureCoordSet(texUnit, tl.getTextureCoordSet());
254
255        // Set texture layer filtering
256        _setTextureUnitFiltering(texUnit, 
257            tl.getTextureFiltering(FT_MIN), 
258            tl.getTextureFiltering(FT_MAG), 
259            tl.getTextureFiltering(FT_MIP));
260
261        // Set texture layer filtering
262        _setTextureLayerAnisotropy(texUnit, tl.getTextureAnisotropy());
263
264                // Set mipmap biasing
265                _setTextureMipmapBias(texUnit, tl.getTextureMipmapBias());
266
267                // Set blend modes
268                // Note, colour before alpha is important
269        _setTextureBlendMode(texUnit, tl.getColourBlendMode());
270        _setTextureBlendMode(texUnit, tl.getAlphaBlendMode());
271
272        // Texture addressing mode
273        const TextureUnitState::UVWAddressingMode& uvw = tl.getTextureAddressingMode();
274        _setTextureAddressingMode(texUnit, uvw);
275        // Set texture border colour only if required
276        if (uvw.u == TextureUnitState::TAM_BORDER ||
277            uvw.v == TextureUnitState::TAM_BORDER ||
278            uvw.w == TextureUnitState::TAM_BORDER)
279        {
280            _setTextureBorderColour(texUnit, tl.getTextureBorderColour());
281        }
282
283        // Set texture effects
284        TextureUnitState::EffectMap::iterator effi;
285        // Iterate over new effects
286        bool anyCalcs = false;
287        for (effi = tl.mEffects.begin(); effi != tl.mEffects.end(); ++effi)
288        {
289            switch (effi->second.type)
290            {
291            case TextureUnitState::ET_ENVIRONMENT_MAP:
292                if (effi->second.subtype == TextureUnitState::ENV_CURVED)
293                {
294                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP);
295                    anyCalcs = true;
296                }
297                else if (effi->second.subtype == TextureUnitState::ENV_PLANAR)
298                {
299                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP_PLANAR);
300                    anyCalcs = true;
301                }
302                else if (effi->second.subtype == TextureUnitState::ENV_REFLECTION)
303                {
304                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP_REFLECTION);
305                    anyCalcs = true;
306                }
307                else if (effi->second.subtype == TextureUnitState::ENV_NORMAL)
308                {
309                    _setTextureCoordCalculation(texUnit, TEXCALC_ENVIRONMENT_MAP_NORMAL);
310                    anyCalcs = true;
311                }
312                break;
313            case TextureUnitState::ET_UVSCROLL:
314                        case TextureUnitState::ET_USCROLL:
315                        case TextureUnitState::ET_VSCROLL:
316            case TextureUnitState::ET_ROTATE:
317            case TextureUnitState::ET_TRANSFORM:
318                break;
319            case TextureUnitState::ET_PROJECTIVE_TEXTURE:
320                _setTextureCoordCalculation(texUnit, TEXCALC_PROJECTIVE_TEXTURE, 
321                    effi->second.frustum);
322                anyCalcs = true;
323                break;
324            }
325        }
326        // Ensure any previous texcoord calc settings are reset if there are now none
327        if (!anyCalcs)
328        {
329            _setTextureCoordCalculation(texUnit, TEXCALC_NONE);
330        }
331
332        // Change tetxure matrix
333        _setTextureMatrix(texUnit, tl.getTextureTransform());
334
335
336    }
337    //-----------------------------------------------------------------------
338        void RenderSystem::_setTexture(size_t unit, bool enabled, 
339                const String &texname)
340        {
341                TexturePtr t = TextureManager::getSingleton().getByName(texname);
342                _setTexture(unit, enabled, t);
343        }
344        //-----------------------------------------------------------------------
345        void RenderSystem::_setVertexTexture(size_t unit, const TexturePtr& tex)
346        {
347                OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, 
348                        "This rendersystem does not support separate vertex texture samplers, "
349                        "you should use the regular texture samplers which are shared between "
350                        "the vertex and fragment units.", 
351                        "RenderSystem::_setVertexTexture");
352        }
353    //-----------------------------------------------------------------------
354    void RenderSystem::_disableTextureUnit(size_t texUnit)
355    {
356        _setTexture(texUnit, false, sNullTexPtr);
357    }
358    //---------------------------------------------------------------------
359    void RenderSystem::_disableTextureUnitsFrom(size_t texUnit)
360    {
361        size_t disableTo = mCapabilities->getNumTextureUnits();
362        if (disableTo > mDisabledTexUnitsFrom)
363            disableTo = mDisabledTexUnitsFrom;
364        mDisabledTexUnitsFrom = texUnit;
365        for (size_t i = texUnit; i < disableTo; ++i)
366        {
367            _disableTextureUnit(i);
368        }
369    }
370    //-----------------------------------------------------------------------
371    void RenderSystem::_setTextureUnitFiltering(size_t unit, FilterOptions minFilter,
372            FilterOptions magFilter, FilterOptions mipFilter)
373    {
374        _setTextureUnitFiltering(unit, FT_MIN, minFilter);
375        _setTextureUnitFiltering(unit, FT_MAG, magFilter);
376        _setTextureUnitFiltering(unit, FT_MIP, mipFilter);
377    }
378    //-----------------------------------------------------------------------
379    CullingMode RenderSystem::_getCullingMode(void) const
380    {
381        return mCullingMode;
382    }
383    //-----------------------------------------------------------------------
384    bool RenderSystem::getWaitForVerticalBlank(void) const
385    {
386        return mVSync;
387    }
388    //-----------------------------------------------------------------------
389    void RenderSystem::setWaitForVerticalBlank(bool enabled)
390    {
391        mVSync = enabled;
392    }
393    bool RenderSystem::getWBufferEnabled(void) const
394    {
395        return mWBuffer;
396    }
397    //-----------------------------------------------------------------------
398    void RenderSystem::setWBufferEnabled(bool enabled)
399    {
400        mWBuffer = enabled;
401    }
402    //-----------------------------------------------------------------------
403    void RenderSystem::shutdown(void)
404    {
405                // Remove occlusion queries
406                for (HardwareOcclusionQueryList::iterator i = mHwOcclusionQueries.begin();
407                        i != mHwOcclusionQueries.end(); ++i)
408                {
409                        delete *i;
410                }
411                mHwOcclusionQueries.clear();
412
413        // Remove all the render targets.
414                // (destroy primary target last since others may depend on it)
415                RenderTarget* primary = 0;
416                for (RenderTargetMap::iterator it = mRenderTargets.begin(); it != mRenderTargets.end(); ++it)
417                {
418                        if (!primary && it->second->isPrimary())
419                                primary = it->second;
420                        else
421                                delete it->second;
422                }
423                delete primary;
424                mRenderTargets.clear();
425
426                mPrioritisedRenderTargets.clear();
427    }
428    //-----------------------------------------------------------------------
429    void RenderSystem::_beginGeometryCount(void)
430    {
431        mBatchCount = mFaceCount = mVertexCount = 0;
432
433    }
434    //-----------------------------------------------------------------------
435    unsigned int RenderSystem::_getFaceCount(void) const
436    {
437        return static_cast< unsigned int >( mFaceCount );
438    }
439    //-----------------------------------------------------------------------
440    unsigned int RenderSystem::_getBatchCount(void) const
441    {
442        return static_cast< unsigned int >( mBatchCount );
443    }
444    //-----------------------------------------------------------------------
445    unsigned int RenderSystem::_getVertexCount(void) const
446    {
447        return static_cast< unsigned int >( mVertexCount );
448    }
449    //-----------------------------------------------------------------------
450        void RenderSystem::convertColourValue(const ColourValue& colour, uint32* pDest)
451        {
452                *pDest = VertexElement::convertColourValue(colour, getColourVertexElementType());
453
454        }
455    //-----------------------------------------------------------------------
456    void RenderSystem::_setWorldMatrices(const Matrix4* m, unsigned short count)
457    {
458        // Do nothing with these matrices here, it never used for now,
459                // derived class should take care with them if required.
460
461        // Set hardware matrix to nothing
462        _setWorldMatrix(Matrix4::IDENTITY);
463    }
464    //-----------------------------------------------------------------------
465    void RenderSystem::_render(const RenderOperation& op)
466    {
467        // Update stats
468        size_t val;
469
470        if (op.useIndexes)
471            val = op.indexData->indexCount;
472        else
473            val = op.vertexData->vertexCount;
474
475        // account for a pass having multiple iterations
476        if (mCurrentPassIterationCount > 1)
477            val *= mCurrentPassIterationCount;
478
479        switch(op.operationType)
480        {
481                case RenderOperation::OT_TRIANGLE_LIST:
482            mFaceCount += val / 3;
483            break;
484        case RenderOperation::OT_TRIANGLE_STRIP:
485        case RenderOperation::OT_TRIANGLE_FAN:
486            mFaceCount += val - 2;
487            break;
488            case RenderOperation::OT_POINT_LIST:
489            case RenderOperation::OT_LINE_LIST:
490            case RenderOperation::OT_LINE_STRIP:
491                break;
492            }
493
494        mVertexCount += op.vertexData->vertexCount;
495        mBatchCount += mCurrentPassIterationCount;
496    }
497    //-----------------------------------------------------------------------
498    void RenderSystem::setInvertVertexWinding(bool invert)
499    {
500        mInvertVertexWinding = invert;
501    }
502    //-----------------------------------------------------------------------
503    void RenderSystem::setClipPlane (ushort index, const Plane &p)
504    {
505        setClipPlane (index, p.normal.x, p.normal.y, p.normal.z, p.d);
506    }
507    //-----------------------------------------------------------------------
508    void RenderSystem::_notifyCameraRemoved(const Camera* cam)
509    {
510        RenderTargetMap::iterator i, iend;
511        iend = mRenderTargets.end();
512        for (i = mRenderTargets.begin(); i != iend; ++i)
513        {
514            RenderTarget* target = i->second;
515            target->_notifyCameraRemoved(cam);
516        }
517    }
518
519        //---------------------------------------------------------------------
520    bool RenderSystem::updatePassIterationRenderState(void)
521    {
522        if (mCurrentPassIterationCount <= 1)
523            return false;
524
525        --mCurrentPassIterationCount;
526        if (!mActiveVertexGpuProgramParameters.isNull())
527        {
528            mActiveVertexGpuProgramParameters->incPassIterationNumber();
529            bindGpuProgramPassIterationParameters(GPT_VERTEX_PROGRAM);
530        }
531        if (!mActiveFragmentGpuProgramParameters.isNull())
532        {
533            mActiveFragmentGpuProgramParameters->incPassIterationNumber();
534            bindGpuProgramPassIterationParameters(GPT_FRAGMENT_PROGRAM);
535        }
536        return true;
537    }
538
539        //-----------------------------------------------------------------------
540        void RenderSystem::addListener(Listener* l)
541        {
542                mEventListeners.push_back(l);
543        }
544        //-----------------------------------------------------------------------
545        void RenderSystem::removeListener(Listener* l)
546        {
547                mEventListeners.remove(l);
548        }
549        //-----------------------------------------------------------------------
550        void RenderSystem::fireEvent(const String& name, const NameValuePairList* params)
551        {
552                for(ListenerList::iterator i = mEventListeners.begin(); 
553                        i != mEventListeners.end(); ++i)
554                {
555                        (*i)->eventOccurred(name, params);
556                }
557        }
558        //-----------------------------------------------------------------------
559        void RenderSystem::destroyHardwareOcclusionQuery( HardwareOcclusionQuery *hq)
560        {
561                HardwareOcclusionQueryList::iterator i =
562                        std::find(mHwOcclusionQueries.begin(), mHwOcclusionQueries.end(), hq);
563                if (i != mHwOcclusionQueries.end())
564                {
565                        mHwOcclusionQueries.erase(i);
566                        delete hq;
567                }
568        }
569        //-----------------------------------------------------------------------
570        void RenderSystem::bindGpuProgram(GpuProgram* prg)
571        {
572            switch(prg->getType())
573            {
574        case GPT_VERTEX_PROGRAM:
575            mVertexProgramBound = true;
576                break;
577        case GPT_FRAGMENT_PROGRAM:
578            mFragmentProgramBound = true;
579                break;
580            }
581        }
582        //-----------------------------------------------------------------------
583        void RenderSystem::unbindGpuProgram(GpuProgramType gptype)
584        {
585            switch(gptype)
586            {
587        case GPT_VERTEX_PROGRAM:
588            mVertexProgramBound = false;
589                break;
590        case GPT_FRAGMENT_PROGRAM:
591            mFragmentProgramBound = false;
592                break;
593            }
594        }
595        //-----------------------------------------------------------------------
596        bool RenderSystem::isGpuProgramBound(GpuProgramType gptype)
597        {
598            switch(gptype)
599            {
600        case GPT_VERTEX_PROGRAM:
601            return mVertexProgramBound;
602        case GPT_FRAGMENT_PROGRAM:
603            return mFragmentProgramBound;
604            }
605        // Make compiler happy
606        return false;
607        }
608
609}
610
Note: See TracBrowser for help on using the repository browser.