Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/Samples/Shadows/src/Shadows.cpp @ 5

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

=hoffentlich gehts jetzt

File size: 50.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
10You may use this sample code for anything you like, it is not covered by the
11LGPL like the rest of the engine.
12-----------------------------------------------------------------------------
13*/
14
15/**
16    \file
17        Shadows.cpp
18    \brief
19        Shows a few ways to use Ogre's shadowing techniques
20*/
21
22#include <CEGUI/CEGUIImageset.h>
23#include <CEGUI/CEGUISystem.h>
24#include <CEGUI/CEGUILogger.h>
25#include <CEGUI/CEGUISchemeManager.h>
26#include <CEGUI/CEGUIWindowManager.h>
27#include <CEGUI/CEGUIWindow.h>
28#include <CEGUI/elements/CEGUICombobox.h>
29#include <CEGUI/elements/CEGUIComboDropList.h>
30#include <CEGUI/elements/CEGUIEditbox.h>
31#include <CEGUI/elements/CEGUIListbox.h>
32#include <CEGUI/elements/CEGUIListboxTextItem.h>
33#include <CEGUI/elements/CEGUIPushButton.h>
34#include <CEGUI/elements/CEGUIScrollbar.h>
35#include <CEGUI/elements/CEGUIRadioButton.h>
36#include "OgreCEGUIRenderer.h"
37#include "OgreCEGUIResourceProvider.h"
38#include "ExampleApplication.h"
39
40/*
41#include "OgreNoMemoryMacros.h"
42#include <ode/odecpp.h>
43#include <ode/odecpp_collision.h>
44#include "OgreMemoryMacros.h"
45*/
46
47/*
48#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
49#include "OgreNoMemoryMacros.h"
50#include <crtdbg.h>
51#endi*/
52
53Entity* mAthene;
54AnimationState* mAnimState = 0;
55Entity* pPlaneEnt;
56std::vector<Entity*> pColumns;
57Light* mLight;
58Light* mSunLight;
59SceneNode* mLightNode = 0;
60AnimationState* mLightAnimationState = 0;
61ColourValue mMinLightColour(0.2, 0.1, 0.0);
62ColourValue mMaxLightColour(0.5, 0.3, 0.1);
63Real mMinFlareSize = 40;
64Real mMaxFlareSize = 80;
65
66// New depth shadowmapping
67String CUSTOM_ROCKWALL_MATERIAL("Ogre/DepthShadowmap/Receiver/RockWall");
68String CUSTOM_CASTER_MATERIAL("Ogre/DepthShadowmap/Caster/Float");
69String CUSTOM_RECEIVER_MATERIAL("Ogre/DepthShadowmap/Receiver/Float");
70String CUSTOM_ATHENE_MATERIAL("Ogre/DepthShadowmap/Receiver/Athene");
71
72String BASIC_ROCKWALL_MATERIAL("Examples/Rockwall");
73String BASIC_ATHENE_MATERIAL("Examples/Athene/NormalMapped");
74
75
76
77OverlayElement* mShadowTechniqueInfo;
78OverlayElement* mMaterialInfo;
79OverlayElement* mInfo;
80
81
82/** This class 'wibbles' the light and billboard */
83class LightWibbler : public ControllerValue<Real>
84{
85protected:
86    Light* mLight;
87    Billboard* mBillboard;
88    ColourValue mColourRange;
89    ColourValue mMinColour;
90    Real mMinSize;
91    Real mSizeRange;
92    Real intensity;
93public:
94    LightWibbler(Light* light, Billboard* billboard, const ColourValue& minColour, 
95        const ColourValue& maxColour, Real minSize, Real maxSize)
96    {
97        mLight = light;
98        mBillboard = billboard;
99        mMinColour = minColour;
100        mColourRange.r = maxColour.r - minColour.r;
101        mColourRange.g = maxColour.g - minColour.g;
102        mColourRange.b = maxColour.b - minColour.b;
103        mMinSize = minSize;
104        mSizeRange = maxSize - minSize;
105    }
106
107    virtual Real  getValue (void) const
108    {
109        return intensity;
110    }
111
112    virtual void  setValue (Real value)
113    {
114        intensity = value;
115
116        ColourValue newColour;
117
118        // Attenuate the brightness of the light
119        newColour.r = mMinColour.r + (mColourRange.r * intensity);
120        newColour.g = mMinColour.g + (mColourRange.g * intensity);
121        newColour.b = mMinColour.b + (mColourRange.b * intensity);
122
123        mLight->setDiffuseColour(newColour);
124        mBillboard->setColour(newColour);
125        // set billboard size
126        Real newSize = mMinSize + (intensity * mSizeRange);
127        mBillboard->setDimensions(newSize, newSize);
128
129    }
130};
131
132Real timeDelay = 0;
133#define KEY_PRESSED(_key,_timeDelay, _macro) \
134{ \
135    if (mKeyboard->isKeyDown(_key) && timeDelay <= 0) \
136{ \
137    timeDelay = _timeDelay; \
138    _macro ; \
139} \
140}
141
142
143//---------------------------------------------------------------------------
144class GaussianListener: public Ogre::CompositorInstance::Listener
145{
146protected:
147        int mVpWidth, mVpHeight;
148        // Array params - have to pack in groups of 4 since this is how Cg generates them
149        // also prevents dependent texture read problems if ops don't require swizzle
150        float mBloomTexWeights[15][4];
151        float mBloomTexOffsetsHorz[15][4];
152        float mBloomTexOffsetsVert[15][4];
153public:
154        GaussianListener() {}
155        virtual ~GaussianListener() {}
156        void notifyViewportSize(int width, int height)
157        {
158                mVpWidth = width;
159                mVpHeight = height;
160                // Calculate gaussian texture offsets & weights
161                float deviation = 3.0f;
162                float texelSize = 1.0f / (float)std::min(mVpWidth, mVpHeight);
163
164                // central sample, no offset
165                mBloomTexOffsetsHorz[0][0] = 0.0f;
166                mBloomTexOffsetsHorz[0][1] = 0.0f;
167                mBloomTexOffsetsVert[0][0] = 0.0f;
168                mBloomTexOffsetsVert[0][1] = 0.0f;
169                mBloomTexWeights[0][0] = mBloomTexWeights[0][1] = 
170                        mBloomTexWeights[0][2] = Ogre::Math::gaussianDistribution(0, 0, deviation);
171                mBloomTexWeights[0][3] = 1.0f;
172
173                // 'pre' samples
174                for(int i = 1; i < 8; ++i)
175                {
176                        mBloomTexWeights[i][0] = mBloomTexWeights[i][1] = 
177                                mBloomTexWeights[i][2] = Ogre::Math::gaussianDistribution(i, 0, deviation);
178                        mBloomTexWeights[i][3] = 1.0f;
179                        mBloomTexOffsetsHorz[i][0] = i * texelSize;
180                        mBloomTexOffsetsHorz[i][1] = 0.0f;
181                        mBloomTexOffsetsVert[i][0] = 0.0f;
182                        mBloomTexOffsetsVert[i][1] = i * texelSize;
183                }
184                // 'post' samples
185                for(int i = 8; i < 15; ++i)
186                {
187                        mBloomTexWeights[i][0] = mBloomTexWeights[i][1] = 
188                                mBloomTexWeights[i][2] = mBloomTexWeights[i - 7][0];
189                        mBloomTexWeights[i][3] = 1.0f;
190
191                        mBloomTexOffsetsHorz[i][0] = -mBloomTexOffsetsHorz[i - 7][0];
192                        mBloomTexOffsetsHorz[i][1] = 0.0f;
193                        mBloomTexOffsetsVert[i][0] = 0.0f;
194                        mBloomTexOffsetsVert[i][1] = -mBloomTexOffsetsVert[i - 7][1];
195                }
196
197        }
198        virtual void notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
199        {
200                // Prepare the fragment params offsets
201                switch(pass_id)
202                {
203                case 701: // blur horz
204                        {
205                                // horizontal bloom
206                                mat->load();
207                                Ogre::GpuProgramParametersSharedPtr fparams = 
208                                        mat->getBestTechnique()->getPass(0)->getFragmentProgramParameters();
209                                const Ogre::String& progName = mat->getBestTechnique()->getPass(0)->getFragmentProgramName();
210                                // A bit hacky - Cg & HLSL index arrays via [0], GLSL does not
211                                fparams->setNamedConstant("sampleOffsets", mBloomTexOffsetsHorz[0], 15);
212                                fparams->setNamedConstant("sampleWeights", mBloomTexWeights[0], 15);
213
214                                break;
215                        }
216                case 700: // blur vert
217                        {
218                                // vertical bloom
219                                mat->load();
220                                Ogre::GpuProgramParametersSharedPtr fparams = 
221                                        mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters();
222                                const Ogre::String& progName = mat->getBestTechnique()->getPass(0)->getFragmentProgramName();
223                                fparams->setNamedConstant("sampleOffsets", mBloomTexOffsetsVert[0], 15);
224                                fparams->setNamedConstant("sampleWeights", mBloomTexWeights[0], 15);
225
226                                break;
227                        }
228                }
229
230        }
231        virtual void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
232        {
233
234        }
235};
236GaussianListener gaussianListener;
237
238
239class ShadowsListener : public ExampleFrameListener, public OIS::MouseListener, 
240        public OIS::KeyListener
241{
242protected:
243    SceneManager* mSceneMgr;
244        Viewport *mShadowVp;
245        CompositorInstance* mShadowCompositor;
246        bool mShutdownRequested;
247        CEGUI::Window* mRootGuiPanel;
248        bool mLMBDown;
249        bool mRMBDown;
250        bool mProcessMovement;
251        bool mUpdateMovement;
252        bool mMoveFwd;
253        bool mMoveBck;
254        bool mMoveLeft;
255        bool mMoveRight;
256        CEGUI::Point mLastMousePosition;
257        bool mLastMousePositionSet;
258        float mAvgFrameTime;
259        Camera* mTexCam;
260
261
262        //----------------------------------------------------------------//
263        CEGUI::MouseButton convertOISMouseButtonToCegui(int buttonID)
264        {
265                switch (buttonID)
266                {
267                case 0: return CEGUI::LeftButton;
268                case 1: return CEGUI::RightButton;
269                case 2: return CEGUI::MiddleButton;
270                case 3: return CEGUI::X1Button;
271                default: return CEGUI::LeftButton;
272                }
273        }
274public:
275        ShadowsListener(RenderWindow* win, Camera* cam, SceneManager* sm)
276        : ExampleFrameListener(win, cam, true, true)
277                , mSceneMgr(sm)
278                , mShadowVp(0)
279                , mShadowCompositor(0)
280                , mShutdownRequested(false)
281                , mLMBDown(false)
282                , mRMBDown(false)
283                , mProcessMovement(false)
284                , mUpdateMovement(false)
285                , mMoveFwd(false)
286                , mMoveBck(false)
287                , mMoveLeft(false)
288                , mMoveRight(false)
289                , mLastMousePositionSet(false)
290                , mAvgFrameTime(0.1f)
291
292    {
293                mMouse->setEventCallback(this);
294                mKeyboard->setEventCallback(this);
295
296                mRootGuiPanel = CEGUI::WindowManager::getSingleton().getWindow("Shadows");
297
298                mMoveSpeed = 10.0f;
299
300                // Set up a debug panel to display the shadow
301                MaterialPtr debugMat = MaterialManager::getSingleton().create(
302                        "Ogre/DebugShadowMap0", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
303                debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
304                TexturePtr shadowTex = mSceneMgr->getShadowTexture(0);
305                TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(shadowTex->getName());
306                t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
307
308                debugMat = MaterialManager::getSingleton().create(
309                        "Ogre/DebugShadowMap1", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
310                debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
311                shadowTex = mSceneMgr->getShadowTexture(1);
312                t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(shadowTex->getName());
313                t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
314
315                /* Uncomment this to display the shadow textures
316                OverlayContainer* debugPanel = (OverlayContainer*)
317                        (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugShadowPanel0"));
318                debugPanel->_setPosition(0.8, 0);
319                debugPanel->_setDimensions(0.2, 0.2);
320                debugPanel->setMaterialName("Ogre/DebugShadowMap0");
321                Overlay* debugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
322                debugOverlay->add2D(debugPanel);
323               
324                debugPanel = (OverlayContainer*)
325                        (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugShadowPanel1"));
326                debugPanel->_setPosition(0.8, 0.2);
327                debugPanel->_setDimensions(0.2, 0.2);
328                debugPanel->setMaterialName("Ogre/DebugShadowMap1");
329                debugOverlay->add2D(debugPanel);
330                */
331               
332
333    }
334
335
336        bool frameStarted(const FrameEvent& evt)
337        {
338                CEGUI::System::getSingleton().injectTimePulse(evt.timeSinceLastFrame);
339
340                mMouse->capture();
341                mKeyboard->capture();
342
343                if (mShutdownRequested)
344                        return false;
345                else
346                {
347                        // update movement process
348                        if(mProcessMovement || mUpdateMovement)
349                        {
350                                mTranslateVector.x += mMoveLeft ? mAvgFrameTime * -mMoveSpeed : 0;
351                                mTranslateVector.x += mMoveRight ? mAvgFrameTime * mMoveSpeed : 0;
352                                mTranslateVector.z += mMoveFwd ? mAvgFrameTime * -mMoveSpeed : 0;
353                                mTranslateVector.z += mMoveBck ? mAvgFrameTime * mMoveSpeed : 0;
354
355                                mCamera->yaw(mRotX);
356                                mCamera->pitch(mRotY);
357                                mCamera->moveRelative(mTranslateVector);
358
359                                mUpdateMovement = false;
360                                mRotX = 0;
361                                mRotY = 0;
362                                mTranslateVector = Ogre::Vector3::ZERO;
363                        }
364
365                }
366
367                return true;
368        }
369
370    bool frameEnded(const FrameEvent& evt)
371    {
372                if (mAnimState)
373                        mAnimState->addTime(evt.timeSinceLastFrame);
374
375                if (mShutdownRequested)
376                        return false;
377                else
378                        return ExampleFrameListener::frameEnded(evt);
379
380    }
381        //----------------------------------------------------------------//
382        bool mouseMoved( const OIS::MouseEvent &arg )
383        {
384                CEGUI::System::getSingleton().injectMouseMove( arg.state.X.rel, arg.state.Y.rel );
385                return true;
386        }
387
388        //----------------------------------------------------------------//
389        bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
390        {
391                CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
392                return true;
393        }
394
395        //----------------------------------------------------------------//
396        bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
397        {
398                CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
399                return true;
400        }
401
402        //----------------------------------------------------------------//
403        bool keyPressed( const OIS::KeyEvent &arg )
404        {
405                if( arg.key == OIS::KC_ESCAPE )
406                        mShutdownRequested = true;
407
408                if (arg.key == OIS::KC_SYSRQ)
409                        mWindow->writeContentsToTimestampedFile("screenshot", ".jpg");
410
411                CEGUI::System::getSingleton().injectKeyDown( arg.key );
412                CEGUI::System::getSingleton().injectChar( arg.text );
413                return true;
414        }
415
416        //----------------------------------------------------------------//
417        bool keyReleased( const OIS::KeyEvent &arg )
418        {
419                CEGUI::System::getSingleton().injectKeyUp( arg.key );
420                return true;
421        }
422        //--------------------------------------------------------------------------
423        bool handleMouseMove(const CEGUI::EventArgs& e)
424        {
425                const CEGUI::MouseEventArgs& me = static_cast<const CEGUI::MouseEventArgs&>(e);
426
427                if( mLMBDown && !mRMBDown)
428                {
429                        // rotate camera
430                        mRotX += Degree(-me.moveDelta.d_x * mAvgFrameTime * 3.0);
431                        mRotY += Degree(-me.moveDelta.d_y * mAvgFrameTime * 3.0);
432                        CEGUI::MouseCursor::getSingleton().setPosition( mLastMousePosition );
433                        mUpdateMovement = true;
434                }
435                else
436                {
437                        if( mRMBDown && !mLMBDown)
438                        {
439                                // translate camera
440                                mTranslateVector.x += me.moveDelta.d_x * mAvgFrameTime * mMoveSpeed;
441                                mTranslateVector.y += -me.moveDelta.d_y * mAvgFrameTime * mMoveSpeed;
442                                //mTranslateVector.z = 0;
443                                CEGUI::MouseCursor::getSingleton().setPosition( mLastMousePosition );
444                                mUpdateMovement = true;
445                        }
446                        else
447                        {
448                                if( mRMBDown && mLMBDown)
449                                {
450                                        mTranslateVector.z += (me.moveDelta.d_x + me.moveDelta.d_y) * mAvgFrameTime * mMoveSpeed;
451                                        CEGUI::MouseCursor::getSingleton().setPosition( mLastMousePosition );
452                                        mUpdateMovement = true;
453                                }
454
455                        }
456                }
457
458                return true;
459        }
460
461        //--------------------------------------------------------------------------
462        bool handleMouseButtonUp(const CEGUI::EventArgs& e)
463        {
464                const CEGUI::MouseEventArgs& me = static_cast<const CEGUI::MouseEventArgs&>(e);
465
466                //Window* wndw = ((const WindowEventArgs&)e).window;
467                if( me.button == CEGUI::LeftButton )
468                {
469                        mLMBDown = false;
470                }
471
472                if( me.button == CEGUI::RightButton )
473                {
474                        mRMBDown = false;
475                }
476                if( !mLMBDown && !mRMBDown )
477                {
478                        CEGUI::MouseCursor::getSingleton().show();
479                        if(mLastMousePositionSet)
480                        {
481                                CEGUI::MouseCursor::getSingleton().setPosition( mLastMousePosition );
482                                mLastMousePositionSet = false;
483                        }
484                        mRootGuiPanel->releaseInput();
485                }
486
487                return true;
488        }
489
490        //--------------------------------------------------------------------------
491        bool handleMouseButtonDown(const CEGUI::EventArgs& e)
492        {
493                const CEGUI::MouseEventArgs& me = static_cast<const CEGUI::MouseEventArgs&>(e);
494
495                //Window* wndw = ((const WindowEventArgs&)e).window;
496                if( me.button == CEGUI::LeftButton )
497                {
498                        mLMBDown = true;
499                }
500
501                if( me.button == CEGUI::RightButton )
502                {
503                        mRMBDown = true;
504                }
505
506                if( mLMBDown || mRMBDown )
507                {
508                        CEGUI::MouseCursor::getSingleton().hide();
509                        if (!mLastMousePositionSet)
510                        {
511                                mLastMousePosition = CEGUI::MouseCursor::getSingleton().getPosition();
512                                mLastMousePositionSet = true;
513                        }
514                        mRootGuiPanel->captureInput();
515                }
516
517                return true;
518        }
519
520        //--------------------------------------------------------------------------
521        bool handleMouseWheelEvent(const CEGUI::EventArgs& e)
522        {
523                const CEGUI::MouseEventArgs& me = static_cast<const CEGUI::MouseEventArgs&>(e);
524                mTranslateVector.z += me.wheelChange * -5.0;
525                mUpdateMovement = true;
526
527                return true;
528        }
529
530        //--------------------------------------------------------------------------
531        void checkMovementKeys(CEGUI::Key::Scan scancode, bool state )
532        {
533
534                switch ( scancode )
535                {
536                case CEGUI::Key::A:
537                        mMoveLeft = state;
538                        break;
539
540                case CEGUI::Key::D:
541                        mMoveRight = state;
542                        break;
543
544                case CEGUI::Key::S:
545                        mMoveBck = state;
546                        break;
547
548                case CEGUI::Key::W:
549                        mMoveFwd = state;
550                        break;
551
552                default:
553                        break;
554
555                }
556
557                mProcessMovement = mMoveLeft || mMoveRight || mMoveFwd || mMoveBck;
558
559        }
560        //--------------------------------------------------------------------------
561        bool handleKeyDownEvent(const CEGUI::EventArgs& e)
562        {
563                const CEGUI::KeyEventArgs& ke = static_cast<const CEGUI::KeyEventArgs&>(e);
564
565                checkMovementKeys(ke.scancode , true);
566
567                return true;
568        }
569
570        //--------------------------------------------------------------------------
571        bool handleKeyUpEvent(const CEGUI::EventArgs& e)
572        {
573                const CEGUI::KeyEventArgs& ke = static_cast<const CEGUI::KeyEventArgs&>(e);
574                checkMovementKeys(ke.scancode, false );
575
576                return true;
577        }
578
579   
580
581
582};
583
584class ShadowsApplication : public ExampleApplication
585{
586protected:
587        enum ShadowProjection
588        {
589                UNIFORM,
590                UNIFORM_FOCUSED,
591                LISPSM,
592                PLANE_OPTIMAL
593        };
594
595        enum ShadowMaterial
596        {
597                MAT_STANDARD,
598                MAT_DEPTH_FLOAT,
599                MAT_DEPTH_FLOAT_PCF
600        };
601        CEGUI::OgreCEGUIRenderer* mGUIRenderer;
602        CEGUI::System* mGUISystem;
603        CEGUI::Window* mDescWindow;
604        CEGUI::Scrollbar* mFixedBias;
605        CEGUI::Scrollbar* mGradientBias;
606        CEGUI::Scrollbar* mGradientClamp;
607        CEGUI::Window* mDepthShadowTweak;
608        CEGUI::Window* mFixedBiasText;
609        CEGUI::Window* mGradientBiasText;
610        CEGUI::Window* mGradientClampText;
611       
612
613        ShadowTechnique mCurrentShadowTechnique;
614        ShadowProjection mCurrentProjection;
615        ShadowMaterial mCurrentMaterial;
616
617        GpuProgramParametersSharedPtr mCustomRockwallVparams;
618        GpuProgramParametersSharedPtr mCustomRockwallFparams;
619        GpuProgramParametersSharedPtr mCustomAtheneVparams;
620        GpuProgramParametersSharedPtr mCustomAtheneFparams;
621
622        ShadowCameraSetupPtr mCurrentShadowCameraSetup;
623        /// Plane that defines plane-optimal shadow mapping basis
624        MovablePlane* mPlane;
625        // transient pointer to LiSPSM setup if present
626        LiSPSMShadowCameraSetup* mLiSPSMSetup;
627
628        bool mIsOpenGL;
629
630public:
631        ShadowsApplication() : 
632          mGUIRenderer(0),
633          mGUISystem(0),
634          mPlane(0)
635        {
636
637
638    }
639
640    ~ShadowsApplication() 
641    {
642                mDescWindow = 0;
643
644                if(mGUISystem)
645                {
646                        delete mGUISystem;
647                        mGUISystem = 0;
648                }
649                if(mGUIRenderer)
650                {
651                        delete mGUIRenderer;
652                        mGUIRenderer = 0;
653                }
654
655                delete mPlane;
656    }
657protected:
658
659        // Override this to ensure FPU mode
660        bool configure(void)
661        {
662                // Show the configuration dialog and initialise the system
663                // You can skip this and use root.restoreConfig() to load configuration
664                // settings if you were sure there are valid ones saved in ogre.cfg
665                if(mRoot->showConfigDialog())
666                {
667                        // Custom option - to use PlaneOptimalShadowCameraSetup we must have
668                        // double-precision. Thus, set the D3D floating point mode if present,
669                        // no matter what was chosen
670                        ConfigOptionMap& optMap = mRoot->getRenderSystem()->getConfigOptions();
671                        ConfigOptionMap::iterator i = optMap.find("Floating-point mode");
672                        if (i != optMap.end())
673                        {
674                                if (i->second.currentValue != "Consistent")
675                                {
676                                        i->second.currentValue = "Consistent";
677                                        LogManager::getSingleton().logMessage("Demo_Shadows: overriding "
678                                                "D3D floating point mode to 'Consistent' to ensure precision "
679                                                "for plane-optimal camera setup option");
680
681                                }
682                        }
683
684                        // If returned true, user clicked OK so initialise
685                        // Here we choose to let the system create a default rendering window by passing 'true'
686                        mWindow = mRoot->initialise(true);
687                        return true;
688                }
689                else
690                {
691                        return false;
692                }
693        }
694
695        void generalSceneSetup()
696    {
697        // do this first so we generate edge lists
698        mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
699                mCurrentShadowTechnique = SHADOWTYPE_STENCIL_ADDITIVE;
700
701        // Set ambient light off
702        mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.0));
703
704        // Fixed light, dim
705        mSunLight = mSceneMgr->createLight("SunLight");
706        mSunLight->setType(Light::LT_SPOTLIGHT);
707        mSunLight->setPosition(1500,1750,1300);
708        mSunLight->setSpotlightRange(Degree(30), Degree(50));
709        Vector3 dir;
710        dir = -mSunLight->getPosition();
711        dir.normalise();
712        mSunLight->setDirection(dir);
713        mSunLight->setDiffuseColour(0.35, 0.35, 0.38);
714        mSunLight->setSpecularColour(0.9, 0.9, 1);
715
716        // Point light, movable, reddish
717        mLight = mSceneMgr->createLight("Light2");
718        mLight->setDiffuseColour(mMinLightColour);
719        mLight->setSpecularColour(1, 1, 1);
720        mLight->setAttenuation(8000,1,0.0005,0);
721
722        // Create light node
723        mLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(
724            "MovingLightNode");
725        mLightNode->attachObject(mLight);
726        // create billboard set
727        BillboardSet* bbs = mSceneMgr->createBillboardSet("lightbbs", 1);
728        bbs->setMaterialName("Examples/Flare");
729        Billboard* bb = bbs->createBillboard(0,0,0,mMinLightColour);
730        // attach
731        mLightNode->attachObject(bbs);
732
733        // create controller, after this is will get updated on its own
734        ControllerFunctionRealPtr func = ControllerFunctionRealPtr(
735            new WaveformControllerFunction(Ogre::WFT_SINE, 0.75, 0.5));
736        ControllerManager& contMgr = ControllerManager::getSingleton();
737        ControllerValueRealPtr val = ControllerValueRealPtr(
738            new LightWibbler(mLight, bb, mMinLightColour, mMaxLightColour, 
739            mMinFlareSize, mMaxFlareSize));
740        Controller<Real>* controller = contMgr.createController(
741            contMgr.getFrameTimeSource(), val, func);
742
743        //mLight->setPosition(Vector3(300,250,-300));
744        mLightNode->setPosition(Vector3(300,1750,-700));
745
746
747        // Create a track for the light
748        Animation* anim = mSceneMgr->createAnimation("LightTrack", 20);
749        // Spline it for nice curves
750        anim->setInterpolationMode(Animation::IM_SPLINE);
751        // Create a track to animate the camera's node
752        NodeAnimationTrack* track = anim->createNodeTrack(0, mLightNode);
753        // Setup keyframes
754        TransformKeyFrame* key = track->createNodeKeyFrame(0); // A startposition
755        key->setTranslate(Vector3(300,750,-700));
756        key = track->createNodeKeyFrame(2);//B
757        key->setTranslate(Vector3(150,800,-250));
758        key = track->createNodeKeyFrame(4);//C
759        key->setTranslate(Vector3(-150,850,-100));
760        key = track->createNodeKeyFrame(6);//D
761        key->setTranslate(Vector3(-400,700,-200));
762        key = track->createNodeKeyFrame(8);//E
763        key->setTranslate(Vector3(-200,700,-400));
764        key = track->createNodeKeyFrame(10);//F
765        key->setTranslate(Vector3(-100,850,-200));
766        key = track->createNodeKeyFrame(12);//G
767        key->setTranslate(Vector3(-100,575,180));
768        key = track->createNodeKeyFrame(14);//H
769        key->setTranslate(Vector3(0,750,300));
770        key = track->createNodeKeyFrame(16);//I
771        key->setTranslate(Vector3(100,850,100));
772        key = track->createNodeKeyFrame(18);//J
773        key->setTranslate(Vector3(250,800,0));
774        key = track->createNodeKeyFrame(20);//K == A
775        key->setTranslate(Vector3(300,750,-700));
776        // Create a new animation state to track this
777        mAnimState = mSceneMgr->createAnimationState("LightTrack");
778        mAnimState->setEnabled(true);
779        // Make light node look at origin, this is for when we
780        // change the moving light to a spotlight
781        mLightNode->setAutoTracking(true, mSceneMgr->getRootSceneNode());
782
783        // Prepare athene mesh for normalmapping
784        MeshPtr pAthene = MeshManager::getSingleton().load("athene.mesh", 
785            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
786        unsigned short src, dest;
787        if (!pAthene->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
788        {
789            pAthene->buildTangentVectors(VES_TANGENT, src, dest);
790        }
791
792        SceneNode* node;
793        node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
794        mAthene = mSceneMgr->createEntity( "athene", "athene.mesh" );
795        mAthene->setMaterialName(BASIC_ATHENE_MATERIAL);
796        node->attachObject( mAthene );
797        node->translate(0,-27, 0);
798        node->yaw(Degree(90));
799
800        Entity* pEnt;
801                // Columns
802                for (int x = -2; x <= 2; ++x)
803                {
804                        for (int z = -2; z <= 2; ++z)
805                        {
806                                if (x != 0 || z != 0)
807                                {
808                                        StringUtil::StrStreamType str;
809                                        str << "col" << x << "_" << z;
810                                        node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
811                                        pEnt = mSceneMgr->createEntity( str.str(), "column.mesh" );
812                                        pEnt->setMaterialName(BASIC_ROCKWALL_MATERIAL);
813                                        pColumns.push_back(pEnt);
814                                        node->attachObject( pEnt );
815                                        node->translate(x*300,0, z*300);
816
817                                }
818                        }
819
820                }
821
822
823        // Skybox
824        mSceneMgr->setSkyBox(true, "Examples/StormySkyBox");
825
826        // Floor plane (use POSM plane def)
827                mPlane = new MovablePlane("*mPlane");
828        mPlane->normal = Vector3::UNIT_Y;
829        mPlane->d = 107;
830        MeshManager::getSingleton().createPlane("Myplane",
831            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, *mPlane,
832            1500,1500,50,50,true,1,5,5,Vector3::UNIT_Z);
833        pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
834        pPlaneEnt->setMaterialName(BASIC_ROCKWALL_MATERIAL);
835        pPlaneEnt->setCastShadows(false);
836        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
837
838                if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_HWRENDER_TO_TEXTURE))
839        {
840            // In D3D, use a 1024x1024 shadow texture
841            mSceneMgr->setShadowTextureSettings(1024, 2);
842        }
843        else
844        {
845            // Use 512x512 texture in GL since we can't go higher than the window res
846            mSceneMgr->setShadowTextureSettings(512, 2);
847        }
848        mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
849
850        // incase infinite far distance is not supported
851        mCamera->setFarClipDistance(100000);
852
853        //mSceneMgr->setShowDebugShadows(true);
854
855                mCamera->setPosition(250, 20, 400);
856                mCamera->lookAt(0, 10, 0);
857
858    }
859       
860    // Just override the mandatory create scene method
861    void createScene(void)
862    {
863                // Need to detect D3D or GL for best depth shadowmapping
864                if (Root::getSingleton().getRenderSystem()->getName().find("GL") != String::npos)
865                {
866                        mIsOpenGL = true;
867                }
868                else
869                {
870                        mIsOpenGL = false;
871                }
872
873                // set up general scene (this defaults to additive stencils)
874        generalSceneSetup();
875
876                setupGUI();
877
878
879    }
880
881        /// Change basic shadow technique
882        void changeShadowTechnique(ShadowTechnique newTech)
883        {
884                mSceneMgr->setShadowTechnique(newTech);
885
886                // Below is for projection
887                //configureShadowCameras(mCurrentShadowTechnique, newTech);
888
889                configureLights(newTech);
890
891                // Advanced modes - materials / compositors
892                //configureCompositors(mCurrentShadowTechnique, newTech);
893                //configureTextures(mCurrentShadowTechnique, newTech);
894                //configureShadowCasterReceiverMaterials(mCurrentShadowTechnique, newTech);
895
896                updateGUI(newTech);
897
898                mCurrentShadowTechnique = newTech;
899
900
901        }
902
903
904
905        void configureLights(ShadowTechnique newTech)
906        {
907                Vector3 dir;
908                switch (newTech)
909                {
910                case SHADOWTYPE_STENCIL_ADDITIVE:
911                        // Fixed light, dim
912                        mSunLight->setCastShadows(true);
913
914                        // Point light, movable, reddish
915                        mLight->setType(Light::LT_POINT);
916                        mLight->setCastShadows(true);
917                        mLight->setDiffuseColour(mMinLightColour);
918                        mLight->setSpecularColour(1, 1, 1);
919                        mLight->setAttenuation(8000,1,0.0005,0);
920
921                        break;
922                case SHADOWTYPE_STENCIL_MODULATIVE:
923                        // Multiple lights cause obvious silhouette edges in modulative mode
924                        // So turn off shadows on the direct light
925                        // Fixed light, dim
926                        mSunLight->setCastShadows(false);
927
928                        // Point light, movable, reddish
929                        mLight->setType(Light::LT_POINT);
930                        mLight->setCastShadows(true);
931                        mLight->setDiffuseColour(mMinLightColour);
932                        mLight->setSpecularColour(1, 1, 1);
933                        mLight->setAttenuation(8000,1,0.0005,0);
934                        break;
935                case SHADOWTYPE_TEXTURE_MODULATIVE:
936                case SHADOWTYPE_TEXTURE_ADDITIVE:
937                        // Fixed light, dim
938                        mSunLight->setCastShadows(true);
939
940                        // Change moving light to spotlight
941                        // Point light, movable, reddish
942                        mLight->setType(Light::LT_SPOTLIGHT);
943                        mLight->setDirection(Vector3::NEGATIVE_UNIT_Z);
944                        mLight->setCastShadows(true);
945                        mLight->setDiffuseColour(mMinLightColour);
946                        mLight->setSpecularColour(1, 1, 1);
947                        mLight->setAttenuation(8000,1,0.0005,0);
948                        mLight->setSpotlightRange(Degree(80),Degree(90));
949
950
951                        break;
952                default:
953                        break;
954                };
955
956        }
957
958        void setupGUI()
959        {
960                // setup GUI system
961                mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, 
962                        Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
963
964                mGUISystem = new CEGUI::System(mGUIRenderer);
965
966                CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
967
968                // load scheme and set up defaults
969                CEGUI::SchemeManager::getSingleton().loadScheme(
970                        (CEGUI::utf8*)"TaharezLookSkin.scheme");
971                mGUISystem->setDefaultMouseCursor(
972                        (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
973                mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
974
975                CEGUI::Window* sheet = 
976                        CEGUI::WindowManager::getSingleton().loadWindowLayout(
977                        (CEGUI::utf8*)"shadows.layout"); 
978                mGUISystem->setGUISheet(sheet);
979
980                // Tooltips aren't big enough, do our own
981                //mGUISystem->setDefaultTooltip("TaharezLook/Tooltip");
982
983                CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
984                // Get description window
985                mDescWindow = wmgr.getWindow("Shadows/Desc");
986
987                CEGUI::Window *wnd = wmgr.getWindow("Shadows/Stencil");
988                wnd->subscribeEvent(CEGUI::Window::EventMouseEnters, 
989                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnter, this));
990                wnd->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
991                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
992                wnd = wmgr.getWindow("Shadows/Texture");
993                wnd->subscribeEvent(CEGUI::Window::EventMouseEnters, 
994                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnter, this));
995                wnd->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
996                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
997                wnd = wmgr.getWindow("Shadows/Additive");
998                wnd->subscribeEvent(CEGUI::Window::EventMouseEnters, 
999                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnter, this));
1000                wnd->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1001                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1002                wnd = wmgr.getWindow("Shadows/Modulative");
1003                wnd->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1004                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnter, this));
1005                wnd->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1006                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1007               
1008                // Combo doesn't raise enter / exit itself, have to grab subcomponents?
1009                CEGUI::Combobox* cbo = static_cast<CEGUI::Combobox*>(wmgr.getWindow("Shadows/Projection"));
1010                cbo->subscribeEvent(CEGUI::Combobox::EventListSelectionAccepted,
1011                        CEGUI::Event::Subscriber(&ShadowsApplication::handleProjectionChanged, this));
1012                cbo->getEditbox()->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1013                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnterCombo, this));
1014                cbo->getEditbox()->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1015                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1016                cbo->getDropList()->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1017                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnterCombo, this));
1018                cbo->getDropList()->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1019                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1020                cbo->getPushButton()->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1021                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnterCombo, this));
1022                cbo->getPushButton()->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1023                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1024                // Populate projection
1025                // Get a select image to be used for highlighting items in listbox when mouse moves over them
1026                const CEGUI::Image* selectImage = &CEGUI::ImagesetManager::getSingleton().getImageset("TaharezLook")->getImage("MultiListSelectionBrush");
1027                CEGUI::ListboxTextItem* li = new CEGUI::ListboxTextItem("Uniform", UNIFORM);
1028        li->setSelectionBrushImage(selectImage);
1029                li->setTooltipText("Uniform: Shadows are rendered and projected using a uniform "
1030                        "frustum for the whole light coverage. Simple and lowest quality.");
1031                cbo->addItem(li);
1032                cbo->setItemSelectState(li, true);
1033                cbo->setText("Uniform");
1034                mCurrentProjection = UNIFORM;
1035                li = new CEGUI::ListboxTextItem("Uniform Focused", UNIFORM_FOCUSED);
1036        li->setSelectionBrushImage(selectImage);
1037                li->setTooltipText("Uniform Focused: As Uniform except that the frustum is "
1038                        "focused on the visible area of the camera. Better quality than Uniform "
1039                        "at the expense of some 'swimming'.");
1040                cbo->addItem(li);
1041                li = new CEGUI::ListboxTextItem("LiSPSM", LISPSM);
1042        li->setSelectionBrushImage(selectImage);
1043                li->setTooltipText("LiSPSM: The frustum is distorted to take into account "
1044                        "the perspective of the camera, and focused on the visible area. "
1045                        "Good quality & flexibility.");
1046                cbo->addItem(li);
1047                li = new CEGUI::ListboxTextItem("Plane Optimal", PLANE_OPTIMAL);
1048        li->setSelectionBrushImage(selectImage);
1049                li->setTooltipText("Plane Optimal: The frustum is optimised to project "
1050                        "shadows onto a plane of interest. Best possible quality for the "
1051                        "plane, less good for other receiver angles.");
1052                cbo->addItem(li);
1053
1054               
1055                cbo = static_cast<CEGUI::Combobox*>(wmgr.getWindow("Shadows/Material"));
1056                cbo->getEditbox()->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1057                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnterCombo, this));
1058                cbo->getEditbox()->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1059                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1060                cbo->getDropList()->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1061                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnterCombo, this));
1062                cbo->getDropList()->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1063                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1064                cbo->getPushButton()->subscribeEvent(CEGUI::Window::EventMouseEnters, 
1065                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseEnterCombo, this));
1066                cbo->getPushButton()->subscribeEvent(CEGUI::Window::EventMouseLeaves, 
1067                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMouseLeave, this));
1068                cbo->subscribeEvent(CEGUI::Combobox::EventListSelectionAccepted,
1069                        CEGUI::Event::Subscriber(&ShadowsApplication::handleMaterialChanged, this));
1070
1071                li = new CEGUI::ListboxTextItem("Standard", MAT_STANDARD);
1072                li->setSelectionBrushImage(selectImage);
1073                li->setTooltipText("Standard Material: Shadows are rendered into a simple RGB texture "
1074                        " and are received only by objects that are not themselves shadow casters "
1075                        " (no self-shadowing)");
1076                cbo->addItem(li);
1077                cbo->setItemSelectState(li, true);
1078                cbo->setText("Standard");
1079                mCurrentMaterial = MAT_STANDARD;
1080
1081                // Only add depth shadowmapping if supported
1082                if (GpuProgramManager::getSingleton().isSyntaxSupported("ps_2_0") ||
1083                        GpuProgramManager::getSingleton().isSyntaxSupported("glsl"))
1084                {
1085                        li = new CEGUI::ListboxTextItem("Depth Shadowmap", MAT_DEPTH_FLOAT);
1086                        li->setSelectionBrushImage(selectImage);
1087                        li->setTooltipText("Depth Shadowmap: Shadow caster depth is rendered into a "
1088                                " floating point texture and a depth comparison is performed on receivers "
1089                                " (self-shadowing allowed). Requires floating point textures and shader support.");
1090                        cbo->addItem(li);
1091
1092                        li = new CEGUI::ListboxTextItem("Depth Shadowmap (PCF)", MAT_DEPTH_FLOAT_PCF);
1093                        li->setSelectionBrushImage(selectImage);
1094                        li->setTooltipText("Depth Shadowmap (PCF): Shadow caster depth is rendered into a "
1095                                " floating point texture and a depth comparison is performed on receivers "
1096                                " (self-shadowing allowed), with a percentage closest filter. Requires "
1097                                "floating point textures and shader support.");
1098                        cbo->addItem(li);
1099                }
1100
1101                CEGUI::RadioButton* radio = static_cast<CEGUI::RadioButton*>(
1102                        wmgr.getWindow("Shadows/Stencil"));
1103                radio->setSelected(true);
1104                radio->subscribeEvent(CEGUI::RadioButton::EventSelectStateChanged, 
1105                        CEGUI::Event::Subscriber(&ShadowsApplication::handleShadowTypeChanged, this));
1106                radio = static_cast<CEGUI::RadioButton*>(wmgr.getWindow("Shadows/Texture"));
1107                radio->subscribeEvent(CEGUI::RadioButton::EventSelectStateChanged, 
1108                        CEGUI::Event::Subscriber(&ShadowsApplication::handleShadowTypeChanged, this));
1109                radio = static_cast<CEGUI::RadioButton*>(wmgr.getWindow("Shadows/Modulative"));
1110                radio->subscribeEvent(CEGUI::RadioButton::EventSelectStateChanged, 
1111                        CEGUI::Event::Subscriber(&ShadowsApplication::handleShadowTypeChanged, this));
1112                radio = static_cast<CEGUI::RadioButton*>(wmgr.getWindow("Shadows/Additive"));
1113                radio->setSelected(true);
1114                radio->subscribeEvent(CEGUI::RadioButton::EventSelectStateChanged, 
1115                        CEGUI::Event::Subscriber(&ShadowsApplication::handleShadowTypeChanged, this));
1116
1117
1118
1119                mFixedBias = static_cast<CEGUI::Scrollbar*>(wmgr.getWindow("Shadows/DepthShadowTweakGroup/FixedBias"));
1120                mFixedBias->setScrollPosition(0.002f);
1121                mFixedBias->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged, 
1122                        CEGUI::Event::Subscriber(&ShadowsApplication::handleParamsChanged, this));
1123                mGradientBias = static_cast<CEGUI::Scrollbar*>(wmgr.getWindow("Shadows/DepthShadowTweakGroup/SlopeBias"));
1124                mGradientBias->setScrollPosition(0.0008f);
1125                mGradientBias->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged, 
1126                        CEGUI::Event::Subscriber(&ShadowsApplication::handleParamsChanged, this));
1127                mGradientClamp = static_cast<CEGUI::Scrollbar*>(wmgr.getWindow("Shadows/DepthShadowTweakGroup/SlopeClamp"));
1128                mGradientClamp->setScrollPosition(0.02f);
1129                mGradientClamp->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged, 
1130                        CEGUI::Event::Subscriber(&ShadowsApplication::handleParamsChanged, this));
1131
1132                mDepthShadowTweak = wmgr.getWindow("Shadows/DepthShadowTweakGroup");
1133                mDepthShadowTweak->setVisible(false);
1134                mFixedBiasText = wmgr.getWindow("Shadows/DepthShadowTweakGroup/FixedBiasText");
1135                mGradientBiasText = wmgr.getWindow("Shadows/DepthShadowTweakGroup/SlopeBiasText");
1136                mGradientClampText = wmgr.getWindow("Shadows/DepthShadowTweakGroup/SlopeClampText");
1137               
1138
1139               
1140
1141                updateGUI(mCurrentShadowTechnique);
1142
1143
1144
1145        }
1146
1147        void updateGUI(ShadowTechnique newTech)
1148        {
1149                bool isTextureBased = (newTech & SHADOWDETAILTYPE_TEXTURE) != 0;
1150
1151                // Stencil based technique, turn off the texture-specific options
1152                CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
1153                CEGUI::Window* win = wmgr.getWindow("Shadows/Projection");
1154                win->setEnabled(isTextureBased);
1155                win = wmgr.getWindow("Shadows/Material");
1156                win->setEnabled(isTextureBased);
1157
1158        }
1159
1160        /// callback when mouse enters a described field (non-combo)
1161        bool handleMouseEnter(const CEGUI::EventArgs& e)
1162        {
1163                const CEGUI::WindowEventArgs& winargs = 
1164                        static_cast<const CEGUI::WindowEventArgs&>(e);
1165                mDescWindow->setText(winargs.window->getTooltipText());
1166
1167                return true;
1168        }
1169        /// callback when mouse leaves a described field
1170        bool handleMouseLeave(const CEGUI::EventArgs& e)
1171        {
1172                //if (mDescWindow)
1173                //      mDescWindow->setText("");
1174
1175                return true;
1176        }
1177
1178        void updateTipForCombo(CEGUI::Combobox* cbo)
1179        {
1180
1181                CEGUI::String text = cbo->getTooltipText();
1182
1183                text.append(" ");
1184                if (cbo->getSelectedItem())
1185                        text.append(cbo->getSelectedItem()->getTooltipText());
1186                mDescWindow->setText(text);
1187
1188        }
1189        /// callback when mouse enters a described field (combo)
1190        bool handleMouseEnterCombo(const CEGUI::EventArgs& e)
1191        {
1192                const CEGUI::WindowEventArgs& winargs = 
1193                        static_cast<const CEGUI::WindowEventArgs&>(e);
1194                // get tooltip from parent combo (events raised on contained components)
1195                CEGUI::Combobox* cbo = static_cast<CEGUI::Combobox*>(winargs.window->getParent());
1196                updateTipForCombo(cbo);
1197
1198                return true;
1199        }
1200        // Callback when a shadow type combo changed
1201        bool handleShadowTypeChanged(const CEGUI::EventArgs& e)
1202        {
1203                // Only trigger change on selected
1204                const CEGUI::WindowEventArgs& we = static_cast<const CEGUI::WindowEventArgs&>(e);
1205                CEGUI::RadioButton* radio = static_cast<CEGUI::RadioButton*>(we.window);
1206                if (radio->isSelected())
1207                {
1208                        ShadowTechnique newTech = mCurrentShadowTechnique;
1209                        switch (radio->getID())
1210                        {
1211                        case 1:
1212                                // stencil
1213                                newTech = static_cast<ShadowTechnique>(
1214                                        (newTech & ~SHADOWDETAILTYPE_TEXTURE) | SHADOWDETAILTYPE_STENCIL);
1215                                resetMaterials();
1216                                break;
1217                        case 2:
1218                                // texture
1219                                newTech = static_cast<ShadowTechnique>(
1220                                        (newTech & ~SHADOWDETAILTYPE_STENCIL) | SHADOWDETAILTYPE_TEXTURE);
1221                                break;
1222                        case 3:
1223                                // additive
1224                                newTech = static_cast<ShadowTechnique>(
1225                                        (newTech & ~SHADOWDETAILTYPE_MODULATIVE) | SHADOWDETAILTYPE_ADDITIVE);
1226                                break;
1227                        case 4:
1228                                // modulative
1229                                newTech = static_cast<ShadowTechnique>(
1230                                        (newTech & ~SHADOWDETAILTYPE_ADDITIVE) | SHADOWDETAILTYPE_MODULATIVE);
1231                                break;
1232
1233
1234                        }
1235
1236                        changeShadowTechnique(newTech);
1237
1238                }
1239
1240                return true;
1241        }
1242
1243        bool handleProjectionChanged(const CEGUI::EventArgs& e)
1244        {
1245                const CEGUI::WindowEventArgs& winargs = 
1246                        static_cast<const CEGUI::WindowEventArgs&>(e);
1247                CEGUI::Combobox* cbo = static_cast<CEGUI::Combobox*>(winargs.window);
1248
1249                if (cbo->getSelectedItem())
1250                {
1251                        ShadowProjection proj = (ShadowProjection)cbo->getSelectedItem()->getID();
1252                        if (proj != mCurrentProjection)
1253                        {
1254                                switch(proj)
1255                                {
1256                                case UNIFORM:
1257                                        mCurrentShadowCameraSetup = 
1258                                                ShadowCameraSetupPtr(new DefaultShadowCameraSetup());
1259                                        break;
1260                                case UNIFORM_FOCUSED:
1261                                        mCurrentShadowCameraSetup = 
1262                                                ShadowCameraSetupPtr(new FocusedShadowCameraSetup());
1263                                        break;
1264                                case LISPSM:
1265                                        {
1266                                                mLiSPSMSetup = new LiSPSMShadowCameraSetup();
1267                                                //mLiSPSMSetup->setUseAggressiveFocusRegion(false);
1268                                                mCurrentShadowCameraSetup = ShadowCameraSetupPtr(mLiSPSMSetup);
1269                                        }
1270                                        break;
1271                                case PLANE_OPTIMAL:
1272                                        mCurrentShadowCameraSetup = 
1273                                                ShadowCameraSetupPtr(new PlaneOptimalShadowCameraSetup(mPlane));
1274                                        break;
1275
1276                                };
1277                                mCurrentProjection = proj;
1278
1279                                mSceneMgr->setShadowCameraSetup(mCurrentShadowCameraSetup);
1280
1281                                updateTipForCombo(cbo);
1282                                if (!mCustomRockwallVparams.isNull() && !mCustomRockwallFparams.isNull())
1283                                {
1284                                        // set
1285                                        setDefaultDepthShadowParams();
1286                                }
1287
1288                        }
1289                }
1290
1291                return true;
1292        }
1293
1294        void updateDepthShadowParams()
1295        {
1296                mCustomRockwallFparams->setNamedConstant("fixedDepthBias", 
1297                        mFixedBias->getScrollPosition());
1298                mCustomRockwallFparams->setNamedConstant("gradientScaleBias",
1299                        mGradientBias->getScrollPosition());
1300                mCustomRockwallFparams->setNamedConstant("gradientClamp",
1301                        mGradientClamp->getScrollPosition());
1302
1303                mCustomAtheneFparams->setNamedConstant("fixedDepthBias", 
1304                        mFixedBias->getScrollPosition());
1305                mCustomAtheneFparams->setNamedConstant("gradientScaleBias",
1306                        mGradientBias->getScrollPosition());
1307                mCustomAtheneFparams->setNamedConstant("gradientClamp",
1308                        mGradientClamp->getScrollPosition());
1309
1310
1311                mFixedBiasText->setText(StringConverter::toString(
1312                        mFixedBias->getScrollPosition(), 4, 5, '0', std::ios::fixed));
1313                mGradientBiasText->setText(StringConverter::toString(
1314                        mGradientBias->getScrollPosition(), 4, 5, '0', std::ios::fixed));
1315                mGradientClampText->setText(StringConverter::toString(
1316                        mGradientClamp->getScrollPosition(), 4, 5, '0', std::ios::fixed));
1317        }
1318
1319        void setDefaultDepthShadowParams()
1320        {
1321                switch(mCurrentProjection)
1322                {
1323                case UNIFORM:
1324                case UNIFORM_FOCUSED:
1325                case PLANE_OPTIMAL:
1326                        mFixedBias->setScrollPosition(0.0f);
1327                        mGradientBias->setScrollPosition(0.0f);
1328                        break;
1329                case LISPSM:
1330                        mFixedBias->setScrollPosition(0.009f);
1331                        mGradientBias->setScrollPosition(0.04f);
1332                        break;
1333                };
1334
1335                updateDepthShadowParams();
1336
1337        }
1338
1339        bool handleParamsChanged(const CEGUI::EventArgs& e)
1340        {
1341                if (!mCustomRockwallVparams.isNull() && !mCustomRockwallFparams.isNull())
1342                {
1343                        updateDepthShadowParams();
1344                }
1345
1346                return true;
1347        }
1348
1349        void rebindDebugShadowOverlays()
1350        {
1351                MaterialPtr debugMat = 
1352                        MaterialManager::getSingleton().getByName("Ogre/DebugShadowMap0");
1353                TexturePtr shadowTex = mSceneMgr->getShadowTexture(0);
1354                debugMat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(shadowTex->getName());
1355
1356                debugMat = 
1357                        MaterialManager::getSingleton().getByName("Ogre/DebugShadowMap1");
1358                shadowTex = mSceneMgr->getShadowTexture(1);
1359                debugMat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(shadowTex->getName());
1360        }
1361
1362        void resetMaterials()
1363        {
1364                // Sort out base materials
1365                pPlaneEnt->setMaterialName(BASIC_ROCKWALL_MATERIAL);
1366                mAthene->setMaterialName(BASIC_ATHENE_MATERIAL);
1367                for (std::vector<Entity*>::iterator i = pColumns.begin();
1368                        i != pColumns.end(); ++i)
1369                {
1370                        (*i)->setMaterialName(BASIC_ROCKWALL_MATERIAL);
1371                }
1372
1373                mCustomRockwallVparams.setNull();
1374                mCustomRockwallFparams.setNull();
1375                mCustomAtheneVparams.setNull();
1376                mCustomAtheneFparams.setNull();
1377
1378        }
1379        bool handleMaterialChanged(const CEGUI::EventArgs& e)
1380        {
1381                const CEGUI::WindowEventArgs& winargs = 
1382                        static_cast<const CEGUI::WindowEventArgs&>(e);
1383                CEGUI::Combobox* cbo = static_cast<CEGUI::Combobox*>(winargs.window);
1384
1385                if (cbo->getSelectedItem())
1386                {
1387                        ShadowMaterial mat = (ShadowMaterial)cbo->getSelectedItem()->getID();
1388                        MaterialPtr themat;
1389                        if (mat != mCurrentMaterial)
1390                        {
1391                                switch(mat)
1392                                {
1393                                case MAT_STANDARD:
1394                                        mSceneMgr->setShadowTexturePixelFormat(PF_L8);
1395                                        mSceneMgr->setShadowTextureCasterMaterial(StringUtil::BLANK);
1396                                        mSceneMgr->setShadowTextureReceiverMaterial(StringUtil::BLANK);
1397                                        mSceneMgr->setShadowTextureSelfShadow(false);   
1398                                        mDepthShadowTweak->setVisible(false);
1399
1400                                        resetMaterials();
1401
1402                                        break;
1403                                case MAT_DEPTH_FLOAT:
1404                                        if (mIsOpenGL)
1405                                        {
1406                                                // GL performs much better if you pick half-float format
1407                                                mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT16_R);
1408                                        }
1409                                        else
1410                                        {
1411                                                // D3D is the opposite - if you ask for PF_FLOAT16_R you
1412                                                // get an integer format instead! You can ask for PF_FLOAT16_GR
1413                                                // but the precision doesn't work well
1414                                                mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
1415                                        }
1416                                        mSceneMgr->setShadowTextureCasterMaterial(CUSTOM_CASTER_MATERIAL);
1417                                        mSceneMgr->setShadowTextureReceiverMaterial(CUSTOM_RECEIVER_MATERIAL);
1418                                        mSceneMgr->setShadowTextureSelfShadow(true);   
1419                                        // Sort out base materials
1420                                        pPlaneEnt->setMaterialName(CUSTOM_ROCKWALL_MATERIAL);
1421                                        mAthene->setMaterialName(CUSTOM_ATHENE_MATERIAL);
1422                                        for (std::vector<Entity*>::iterator i = pColumns.begin();
1423                                                i != pColumns.end(); ++i)
1424                                        {
1425                                                (*i)->setMaterialName(CUSTOM_ROCKWALL_MATERIAL);
1426                                        }
1427
1428                                        themat = MaterialManager::getSingleton().getByName(CUSTOM_ROCKWALL_MATERIAL);
1429                                        mCustomRockwallVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
1430                                        mCustomRockwallFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
1431                                        themat = MaterialManager::getSingleton().getByName(CUSTOM_ATHENE_MATERIAL);
1432                                        mCustomAtheneVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
1433                                        mCustomAtheneFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
1434                                        mDepthShadowTweak->setVisible(true);
1435
1436
1437                                        // set the current params
1438                                        setDefaultDepthShadowParams();
1439                                        break;
1440                                case MAT_DEPTH_FLOAT_PCF:
1441                                        if (mIsOpenGL)
1442                                        {
1443                                                // GL performs much better if you pick half-float format
1444                                                mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT16_R);
1445                                        }
1446                                        else
1447                                        {
1448                                                // D3D is the opposite - if you ask for PF_FLOAT16_R you
1449                                                // get an integer format instead! You can ask for PF_FLOAT16_GR
1450                                                // but the precision doesn't work well
1451                                                mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
1452                                        }
1453                                        mSceneMgr->setShadowTextureCasterMaterial(CUSTOM_CASTER_MATERIAL);
1454                                        mSceneMgr->setShadowTextureReceiverMaterial(CUSTOM_RECEIVER_MATERIAL + "/PCF");
1455                                        mSceneMgr->setShadowTextureSelfShadow(true);   
1456                                        // Sort out base materials
1457                                        pPlaneEnt->setMaterialName(CUSTOM_ROCKWALL_MATERIAL + "/PCF");
1458                                        mAthene->setMaterialName(CUSTOM_ATHENE_MATERIAL + "/PCF");
1459                                        for (std::vector<Entity*>::iterator i = pColumns.begin();
1460                                                i != pColumns.end(); ++i)
1461                                        {
1462                                                (*i)->setMaterialName(CUSTOM_ROCKWALL_MATERIAL + "/PCF");
1463                                        }
1464
1465                                        themat = MaterialManager::getSingleton().getByName(CUSTOM_ROCKWALL_MATERIAL + "/PCF");
1466                                        mCustomRockwallVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
1467                                        mCustomRockwallFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
1468                                        themat = MaterialManager::getSingleton().getByName(CUSTOM_ATHENE_MATERIAL + "/PCF");
1469                                        mCustomAtheneVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
1470                                        mCustomAtheneFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
1471                                        mDepthShadowTweak->setVisible(true);
1472
1473                                        // set the current params
1474                                        setDefaultDepthShadowParams();
1475                                        break;
1476                                };
1477                                mCurrentMaterial = mat;
1478
1479                                updateTipForCombo(cbo);
1480                                rebindDebugShadowOverlays();
1481
1482                        }
1483                }
1484
1485                return true;
1486        }
1487
1488    // Create new frame listener
1489    void createFrameListener(void)
1490    {
1491        ShadowsListener* shadowListener = new ShadowsListener(mWindow, mCamera, mSceneMgr);
1492                mFrameListener = shadowListener;
1493        mFrameListener->showDebugOverlay(true);
1494        mRoot->addFrameListener(mFrameListener);
1495
1496                // Hook up Root sheet (handles main input)
1497                CEGUI::Window* wnd = CEGUI::WindowManager::getSingleton().getWindow("Shadows");
1498                wnd->subscribeEvent(CEGUI::Window::EventMouseMove, 
1499                        CEGUI::Event::Subscriber(&ShadowsListener::handleMouseMove, shadowListener));
1500                wnd->subscribeEvent(CEGUI::Window::EventMouseButtonUp, 
1501                        CEGUI::Event::Subscriber(&ShadowsListener::handleMouseButtonUp, shadowListener));
1502                wnd->subscribeEvent(CEGUI::Window::EventMouseButtonDown, 
1503                        CEGUI::Event::Subscriber(&ShadowsListener::handleMouseButtonDown, shadowListener));
1504                wnd->subscribeEvent(CEGUI::Window::EventMouseWheel, 
1505                        CEGUI::Event::Subscriber(&ShadowsListener::handleMouseWheelEvent, shadowListener));
1506                wnd->subscribeEvent(CEGUI::Window::EventKeyDown, 
1507                        CEGUI::Event::Subscriber(&ShadowsListener::handleKeyDownEvent, shadowListener ));
1508                wnd->subscribeEvent(CEGUI::Window::EventKeyUp, 
1509                        CEGUI::Event::Subscriber(&ShadowsListener::handleKeyUpEvent, shadowListener ));
1510
1511
1512    }
1513
1514
1515public:
1516    void go(void)
1517    {
1518        if (!setup())
1519            return;
1520
1521        mRoot->startRendering();
1522    }
1523
1524
1525};
1526
1527
1528
1529#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1530#define WIN32_LEAN_AND_MEAN
1531#include "windows.h"
1532#endif
1533
1534#ifdef __cplusplus
1535extern "C" {
1536#endif
1537
1538#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1539INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
1540#else
1541int main(int argc, char *argv[])
1542#endif
1543{
1544    // Create application object
1545    ShadowsApplication app;
1546
1547    try {
1548        app.go();
1549    } catch( Ogre::Exception& e ) {
1550#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1551        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
1552#else
1553        std::cerr << "An exception has occured: " <<
1554            e.getFullDescription().c_str() << std::endl;
1555#endif
1556    }
1557
1558    return 0;
1559}
1560
1561#ifdef __cplusplus
1562}
1563#endif
Note: See TracBrowser for help on using the repository browser.