Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreD3D9RenderSystem.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://ogre.sourceforge.net/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreD3D9RenderSystem.h"
    00026 #include "OgreD3D9Prerequisites.h"
    00027 #include "OgreD3D9DriverList.h"
    00028 #include "OgreD3D9Driver.h"
    00029 #include "OgreD3D9VideoModeList.h"
    00030 #include "OgreD3D9VideoMode.h"
    00031 #include "OgreD3D9RenderWindow.h"
    00032 #include "OgreD3D9TextureManager.h"
    00033 #include "OgreD3D9Texture.h"
    00034 #include "OgreLogManager.h"
    00035 #include "OgreLight.h"
    00036 #include "OgreMath.h"
    00037 #include "OgreD3D9HardwareBufferManager.h"
    00038 #include "OgreD3D9HardwareIndexBuffer.h"
    00039 #include "OgreD3D9HardwareVertexBuffer.h"
    00040 #include "OgreD3D9VertexDeclaration.h"
    00041 #include "OgreD3D9GpuProgram.h"
    00042 #include "OgreD3D9GpuProgramManager.h"
    00043 //#include "OgreD3D9HLSLProgramFactory.h"
    00044 #include "OgreHighLevelGpuProgramManager.h"
    00045 #include "OgreD3D9HardwareOcclusionQuery.h"
    00046 #include "OgreFrustum.h"
    00047
    00048
    00049
    00050 namespace Ogre
    00051 {
    00052
    00053     const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(
    00054         0.5,    0,  0, -0.5,
    00055         0, -0.5,  0, -0.5,
    00056         0,    0,  0,   1,
    00057         0,    0,  0,   1);
    00058
    00059     const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO(
    00060         -0.5,    0,  0, -0.5,
    00061         0, 0.5,  0, -0.5,
    00062         0,    0,  0,   1,
    00063         0,    0,  0,   1);
    00064
    00065     //---------------------------------------------------------------------
    00066     D3D9RenderSystem::D3D9RenderSystem( HINSTANCE hInstance )
    00067     {
    00068         OgreGuard( "D3D9RenderSystem::D3D9RenderSystem" );
    00069         LogManager::getSingleton().logMessage( "D3D9 : " + getName() + " created." );
    00070
    00071         // set the instance being passed
    00072         mhInstance = hInstance;
    00073
    00074         // set pointers to NULL
    00075         mpD3D = NULL;
    00076         mpD3DDevice = NULL;
    00077         mDriverList = NULL;
    00078         mActiveD3DDriver = NULL;
    00079         mExternalHandle = NULL;
    00080         mTextureManager = NULL;
    00081         mHardwareBufferManager = NULL;
    00082         mGpuProgramManager = NULL;
    00083         //mHLSLProgramFactory = NULL;
    00084
    00085         // init lights
    00086         for(int i = 0; i < MAX_LIGHTS; i++ )
    00087             mLights[i] = 0;
    00088
    00089         // Create our Direct3D object
    00090         if( NULL == (mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
    00091             Except( Exception::ERR_INTERNAL_ERROR, "Failed to create Direct3D9 object", "D3D9RenderSystem::D3D9RenderSystem" );
    00092
    00093         // set config options defaults
    00094         initConfigOptions();
    00095
    00096         // fsaa options
    00097         mFSAAType = D3DMULTISAMPLE_NONE;
    00098         mFSAAQuality = 0;
    00099
    00100         // set stages desc. to defaults
    00101         for (size_t n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++)
    00102         {
    00103             mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
    00104             mTexStageDesc[n].coordIndex = 0;
    00105             mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
    00106             mTexStageDesc[n].pTex = 0;
    00107         }
    00108
    00109         mLastVertexSourceCount = 0;
    00110
    00111         mCurrentLights = 0;
    00112
    00113
    00114         OgreUnguard();
    00115     }
    00116     //---------------------------------------------------------------------
    00117     D3D9RenderSystem::~D3D9RenderSystem()
    00118     {
    00119         OgreGuard( "D3D9RenderSystem::~D3D9RenderSystem" );
    00120         shutdown();
    00121
    00122         // Unbind any vertex streams to avoid memory leaks
    00123         for (unsigned int i = 0; i < mLastVertexSourceCount; ++i)
    00124         {
    00125             HRESULT hr = mpD3DDevice->SetStreamSource(i, NULL, 0, 0);
    00126         }
    00127
    00128
    00129         SAFE_DELETE( mDriverList );
    00130         SAFE_DELETE( mTextureManager );
    00131         SAFE_DELETE(mHardwareBufferManager);
    00132         //SAFE_DELETE(mHLSLProgramFactory);
    00133         SAFE_DELETE(mGpuProgramManager);
    00134         SAFE_RELEASE( mpD3D );
    00135
    00136         if (mCapabilities)
    00137         {
    00138             delete mCapabilities;
    00139             mCapabilities = NULL;
    00140         }
    00141
    00142         LogManager::getSingleton().logMessage( "D3D9 : " + getName() + " destroyed." );
    00143         OgreUnguard();
    00144     }
    00145     //---------------------------------------------------------------------
    00146     const String& D3D9RenderSystem::getName() const
    00147     {
    00148         static String strName( "Direct3D9 Rendering SubSystem");
    00149         return strName;
    00150     }
    00151     //---------------------------------------------------------------------
    00152     D3D9DriverList* D3D9RenderSystem::getDirect3DDrivers()
    00153     {
    00154         if( !mDriverList )
    00155             mDriverList = new D3D9DriverList( mpD3D );
    00156
    00157         return mDriverList;
    00158     }
    00159     //---------------------------------------------------------------------
    00160     bool D3D9RenderSystem::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
    00161     {
    00162         HRESULT hr;
    00163         hr = mpD3D->CheckDeviceMultiSampleType(
    00164                 adapterNum,
    00165                 deviceType,
    00166                 format,
    00167                 fullScreen,
    00168                 type,
    00169                 outQuality);
    00170
    00171         if (SUCCEEDED(hr))
    00172             return true;
    00173         else
    00174             return false;
    00175     }
    00176     //---------------------------------------------------------------------
    00177     D3D9RenderSystem::initConfigOptions()
    00178     {
    00179         OgreGuard( "D3D9RenderSystem::initConfigOptions" );
    00180
    00181         D3D9DriverList* driverList;
    00182         D3D9Driver* driver;
    00183
    00184         ConfigOption optDevice;
    00185         ConfigOption optVideoMode;
    00186         ConfigOption optFullScreen;
    00187         ConfigOption optVSync;
    00188         ConfigOption optAA;
    00189
    00190         driverList = this->getDirect3DDrivers();
    00191
    00192         optDevice.name = "Rendering Device";
    00193         optDevice.currentValue = "";
    00194         optDevice.possibleValues.clear();
    00195         optDevice.immutable = false;
    00196
    00197         optVideoMode.name = "Video Mode";
    00198         optVideoMode.currentValue = "800 x 600 @ 32-bit colour";
    00199         optVideoMode.immutable = false;
    00200
    00201         optFullScreen.name = "Full Screen";
    00202         optFullScreen.possibleValues.push_back( "Yes" );
    00203         optFullScreen.possibleValues.push_back( "No" );
    00204         optFullScreen.currentValue = "Yes";
    00205         optFullScreen.immutable = false;
    00206
    00207         for( unsigned j=0; j < driverList->count(); j++ )
    00208         {
    00209             driver = driverList->item(j);
    00210             optDevice.possibleValues.push_back( driver->DriverDescription() );
    00211             // Make first one default
    00212             if( j==0 )
    00213                 optDevice.currentValue = driver->DriverDescription();
    00214         }
    00215
    00216         optVSync.name = "VSync";
    00217         optVSync.immutable = false;
    00218         optVSync.possibleValues.push_back( "Yes" );
    00219         optVSync.possibleValues.push_back( "No" );
    00220         optVSync.currentValue = "No";
    00221
    00222         optAA.name = "Anti aliasing";
    00223         optAA.immutable = false;
    00224         optAA.possibleValues.push_back( "None" );
    00225         optAA.currentValue = "None";
    00226
    00227         mOptions[optDevice.name] = optDevice;
    00228         mOptions[optVideoMode.name] = optVideoMode;
    00229         mOptions[optFullScreen.name] = optFullScreen;
    00230         mOptions[optVSync.name] = optVSync;
    00231         mOptions[optAA.name] = optAA;
    00232
    00233         refreshD3DSettings();
    00234
    00235         OgreUnguard();
    00236     }
    00237     //---------------------------------------------------------------------
    00238     void D3D9RenderSystem::refreshD3DSettings()
    00239     {
    00240         OgreGuard( "D3D9RenderSystem::refreshD3DSettings" );
    00241
    00242         ConfigOption* optVideoMode;
    00243         D3D9Driver* driver;
    00244         D3D9VideoMode* videoMode;
    00245
    00246         ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
    00247         if( opt != mOptions.end() )
    00248         {
    00249             for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
    00250             {
    00251                 driver = getDirect3DDrivers()->item(j);
    00252                 if( driver->DriverDescription() == opt->second.currentValue )
    00253                     break;
    00254             }
    00255
    00256             opt = mOptions.find( "Video Mode" );
    00257             optVideoMode = &opt->second;
    00258             optVideoMode->possibleValues.clear();
    00259             // get vide modes for this device
    00260             for( unsigned k=0; k < driver->getVideoModeList()->count(); k++ )
    00261             {
    00262                 videoMode = driver->getVideoModeList()->item( k );
    00263                 optVideoMode->possibleValues.push_back( videoMode->getDescription() );
    00264             }
    00265         }
    00266
    00267         OgreUnguard();
    00268     }
    00269     //---------------------------------------------------------------------
    00270     void D3D9RenderSystem::setConfigOption( const String &name, const String &value )
    00271     {
    00272         OgreGuard( "D3D9RenderSystem::setConfigOption" );
    00273
    00274         char msg[128];
    00275         sprintf( msg, "D3D9 : RenderSystem Option: %s = %s", name.c_str(), value.c_str() );
    00276         LogManager::getSingleton().logMessage( msg );
    00277
    00278         // Find option
    00279         ConfigOptionMap::iterator it = mOptions.find( name );
    00280
    00281         // Update
    00282         if( it != mOptions.end() )
    00283             it->second.currentValue = value;
    00284         else
    00285         {
    00286             sprintf( msg, "Option named '%s' does not exist.", name.c_str() );
    00287             Except( Exception::ERR_INVALIDPARAMS, msg, "D3D9RenderSystem::setConfigOption" );
    00288         }
    00289
    00290         // Refresh other options if D3DDriver changed
    00291         if( name == "Rendering Device" )
    00292             refreshD3DSettings();
    00293
    00294         if( name == "Full Screen" )
    00295         {
    00296             // Video mode is applicable
    00297             it = mOptions.find( "Video Mode" );
    00298             if (it->second.currentValue == "")
    00299                 it->second.currentValue = "800 x 600 @ 32-bit colour";
    00300         }
    00301
    00302         if( name == "Anti aliasing" )
    00303         {
    00304             if (value == "None")
    00305                 _setFSAA(D3DMULTISAMPLE_NONE, 0);
    00306             else
    00307             {
    00308                 D3DMULTISAMPLE_TYPE fsaa = D3DMULTISAMPLE_NONE;
    00309                 DWORD level = 0;
    00310
    00311                 if (value.find_first_of("NonMaskable") != -1)
    00312                 {
    00313                     fsaa = D3DMULTISAMPLE_NONMASKABLE;
    00314                     size_t pos = value.find_last_of(" ");
    00315                     String sNum = value.substr(pos + 1);
    00316                     level = StringConverter::parseInt(sNum);
    00317                     level -= 1;
    00318                 }
    00319                 else if (value.find_first_of("Level") != -1)
    00320                 {
    00321                     size_t pos = value.find_last_of(" ");
    00322                     String sNum = value.substr(pos + 1);
    00323                     fsaa = (D3DMULTISAMPLE_TYPE)StringConverter::parseInt(sNum);
    00324                 }
    00325
    00326                 _setFSAA(fsaa, level);
    00327             }
    00328         }
    00329
    00330         if( name == "VSync" )
    00331         {
    00332             if (value == "Yes")
    00333                 mVSync = true;
    00334             else
    00335                 mVSync = false;
    00336         }
    00337
    00338         if( name == "Video Mode" )
    00339         {
    00340             ConfigOption* optFSAA;
    00341             it = mOptions.find( "Anti aliasing" );
    00342             optFSAA = &it->second;
    00343             optFSAA->possibleValues.clear();
    00344             optFSAA->possibleValues.push_back("None");
    00345
    00346             it = mOptions.find("Rendering Device");
    00347             D3D9Driver *driver = getDirect3DDrivers()->item(it->second.currentValue);
    00348             if (driver)
    00349             {
    00350                 it = mOptions.find("Video Mode");
    00351                 D3D9VideoMode *videoMode = driver->getVideoModeList()->item(it->second.currentValue);
    00352                 if (videoMode)
    00353                 {
    00354                     // get non maskable FSAA for this VMODE
    00355                     DWORD numLevels = 0;
    00356                     bool bOK = this->_checkMultiSampleQuality(
    00357                         D3DMULTISAMPLE_NONMASKABLE,
    00358                         &numLevels,
    00359                         videoMode->getFormat(),
    00360                         driver->getAdapterNumber(),
    00361                         D3DDEVTYPE_HAL,
    00362                         TRUE);
    00363                     if (bOK && numLevels > 0)
    00364                     {
    00365                         for (DWORD n = 0; n < numLevels; n++)
    00366                             optFSAA->possibleValues.push_back("NonMaskable " + StringConverter::toString(n + 1));
    00367                     }
    00368
    00369                     // set maskable levels supported
    00370                     for (unsigned int n = 2; n < 17; n++)
    00371                     {
    00372                         bOK = this->_checkMultiSampleQuality(
    00373                             (D3DMULTISAMPLE_TYPE)n,
    00374                             &numLevels,
    00375                             videoMode->getFormat(),
    00376                             driver->getAdapterNumber(),
    00377                             D3DDEVTYPE_HAL,
    00378                             TRUE);
    00379                         if (bOK)
    00380                             optFSAA->possibleValues.push_back("Level " + StringConverter::toString(n));
    00381                     }
    00382                 }
    00383             }
    00384         }
    00385
    00386         OgreUnguard();
    00387     }
    00388     //---------------------------------------------------------------------
    00389     String D3D9RenderSystem::validateConfigOptions()
    00390     {
    00391         ConfigOptionMap::iterator it;
    00392
    00393         // check if video mode is selected
    00394         it = mOptions.find( "Video Mode" );
    00395         if( it->second.currentValue == "" )
    00396             return "A video mode must be selected.";
    00397
    00398         it = mOptions.find( "Rendering Device" );
    00399         bool foundDriver = false;
    00400         D3D9DriverList* driverList = getDirect3DDrivers();
    00401         for( ushort j=0; j < driverList->count(); j++ )
    00402         {
    00403             if( driverList->item(j)->DriverDescription() == it->second.currentValue )
    00404             {
    00405                 foundDriver = true;
    00406                 break;
    00407             }
    00408         }
    00409
    00410         if (!foundDriver)
    00411         {
    00412             // Just pick the first driver
    00413             setConfigOption("Rendering Device", driverList->item(0)->DriverDescription());
    00414             return "Your DirectX driver name has changed since the last time you ran OGRE; "
    00415                 "the 'Rendering Device' has been changed.";
    00416         }
    00417
    00418         it = mOptions.find( "VSync" );
    00419         if( it->second.currentValue == "Yes" )
    00420             mVSync = true;
    00421         else
    00422             mVSync = false;
    00423
    00424         return "";
    00425     }
    00426     //---------------------------------------------------------------------
    00427     ConfigOptionMap& D3D9RenderSystem::getConfigOptions()
    00428     {
    00429         // return a COPY of the current config options
    00430         return mOptions;
    00431     }
    00432     //---------------------------------------------------------------------
    00433     RenderWindow* D3D9RenderSystem::initialise( bool autoCreateWindow, const String& windowTitle )
    00434     {
    00435         RenderWindow* autoWindow = NULL;
    00436         LogManager::getSingleton().logMessage( "D3D9 : Subsystem Initialising" );
    00437
    00438         // Init using current settings
    00439         mActiveD3DDriver = NULL;
    00440         ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
    00441         for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
    00442         {
    00443             if( getDirect3DDrivers()->item(j)->DriverDescription() == opt->second.currentValue )
    00444             {
    00445                 mActiveD3DDriver = getDirect3DDrivers()->item(j);
    00446                 break;
    00447             }
    00448         }
    00449
    00450         if( !mActiveD3DDriver )
    00451             Except( Exception::ERR_INVALIDPARAMS, "Problems finding requested Direct3D driver!", "D3D9RenderSystem::initialise" );
    00452
    00453         if( autoCreateWindow )
    00454         {
    00455             bool fullScreen;
    00456             opt = mOptions.find( "Full Screen" );
    00457             if( opt == mOptions.end() )
    00458                 Exception( Exception::ERR_INTERNAL_ERROR, "Can't find full screen option!", "D3D9RenderSystem::initialise" );
    00459             fullScreen = opt->second.currentValue == "Yes";
    00460
    00461             D3D9VideoMode* videoMode = NULL;
    00462             unsigned int width, height, colourDepth;
    00463             String temp;
    00464
    00465             opt = mOptions.find( "Video Mode" );
    00466             if( opt == mOptions.end() )
    00467                 Exception( Exception::ERR_INTERNAL_ERROR, "Can't find Video Mode option!", "D3D9RenderSystem::initialise" );
    00468
    00469             for( unsigned j=0; j < mActiveD3DDriver->getVideoModeList()->count(); j++ )
    00470             {
    00471                 temp = mActiveD3DDriver->getVideoModeList()->item(j)->getDescription();
    00472                 if( temp == opt->second.currentValue )
    00473                 {
    00474                     videoMode = mActiveD3DDriver->getVideoModeList()->item(j);
    00475                     break;
    00476                 }
    00477             }
    00478
    00479             if( !videoMode )
    00480                 Except( Exception::ERR_INTERNAL_ERROR, "Can't find requested video mode.", "D3D9RenderSystem::initialise" );
    00481
    00482             width = videoMode->getWidth();
    00483             height = videoMode->getHeight();
    00484             colourDepth = videoMode->getColourDepth();
    00485
    00486             autoWindow = this->createRenderWindow( windowTitle, width, height, colourDepth, fullScreen );
    00487
    00488             // If we have 16bit depth buffer enable w-buffering.
    00489             assert( autoWindow );
    00490             if ( autoWindow->getColourDepth() == 16 )
    00491             {
    00492                 mWBuffer = true;
    00493             }
    00494             else
    00495             {
    00496                 mWBuffer = false;
    00497             }
    00498         }
    00499
    00500         LogManager::getSingleton().logMessage("***************************************");
    00501
    00502         LogManager::getSingleton().logMessage("*** D3D9 : Subsystem Initialised OK ***");
    00503         LogManager::getSingleton().logMessage("***************************************");
    00504
    00505         // call superclass method
    00506         RenderSystem::initialise( autoCreateWindow );
    00507
    00508
    00509         return autoWindow;
    00510     }
    00511     //---------------------------------------------------------------------
    00512     void D3D9RenderSystem::_setFSAA(D3DMULTISAMPLE_TYPE type, DWORD qualityLevel)
    00513     {
    00514         if (!mpD3DDevice)
    00515         {
    00516             mFSAAType = type;
    00517             mFSAAQuality = qualityLevel;
    00518         }
    00519     }
    00520     //---------------------------------------------------------------------
    00521     void D3D9RenderSystem::reinitialise()
    00522     {
    00523         LogManager::getSingleton().logMessage( "D3D9 : Reinitialising" );
    00524         this->shutdown();
    00525         this->initialise( true );
    00526     }
    00527     //---------------------------------------------------------------------
    00528     void D3D9RenderSystem::shutdown()
    00529     {
    00530         RenderSystem::shutdown();
    00531         SAFE_DELETE( mDriverList );
    00532         mActiveD3DDriver = NULL;
    00533         LogManager::getSingleton().logMessage("D3D9 : Shutting down cleanly.");
    00534     }
    00535     //---------------------------------------------------------------------
    00536     RenderWindow* D3D9RenderSystem::createRenderWindow( const String &name, unsigned int width, unsigned int height, unsigned int colourDepth,
    00537         bool fullScreen, int left, int top, bool depthBuffer, RenderWindow* parentWindowHandle)
    00538     {
    00539         static bool firstWindow = true;
    00540
    00541         OgreGuard( "D3D9RenderSystem::createRenderWindow" );
    00542
    00543         String msg;
    00544
    00545         // Make sure we don't already have a render target of the
    00546         // sam name as the one supplied
    00547         if( mRenderTargets.find( name ) != mRenderTargets.end() )
    00548         {
    00549             msg = "A render target of the same name '" + name + "' already "
    00550                 "exists.  You cannot create a new window with this name.";
    00551             Except( Exception::ERR_INTERNAL_ERROR, msg, "D3D9RenderSystem::createRenderWindow" );
    00552         }
    00553
    00554         RenderWindow* win = new D3D9RenderWindow();
    00555         if (!fullScreen && mExternalHandle)
    00556         {
    00557             D3D9RenderWindow *pWin32Window = (D3D9RenderWindow *)win;
    00558             pWin32Window->SetExternalWindowHandle(mExternalHandle);
    00559         }
    00560
    00561         win->create( name, width, height, colourDepth, fullScreen,
    00562                 left, top, depthBuffer, &mhInstance, mActiveD3DDriver,
    00563                 parentWindowHandle, mFSAAType, mFSAAQuality, mVSync );
    00564
    00565         attachRenderTarget( *win );
    00566
    00567         // If this is the first window, get the D3D device and create the texture manager
    00568         if( firstWindow )
    00569         {
    00570             win->getCustomAttribute( "D3DDEVICE", &mpD3DDevice );
    00571
    00572             // Create the texture manager for use by others
    00573             mTextureManager = new D3D9TextureManager( mpD3DDevice );
    00574             // Also create hardware buffer manager
    00575             mHardwareBufferManager = new D3D9HardwareBufferManager(mpD3DDevice);
    00576
    00577             // Create the GPU program manager
    00578             mGpuProgramManager = new D3D9GpuProgramManager(mpD3DDevice);
    00579             // create & register HLSL factory
    00580             //mHLSLProgramFactory = new D3D9HLSLProgramFactory();
    00581             //HighLevelGpuProgramManager::getSingleton().addFactory(mHLSLProgramFactory);
    00582             mGpuProgramManager->_pushSyntaxCode("hlsl");
    00583
    00584
    00585             // Initialise the capabilities structures
    00586             initCapabilities();
    00587
    00588
    00589             firstWindow = false;
    00590
    00591         }
    00592
    00593         OgreUnguardRet( win );
    00594     }
    00595     //---------------------------------------------------------------------
    00596     void D3D9RenderSystem::initCapabilities(void)
    00597     {
    00598         // get caps
    00599         mpD3DDevice->GetDeviceCaps( &mCaps );
    00600
    00601         // Check for hardware stencil support
    00602         LPDIRECT3DSURFACE9 pSurf;
    00603         D3DSURFACE_DESC surfDesc;
    00604         mpD3DDevice->GetDepthStencilSurface(&pSurf);
    00605         pSurf->GetDesc(&surfDesc);
    00606         pSurf->Release();
    00607
    00608         if (surfDesc.Format == D3DFMT_D24S8 || surfDesc.Format == D3DFMT_D24X8)
    00609         {
    00610             mCapabilities->setCapability(RSC_HWSTENCIL);
    00611             // Actually, it's always 8-bit
    00612             mCapabilities->setStencilBufferBitDepth(8);
    00613
    00614         }
    00615
    00616         // Set number of texture units
    00617         mCapabilities->setNumTextureUnits(mCaps.MaxSimultaneousTextures);
    00618         // Anisotropy?
    00619         if (mCaps.MaxAnisotropy > 1)
    00620             mCapabilities->setCapability(RSC_ANISOTROPY);
    00621         // Automatic mipmap generation?
    00622         if (mCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
    00623             mCapabilities->setCapability(RSC_AUTOMIPMAP);
    00624         // Blending between stages supported
    00625         mCapabilities->setCapability(RSC_BLENDING);
    00626         // Dot 3
    00627         if (mCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
    00628             mCapabilities->setCapability(RSC_DOT3);
    00629         // Cube map
    00630         if (mCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
    00631             mCapabilities->setCapability(RSC_CUBEMAPPING);
    00632
    00633         // We always support compression, D3DX will decompress if device does not support
    00634         mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
    00635         mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
    00636
    00637         // We always support VBOs
    00638         mCapabilities->setCapability(RSC_VBO);
    00639
    00640         // Scissor test
    00641         if (mCaps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST)
    00642             mCapabilities->setCapability(RSC_SCISSOR_TEST);
    00643
    00644         // Two-sided stencil
    00645         if (mCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)
    00646             mCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
    00647
    00648         // stencil wrap
    00649         if ((mCaps.StencilCaps & D3DSTENCILCAPS_INCR) &&
    00650             (mCaps.StencilCaps & D3DSTENCILCAPS_DECR))
    00651             mCapabilities->setCapability(RSC_STENCIL_WRAP);
    00652
    00653         // Check for hardware occlusion support
    00654         if ( ( mpD3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION,  NULL ) ) == D3D_OK )
    00655         {
    00656             mCapabilities->setCapability(RSC_HWOCCLUSION);
    00657         }
    00658         convertVertexShaderCaps();
    00659         convertPixelShaderCaps();
    00660
    00661         // User clip planes
    00662         if (mCaps.MaxUserClipPlanes > 0)
    00663         {
    00664             mCapabilities->setCapability(RSC_USER_CLIP_PLANES);
    00665         }
    00666
    00667         // UBYTE4 type?
    00668         if (mCaps.DeclTypes & D3DDTCAPS_UBYTE4)
    00669         {
    00670             mCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
    00671         }
    00672
    00673         // Infinite projection?
    00674         // We have no capability for this, so we have to base this on our
    00675         // experience and reports from users
    00676         // Non-vertex program capable hardware does not appear to support it
    00677         if (mCapabilities->hasCapability(RSC_VERTEX_PROGRAM))
    00678         {
    00679             // GeForce4 Ti (and presumably GeForce3) does not
    00680             // render infinite projection properly, even though it does in GL
    00681             // So exclude all cards prior to the FX range from doing infinite
    00682             D3DADAPTER_IDENTIFIER9 adapterID = mActiveD3DDriver->getAdapterIdentifier();
    00683             if (adapterID.VendorId != 0x10DE || // not nVidia
    00684                 adapterID.DeviceId >= 0x0301) // or GeForce FX or above
    00685             {
    00686                 mCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
    00687             }
    00688
    00689         }
    00690
    00691
    00692         mCapabilities->log(LogManager::getSingleton().getDefaultLog());
    00693     }
    00694     //---------------------------------------------------------------------
    00695     void D3D9RenderSystem::convertVertexShaderCaps(void)
    00696     {
    00697         ushort major, minor;
    00698         major = static_cast<ushort>((mCaps.VertexShaderVersion & 0x0000FF00) >> 8);
    00699         minor = static_cast<ushort>(mCaps.VertexShaderVersion & 0x000000FF);
    00700
    00701         // Populate max version & params
    00702         switch (major)
    00703         {
    00704         case 1:
    00705             mCapabilities->setMaxVertexProgramVersion("vs_1_1");
    00706             // No boolean params allowed
    00707             mCapabilities->setVertexProgramConstantBoolCount(0);
    00708             // No integer params allowed
    00709             mCapabilities->setVertexProgramConstantIntCount(0);
    00710             // float params, always 4D
    00711             mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
    00712
    00713             break;
    00714         case 2:
    00715             if (minor > 0)
    00716             {
    00717                 mCapabilities->setMaxVertexProgramVersion("vs_2_x");
    00718             }
    00719             else
    00720             {
    00721                 mCapabilities->setMaxVertexProgramVersion("vs_2_0");
    00722             }
    00723             // 16 boolean params allowed
    00724             mCapabilities->setVertexProgramConstantBoolCount(16);
    00725             // 16 integer params allowed, 4D
    00726             mCapabilities->setVertexProgramConstantIntCount(16);
    00727             // float params, always 4D
    00728             mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
    00729             break;
    00730         case 3:
    00731             mCapabilities->setMaxVertexProgramVersion("vs_3_0");
    00732             // 16 boolean params allowed
    00733             mCapabilities->setVertexProgramConstantBoolCount(16);
    00734             // 16 integer params allowed, 4D
    00735             mCapabilities->setVertexProgramConstantIntCount(16);
    00736             // float params, always 4D
    00737             mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
    00738             break;
    00739         default:
    00740             mCapabilities->setMaxVertexProgramVersion("");
    00741             break;
    00742         }
    00743
    00744         // populate syntax codes in program manager (no breaks in this one so it falls through)
    00745         switch(major)
    00746         {
    00747         case 3:
    00748             mGpuProgramManager->_pushSyntaxCode("vs_3_0");
    00749         case 2:
    00750             if (major > 2 || minor > 0)
    00751                 mGpuProgramManager->_pushSyntaxCode("vs_2_x");
    00752
    00753             mGpuProgramManager->_pushSyntaxCode("vs_2_0");
    00754         case 1:
    00755             mGpuProgramManager->_pushSyntaxCode("vs_1_1");
    00756             mCapabilities->setCapability(RSC_VERTEX_PROGRAM);
    00757         }
    00758     }
    00759     //---------------------------------------------------------------------
    00760     void D3D9RenderSystem::convertPixelShaderCaps(void)
    00761     {
    00762         ushort major, minor;
    00763         major = static_cast<ushort>((mCaps.PixelShaderVersion & 0x0000FF00) >> 8);
    00764         minor = static_cast<ushort>(mCaps.PixelShaderVersion & 0x000000FF);
    00765         switch (major)
    00766         {
    00767         case 1:
    00768             switch(minor)
    00769             {
    00770             case 1:
    00771                 mCapabilities->setMaxFragmentProgramVersion("ps_1_1");
    00772                 break;
    00773             case 2:
    00774                 mCapabilities->setMaxFragmentProgramVersion("ps_1_2");
    00775                 break;
    00776             case 3:
    00777                 mCapabilities->setMaxFragmentProgramVersion("ps_1_3");
    00778                 break;
    00779             case 4:
    00780                 mCapabilities->setMaxFragmentProgramVersion("ps_1_4");
    00781                 break;
    00782             }
    00783             break;
    00784             // no boolean params allowed
    00785             mCapabilities->setFragmentProgramConstantBoolCount(0);
    00786             // no integer params allowed
    00787             mCapabilities->setFragmentProgramConstantIntCount(0);
    00788             // float params, always 4D
    00789             // NB in ps_1_x these are actually stored as fixed point values,
    00790             // but they are entered as floats
    00791             mCapabilities->setFragmentProgramConstantFloatCount(8);
    00792         case 2:
    00793             if (minor > 0)
    00794             {
    00795                 mCapabilities->setMaxFragmentProgramVersion("ps_2_x");
    00796                 // 16 boolean params allowed
    00797                 mCapabilities->setFragmentProgramConstantBoolCount(16);
    00798                 // 16 integer params allowed, 4D
    00799                 mCapabilities->setFragmentProgramConstantIntCount(16);
    00800                 // float params, always 4D
    00801                 mCapabilities->setFragmentProgramConstantFloatCount(224);
    00802             }
    00803             else
    00804             {
    00805                 mCapabilities->setMaxFragmentProgramVersion("ps_2_0");
    00806                 // no boolean params allowed
    00807                 mCapabilities->setFragmentProgramConstantBoolCount(0);
    00808                 // no integer params allowed
    00809                 mCapabilities->setFragmentProgramConstantIntCount(0);
    00810                 // float params, always 4D
    00811                 mCapabilities->setFragmentProgramConstantFloatCount(32);
    00812             }
    00813             break;
    00814         case 3:
    00815             if (minor > 0)
    00816             {
    00817                 mCapabilities->setMaxFragmentProgramVersion("ps_3_x");
    00818             }
    00819             else
    00820             {
    00821                 mCapabilities->setMaxFragmentProgramVersion("ps_3_0");
    00822             }
    00823             // 16 boolean params allowed
    00824             mCapabilities->setFragmentProgramConstantBoolCount(16);
    00825             // 16 integer params allowed, 4D
    00826             mCapabilities->setFragmentProgramConstantIntCount(16);
    00827             // float params, always 4D
    00828             mCapabilities->setFragmentProgramConstantFloatCount(224);
    00829             break;
    00830         default:
    00831             mCapabilities->setMaxFragmentProgramVersion("");
    00832             break;
    00833         }
    00834
    00835         // populate syntax codes in program manager (no breaks in this one so it falls through)
    00836         switch(major)
    00837         {
    00838         case 3:
    00839             if (minor > 0)
    00840                 mGpuProgramManager->_pushSyntaxCode("ps_3_x");
    00841
    00842             mGpuProgramManager->_pushSyntaxCode("ps_3_0");
    00843         case 2:
    00844             if (major > 2 || minor > 0)
    00845                 mGpuProgramManager->_pushSyntaxCode("ps_2_x");
    00846
    00847             mGpuProgramManager->_pushSyntaxCode("ps_2_0");
    00848         case 1:
    00849             if (major > 1 || minor >= 4)
    00850                 mGpuProgramManager->_pushSyntaxCode("ps_1_4");
    00851             if (major > 1 || minor >= 3)
    00852                 mGpuProgramManager->_pushSyntaxCode("ps_1_3");
    00853             if (major > 1 || minor >= 2)
    00854                 mGpuProgramManager->_pushSyntaxCode("ps_1_2");
    00855
    00856             mGpuProgramManager->_pushSyntaxCode("ps_1_1");
    00857             mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
    00858         }
    00859     }
    00860     //---------------------------------------------------------------------
    00861     RenderTexture * D3D9RenderSystem::createRenderTexture( const String & name, unsigned int width, unsigned int height )
    00862     {
    00863         RenderTexture *rt = new D3D9RenderTexture( name, width, height );
    00864         attachRenderTarget( *rt );
    00865         return rt;
    00866     }
    00867     //---------------------------------------------------------------------
    00868     void D3D9RenderSystem::destroyRenderWindow( RenderWindow* pWin )
    00869     {
    00870         // Find it to remove from list
    00871         RenderTargetMap::iterator i = mRenderTargets.begin();
    00872
    00873         while( i->second != pWin && i != mRenderTargets.end() )
    00874         {
    00875             if( i->second == pWin )
    00876             {
    00877                 mRenderTargets.erase(i);
    00878                 delete pWin;
    00879                 break;
    00880             }
    00881         }
    00882     }
    00883     //---------------------------------------------------------------------
    00884     String D3D9RenderSystem::getErrorDescription( long errorNumber ) const
    00885     {
    00886         const String errMsg = DXGetErrorDescription9( errorNumber );
    00887         return errMsg;
    00888     }
    00889     //---------------------------------------------------------------------
    00890     void D3D9RenderSystem::convertColourValue( const ColourValue& colour, unsigned long* pDest )
    00891     {
    00892         *pDest = colour.getAsLongARGB();
    00893     }
    00894     //---------------------------------------------------------------------
    00895     void D3D9RenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane,
    00896         Real farPlane, Matrix4& dest, bool forGpuProgram)
    00897     {
    00898         Radian theta ( fovy * 0.5 );
    00899         Real h = 1 / Math::Tan(theta);
    00900         Real w = h / aspect;
    00901         Real q, qn;
    00902         if (farPlane == 0)
    00903         {
    00904             q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
    00905             qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
    00906         }
    00907         else
    00908         {
    00909             q = farPlane / ( farPlane - nearPlane );
    00910             qn = -q * nearPlane;
    00911         }
    00912
    00913         dest = Matrix4::ZERO;
    00914         dest[0][0] = w;
    00915         dest[1][1] = h;
    00916
    00917         if (forGpuProgram)
    00918         {
    00919             dest[2][2] = -q;
    00920             dest[3][2] = -1.0f;
    00921         }
    00922         else
    00923         {
    00924             dest[2][2] = q;
    00925             dest[3][2] = 1.0f;
    00926         }
    00927
    00928         dest[2][3] = qn;
    00929     }
    00930     //---------------------------------------------------------------------
    00931     void D3D9RenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, Real farPlane,
    00932         Matrix4& dest, bool forGpuProgram )
    00933     {
    00934         Radian thetaY (fovy / 2.0f);
    00935         Real tanThetaY = Math::Tan(thetaY);
    00936
    00937         //Real thetaX = thetaY * aspect;
    00938         Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
    00939         Real half_w = tanThetaX * nearPlane;
    00940         Real half_h = tanThetaY * nearPlane;
    00941         Real iw = 1.0 / half_w;
    00942         Real ih = 1.0 / half_h;
    00943         Real q;
    00944         if (farPlane == 0)
    00945         {
    00946             q = 0;
    00947         }
    00948         else
    00949         {
    00950             q = 1.0 / (farPlane - nearPlane);
    00951         }
    00952
    00953         dest = Matrix4::ZERO;
    00954         dest[0][0] = iw;
    00955         dest[1][1] = ih;
    00956         dest[2][2] = q;
    00957         dest[2][3] = -nearPlane / (farPlane - nearPlane);
    00958         dest[3][3] = 1;
    00959
    00960         if (forGpuProgram)
    00961         {
    00962             dest[2][2] = -dest[2][2];
    00963         }
    00964     }
    00965     //---------------------------------------------------------------------
    00966     D3D9RenderSystem::ResizeRepositionWindow(HWND wich)
    00967     {
    00968         for (RenderTargetMap::iterator it = mRenderTargets.begin(); it != mRenderTargets.end(); ++it)
    00969         {
    00970             if (it->second->isActive())
    00971             {
    00972                 D3D9RenderWindow *pWin32Window = (D3D9RenderWindow *)it->second;
    00973                 if (pWin32Window->getWindowHandle() == wich)
    00974                 {
    00975                     pWin32Window->WindowMovedOrResized();
    00976                     break;
    00977                 }
    00978             }
    00979         }
    00980     }
    00981     //---------------------------------------------------------------------
    00982     void D3D9RenderSystem::setAmbientLight( float r, float g, float b )
    00983     {
    00984         HRESULT hr = __SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( r, g, b, 1.0f ) );
    00985         if( FAILED( hr ) )
    00986             Except( hr, "Failed to set render stat D3DRS_AMBIENT", "D3D9RenderSystem::setAmbientLight" );
    00987     }
    00988     //---------------------------------------------------------------------
    00989     void D3D9RenderSystem::_useLights(const LightList& lights, unsigned short limit)
    00990     {
    00991         LightList::const_iterator i, iend;
    00992         iend = lights.end();
    00993         unsigned short num = 0;
    00994         for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
    00995         {
    00996             setD3D9Light(num, *i);
    00997         }
    00998         // Disable extra lights
    00999         for (; num < mCurrentLights; ++num)
    01000         {
    01001             setD3D9Light(num, NULL);
    01002         }
    01003         mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
    01004
    01005     }
    01006     //---------------------------------------------------------------------
    01007     void D3D9RenderSystem::setShadingType( ShadeOptions so )
    01008     {
    01009         HRESULT hr = __SetRenderState( D3DRS_SHADEMODE, D3D9Mappings::get(so) );
    01010         if( FAILED( hr ) )
    01011             Except( hr, "Failed to set render stat D3DRS_SHADEMODE", "D3D9RenderSystem::setShadingType" );
    01012     }
    01013     //---------------------------------------------------------------------
    01014     void D3D9RenderSystem::setLightingEnabled( bool enabled )
    01015     {
    01016         HRESULT hr;
    01017         if( FAILED( hr = __SetRenderState( D3DRS_LIGHTING, enabled ) ) )
    01018             Except( hr, "Failed to set render state D3DRS_LIGHTING", "D3D9RenderSystem::setLightingEnabled" );
    01019     }
    01020     //---------------------------------------------------------------------
    01021     void D3D9RenderSystem::setD3D9Light( size_t index, Light* lt )
    01022     {
    01023         HRESULT hr;
    01024
    01025         D3DLIGHT9 d3dLight;
    01026         ZeroMemory( &d3dLight, sizeof(d3dLight) );
    01027
    01028         if (!lt)
    01029         {
    01030             if( FAILED( hr = mpD3DDevice->LightEnable( index, FALSE) ) )
    01031                 Except( hr, "Unable to disable light", "D3D9RenderSystem::setD3D9Light" );
    01032         }
    01033         else
    01034         {
    01035             switch( lt->getType() )
    01036             {
    01037             case Light::LT_POINT:
    01038                 d3dLight.Type = D3DLIGHT_POINT;
    01039                 break;
    01040
    01041             case Light::LT_DIRECTIONAL:
    01042                 d3dLight.Type = D3DLIGHT_DIRECTIONAL;
    01043                 break;
    01044
    01045             case Light::LT_SPOTLIGHT:
    01046                 d3dLight.Type = D3DLIGHT_SPOT;
    01047                 d3dLight.Falloff = lt->getSpotlightFalloff();
    01048                 d3dLight.Theta = lt->getSpotlightInnerAngle().valueRadians();
    01049                 d3dLight.Phi = lt->getSpotlightOuterAngle().valueRadians();
    01050                 break;
    01051             }
    01052
    01053             ColourValue col;
    01054             col = lt->getDiffuseColour();
    01055             d3dLight.Diffuse = D3DXCOLOR( col.r, col.g, col.b, col.a );
    01056
    01057             col = lt->getSpecularColour();
    01058             d3dLight.Specular = D3DXCOLOR( col.r, col.g, col.b, col.a );
    01059
    01060             Vector3 vec;
    01061             if( lt->getType() != Light::LT_DIRECTIONAL )
    01062             {
    01063                 vec = lt->getDerivedPosition();
    01064                 d3dLight.Position = D3DXVECTOR3( vec.x, vec.y, vec.z );
    01065             }
    01066             if( lt->getType() != Light::LT_POINT )
    01067             {
    01068                 vec = lt->getDerivedDirection();
    01069                 d3dLight.Direction = D3DXVECTOR3( vec.x, vec.y, vec.z );
    01070             }
    01071
    01072             d3dLight.Range = lt->getAttenuationRange();
    01073             d3dLight.Attenuation0 = lt->getAttenuationConstant();
    01074             d3dLight.Attenuation1 = lt->getAttenuationLinear();
    01075             d3dLight.Attenuation2 = lt->getAttenuationQuadric();
    01076
    01077             if( FAILED( hr = mpD3DDevice->SetLight( index, &d3dLight ) ) )
    01078                 Except( hr, "Unable to set light details", "D3D9RenderSystem::setD3D9Light" );
    01079
    01080             if( FAILED( hr = mpD3DDevice->LightEnable( index, TRUE ) ) )
    01081                 Except( hr, "Unable to enable light", "D3D9RenderSystem::setD3D9Light" );
    01082         }
    01083
    01084
    01085     }
    01086     //---------------------------------------------------------------------
    01087     void D3D9RenderSystem::_setViewMatrix( const Matrix4 &m )
    01088     {
    01089         // save latest view matrix
    01090         mViewMatrix = m;
    01091         mViewMatrix[2][0] = -mViewMatrix[2][0];
    01092         mViewMatrix[2][1] = -mViewMatrix[2][1];
    01093         mViewMatrix[2][2] = -mViewMatrix[2][2];
    01094         mViewMatrix[2][3] = -mViewMatrix[2][3];
    01095
    01096         D3DXMATRIX d3dmat = D3D9Mappings::makeD3DXMatrix( mViewMatrix );
    01097
    01098         HRESULT hr;
    01099         if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_VIEW, &d3dmat ) ) )
    01100             Except( hr, "Cannot set D3D9 view matrix", "D3D9RenderSystem::_setViewMatrix" );
    01101     }
    01102     //---------------------------------------------------------------------
    01103     void D3D9RenderSystem::_setProjectionMatrix( const Matrix4 &m )
    01104     {
    01105         D3DXMATRIX d3dMat = D3D9Mappings::makeD3DXMatrix( m );
    01106
    01107         if( mActiveRenderTarget->requiresTextureFlipping() )
    01108             d3dMat._22 = - d3dMat._22;
    01109
    01110         HRESULT hr;
    01111         if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_PROJECTION, &d3dMat ) ) )
    01112             Except( hr, "Cannot set D3D9 projection matrix", "D3D9RenderSystem::_setProjectionMatrix" );
    01113     }
    01114     //---------------------------------------------------------------------
    01115     void D3D9RenderSystem::_setWorldMatrix( const Matrix4 &m )
    01116     {
    01117         D3DXMATRIX d3dMat = D3D9Mappings::makeD3DXMatrix( m );
    01118
    01119         HRESULT hr;
    01120         if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_WORLD, &d3dMat ) ) )
    01121             Except( hr, "Cannot set D3D9 world matrix", "D3D9RenderSystem::_setWorldMatrix" );
    01122     }
    01123     //---------------------------------------------------------------------
    01124     void D3D9RenderSystem::_setSurfaceParams( const ColourValue &ambient, const ColourValue &diffuse,
    01125         const ColourValue &specular, const ColourValue &emissive, Real shininess )
    01126     {
    01127         // Remember last call
    01128         static ColourValue lastAmbient = ColourValue::Black;
    01129         static ColourValue lastDiffuse = ColourValue::Black;
    01130         static ColourValue lastSpecular = ColourValue::Black;
    01131         static ColourValue lastEmissive = ColourValue::Black;
    01132         static Real lastShininess = 0.0;
    01133
    01134         // Only update if changed
    01135         if( ambient != lastAmbient || diffuse != lastDiffuse ||
    01136             specular != lastSpecular || emissive != lastEmissive ||
    01137             shininess != lastShininess )
    01138         {
    01139             D3DMATERIAL9 material;
    01140             material.Diffuse = D3DXCOLOR( diffuse.r, diffuse.g, diffuse.b, diffuse.a );
    01141             material.Ambient = D3DXCOLOR( ambient.r, ambient.g, ambient.b, ambient.a );
    01142             material.Specular = D3DXCOLOR( specular.r, specular.g, specular.b, specular.a );
    01143             material.Emissive = D3DXCOLOR( emissive.r, emissive.g, emissive.b, emissive.a );
    01144             material.Power = shininess;
    01145
    01146             HRESULT hr = mpD3DDevice->SetMaterial( &material );
    01147             if( FAILED( hr ) )
    01148                 Except( hr, "Error setting D3D material", "D3D9RenderSystem::_setSurfaceParams" );
    01149
    01150             // Remember the details
    01151             lastAmbient = ambient;
    01152             lastDiffuse = diffuse;
    01153             lastSpecular = specular;
    01154             lastEmissive = emissive;
    01155             lastShininess = shininess;
    01156         }
    01157     }
    01158     //---------------------------------------------------------------------
    01159     void D3D9RenderSystem::_setTexture( size_t stage, bool enabled, const String &texname )
    01160     {
    01161         HRESULT hr;
    01162         D3D9Texture *dt = (D3D9Texture *)TextureManager::getSingleton().getByName(texname);
    01163         if (enabled && dt)
    01164         {
    01165             IDirect3DBaseTexture9 *pTex = dt->getTexture();
    01166             if (mTexStageDesc[stage].pTex != pTex)
    01167             {
    01168                 hr = mpD3DDevice->SetTexture(stage, pTex);
    01169                 if( hr != S_OK )
    01170                 {
    01171                     String str = "Unable to set texture '" + texname + "' in D3D9";
    01172                     Except( hr, str, "D3D9RenderSystem::_setTexture" );
    01173                 }
    01174
    01175                 // set stage desc.
    01176                 mTexStageDesc[stage].pTex = pTex;
    01177                 mTexStageDesc[stage].texType = D3D9Mappings::get(dt->getTextureType());
    01178             }
    01179         }
    01180         else
    01181         {
    01182             if (mTexStageDesc[stage].pTex != 0)
    01183             {
    01184                 hr = mpD3DDevice->SetTexture(stage, 0);
    01185                 if( hr != S_OK )
    01186                 {
    01187                     String str = "Unable to disable texture '" + texname + "' in D3D9";
    01188                     Except( hr, str, "D3D9RenderSystem::_setTexture" );
    01189                 }
    01190             }
    01191
    01192             hr = this->__SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE);
    01193             if( hr != S_OK )
    01194             {
    01195                 String str = "Unable to disable texture '" + texname + "' in D3D9";
    01196                 Except( hr, str, "D3D9RenderSystem::_setTexture" );
    01197             }
    01198
    01199             // set stage desc. to defaults
    01200             mTexStageDesc[stage].pTex = 0;
    01201             mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
    01202             mTexStageDesc[stage].coordIndex = 0;
    01203             mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
    01204         }
    01205     }
    01206     //---------------------------------------------------------------------
    01207     void D3D9RenderSystem::_setTextureCoordSet( size_t stage, size_t index )
    01208     {
    01209         HRESULT hr;
    01210         // Record settings
    01211         mTexStageDesc[stage].coordIndex = index;
    01212
    01213         hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(mTexStageDesc[stage].autoTexCoordType, mCaps) | index );
    01214         if( FAILED( hr ) )
    01215             Except( hr, "Unable to set texture coord. set index", "D3D8RenderSystem::_setTextureCoordSet" );
    01216     }
    01217     //---------------------------------------------------------------------
    01218     void D3D9RenderSystem::_setTextureCoordCalculation( size_t stage, TexCoordCalcMethod m,
    01219         const Frustum* frustum)
    01220     {
    01221         HRESULT hr;
    01222         // record the stage state
    01223         mTexStageDesc[stage].autoTexCoordType = m;
    01224         mTexStageDesc[stage].frustum = frustum;
    01225
    01226         hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(m, mCaps) | mTexStageDesc[stage].coordIndex );
    01227         if(FAILED(hr))
    01228             Except( hr, "Unable to set texture auto tex.coord. generation mode", "D3D8RenderSystem::_setTextureCoordCalculation" );
    01229     }
    01230     //---------------------------------------------------------------------
    01231     void D3D9RenderSystem::_setTextureMatrix( size_t stage, const Matrix4& xForm )
    01232     {
    01233         HRESULT hr;
    01234         D3DXMATRIX d3dMatId; // ident. matrix in D3DX format
    01235         D3DXMATRIX d3dMat; // the matrix we'll maybe apply
    01236         Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format
    01237         // make the ident. matrix in D3D format
    01238         D3DXMatrixIdentity(&d3dMatId);
    01239
    01240         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP)
    01241         {
    01242             if (mCaps.VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP)
    01243             {
    01245                 Matrix4 ogreMatEnvMap = Matrix4::IDENTITY;
    01246                 // set env_map values
    01247                 ogreMatEnvMap[1][1] = -1.0f;
    01248                 // concatenate with the xForm
    01249                 newMat = newMat.concatenate(ogreMatEnvMap);
    01250             }
    01251             else
    01252             {
    01253                 /* If envmap is applied, but device doesn't support spheremap,
    01254                 then we have to use texture transform to make the camera space normal
    01255                 reference the envmap properly. This isn't exactly the same as spheremap
    01256                 (it looks nasty on flat areas because the camera space normals are the same)
    01257                 but it's the best approximation we have in the absence of a proper spheremap */
    01258                 // concatenate with the xForm
    01259                 newMat = newMat.concatenate(Matrix4::CLIPSPACE2DTOIMAGESPACE);
    01260             }
    01261         }
    01262
    01263         // If this is a cubic reflection, we need to modify using the view matrix
    01264         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION)
    01265         {
    01266             D3DXMATRIX viewMatrix;
    01267
    01268             // Get view matrix
    01269             mpD3DDevice->GetTransform(D3DTS_VIEW, &viewMatrix);
    01270             // Get transposed 3x3, ie since D3D is transposed just copy
    01271             // We want to transpose since that will invert an orthonormal matrix ie rotation
    01272             Matrix4 ogreViewTransposed;
    01273             ogreViewTransposed[0][0] = viewMatrix.m[0][0];
    01274             ogreViewTransposed[0][1] = viewMatrix.m[0][1];
    01275             ogreViewTransposed[0][2] = viewMatrix.m[0][2];
    01276             ogreViewTransposed[0][3] = 0.0f;
    01277
    01278             ogreViewTransposed[1][0] = viewMatrix.m[1][0];
    01279             ogreViewTransposed[1][1] = viewMatrix.m[1][1];
    01280             ogreViewTransposed[1][2] = viewMatrix.m[1][2];
    01281             ogreViewTransposed[1][3] = 0.0f;
    01282
    01283             ogreViewTransposed[2][0] = viewMatrix.m[2][0];
    01284             ogreViewTransposed[2][1] = viewMatrix.m[2][1];
    01285             ogreViewTransposed[2][2] = viewMatrix.m[2][2];
    01286             ogreViewTransposed[2][3] = 0.0f;
    01287
    01288             ogreViewTransposed[3][0] = 0.0f;
    01289             ogreViewTransposed[3][1] = 0.0f;
    01290             ogreViewTransposed[3][2] = 0.0f;
    01291             ogreViewTransposed[3][3] = 1.0f;
    01292
    01293             newMat = newMat.concatenate(ogreViewTransposed);
    01294         }
    01295
    01296         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
    01297         {
    01298             // Derive camera space to projector space transform
    01299             // To do this, we need to undo the camera view matrix, then
    01300             // apply the projector view & projection matrices
    01301             newMat = mViewMatrix.inverse() * newMat;
    01302             newMat = mTexStageDesc[stage].frustum->getViewMatrix() * newMat;
    01303             newMat = mTexStageDesc[stage].frustum->getProjectionMatrix() * newMat;
    01304             if (mTexStageDesc[stage].frustum->getProjectionType() == PT_PERSPECTIVE)
    01305             {
    01306                 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * newMat;
    01307             }
    01308             else
    01309             {
    01310                 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO * newMat;
    01311             }
    01312
    01313         }
    01314
    01315         // convert our matrix to D3D format
    01316         d3dMat = D3D9Mappings::makeD3DXMatrix(newMat);
    01317
    01318         // need this if texture is a cube map, to invert D3D's z coord
    01319         if (mTexStageDesc[stage].autoTexCoordType != TEXCALC_NONE)
    01320         {
    01321             d3dMat._13 = -d3dMat._13;
    01322             d3dMat._23 = -d3dMat._23;
    01323             d3dMat._33 = -d3dMat._33;
    01324             d3dMat._43 = -d3dMat._43;
    01325         }
    01326
    01327         // set the matrix if it's not the identity
    01328         if (d3dMat != d3dMatId)
    01329         {
    01330             // tell D3D the dimension of tex. coord.
    01331             int texCoordDim;
    01332             if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
    01333             {
    01334                 texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT3;
    01335             }
    01336             else
    01337             {
    01338                 switch (mTexStageDesc[stage].texType)
    01339                 {
    01340                 case D3D9Mappings::D3D_TEX_TYPE_NORMAL:
    01341                     texCoordDim = D3DTTFF_COUNT2;
    01342                     break;
    01343                 case D3D9Mappings::D3D_TEX_TYPE_CUBE:
    01344                 case D3D9Mappings::D3D_TEX_TYPE_VOLUME:
    01345                     texCoordDim = D3DTTFF_COUNT3;
    01346                 }
    01347             }
    01348
    01349             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim );
    01350             if (FAILED(hr))
    01351                 Except( hr, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" );
    01352
    01353             hr = mpD3DDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
    01354             if (FAILED(hr))
    01355                 Except( hr, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
    01356         }
    01357         else
    01358         {
    01359             // disable all of this
    01360             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
    01361             if( FAILED( hr ) )
    01362                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
    01363
    01364             // set the identity matrix
    01365             D3DXMatrixIdentity( &d3dMat );
    01366             hr = mpD3DDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
    01367             if( FAILED( hr ) )
    01368                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
    01369         }
    01370     }
    01371     //---------------------------------------------------------------------
    01372     void D3D9RenderSystem::_setTextureAddressingMode( size_t stage, TextureUnitState::TextureAddressingMode tam )
    01373     {
    01374         HRESULT hr;
    01375         if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSU, D3D9Mappings::get(tam) ) ) )
    01376             Except( hr, "Failed to set texture addressing mode for U", "D3D9RenderSystem::_setTextureAddressingMode" );
    01377         if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSV, D3D9Mappings::get(tam) ) ) )
    01378             Except( hr, "Failed to set texture addressing mode for V", "D3D9RenderSystem::_setTextureAddressingMode" );
    01379         if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSW, D3D9Mappings::get(tam) ) ) )
    01380             Except( hr, "Failed to set texture addressing mode for W", "D3D9RenderSystem::_setTextureAddressingMode" );
    01381     }
    01382     //---------------------------------------------------------------------
    01383     void D3D9RenderSystem::_setTextureBlendMode( size_t stage, const LayerBlendModeEx& bm )
    01384     {
    01385         HRESULT hr = S_OK;
    01386         D3DTEXTURESTAGESTATETYPE tss;
    01387         D3DCOLOR manualD3D;
    01388
    01389         // choose type of blend.
    01390         if( bm.blendType == LBT_COLOUR )
    01391             tss = D3DTSS_COLOROP;
    01392         else if( bm.blendType == LBT_ALPHA )
    01393             tss = D3DTSS_ALPHAOP;
    01394         // set manual factor if required by operation
    01395         if (bm.operation == LBX_BLEND_MANUAL)
    01396         {
    01397             hr = __SetRenderState( D3DRS_TEXTUREFACTOR, D3DXCOLOR(0.0, 0.0, 0.0,  bm.factor) );
    01398             if (FAILED(hr))
    01399                 Except( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
    01400         }
    01401         // set operation
    01402         hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.operation, mCaps) );
    01403         if (FAILED(hr))
    01404             Except( hr, "Failed to set operation", "D3D9RenderSystem::_setTextureBlendMode" );
    01405
    01406         // choose source 1
    01407         if( bm.blendType == LBT_COLOUR )
    01408         {
    01409             tss = D3DTSS_COLORARG1;
    01410             manualD3D = D3DXCOLOR( bm.colourArg1.r, bm.colourArg1.g, bm.colourArg1.b, bm.colourArg1.a );
    01411         }
    01412         else if( bm.blendType == LBT_ALPHA )
    01413         {
    01414             tss = D3DTSS_ALPHAARG1;
    01415             manualD3D = D3DXCOLOR( 0.0, 0.0, 0.0, bm.alphaArg1 );
    01416         }
    01417         // Set manual factor if required
    01418         if (bm.source1 == LBS_MANUAL)
    01419         {
    01420             hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
    01421             if (FAILED(hr))
    01422                 Except( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
    01423         }
    01424         // set source 1
    01425         hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.source1) );
    01426         if (FAILED(hr))
    01427             Except( hr, "Failed to set source1", "D3D9RenderSystem::_setTextureBlendMode" );
    01428
    01429         // choose source 2
    01430         if( bm.blendType == LBT_COLOUR )
    01431         {
    01432             tss = D3DTSS_COLORARG2;
    01433             manualD3D = D3DXCOLOR( bm.colourArg2.r, bm.colourArg2.g, bm.colourArg2.b, bm.colourArg2.a );
    01434         }
    01435         else if( bm.blendType == LBT_ALPHA )
    01436         {
    01437             tss = D3DTSS_ALPHAARG2;
    01438             manualD3D = D3DXCOLOR( 0.0, 0.0, 0.0, bm.alphaArg2 );
    01439         }
    01440         // Set manual factor if required
    01441         if (bm.source2 == LBS_MANUAL)
    01442         {
    01443             hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
    01444             if (FAILED(hr))
    01445                 Except( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
    01446         }
    01447         // Now set source 2
    01448         hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.source2) );
    01449         if (FAILED(hr))
    01450             Except( hr, "Failed to set source 2", "D3D9RenderSystem::_setTextureBlendMode" );
    01451     }
    01452     //---------------------------------------------------------------------
    01453     void D3D9RenderSystem::_setSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor )
    01454     {
    01455         HRESULT hr;
    01456         if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
    01457             Except( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
    01458         if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
    01459             Except( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
    01460     }
    01461     //---------------------------------------------------------------------
    01462     void D3D9RenderSystem::_setAlphaRejectSettings( CompareFunction func, unsigned char value )
    01463     {
    01464         HRESULT hr;
    01465         if (func != CMPF_ALWAYS_PASS)
    01466         {
    01467             if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE ) ) )
    01468                 Except( hr, "Failed to enable alpha testing",
    01469                 "D3D9RenderSystem::_setAlphaRejectSettings" );
    01470         }
    01471         else
    01472         {
    01473             if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  FALSE ) ) )
    01474                 Except( hr, "Failed to disable alpha testing",
    01475                 "D3D9RenderSystem::_setAlphaRejectSettings" );
    01476         }
    01477         // Set always just be sure
    01478         if( FAILED( hr = __SetRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
    01479             Except( hr, "Failed to set alpha reject function", "D3D9RenderSystem::_setAlphaRejectSettings" );
    01480         if( FAILED( hr = __SetRenderState( D3DRS_ALPHAREF, value ) ) )
    01481             Except( hr, "Failed to set render state D3DRS_ALPHAREF", "D3D9RenderSystem::_setAlphaRejectSettings" );
    01482     }
    01483     //---------------------------------------------------------------------
    01484     void D3D9RenderSystem::_setCullingMode( CullingMode mode )
    01485     {
    01486         HRESULT hr;
    01487         bool flip = ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
    01488                 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding));
    01489
    01490         if( FAILED (hr = __SetRenderState(D3DRS_CULLMODE,
    01491             D3D9Mappings::get(mode, flip))) )
    01492             Except( hr, "Failed to set culling mode", "D3D9RenderSystem::_setCullingMode" );
    01493     }
    01494     //---------------------------------------------------------------------
    01495     void D3D9RenderSystem::_setDepthBufferParams( bool depthTest, bool depthWrite, CompareFunction depthFunction )
    01496     {
    01497         _setDepthBufferCheckEnabled( depthTest );
    01498         _setDepthBufferWriteEnabled( depthWrite );
    01499         _setDepthBufferFunction( depthFunction );
    01500     }
    01501     //---------------------------------------------------------------------
    01502     void D3D9RenderSystem::_setDepthBufferCheckEnabled( bool enabled )
    01503     {
    01504         HRESULT hr;
    01505
    01506         if( enabled )
    01507         {
    01508             // Use w-buffer if available and enabled
    01509             if( mWBuffer && mCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
    01510                 hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
    01511             else
    01512                 hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
    01513         }
    01514         else
    01515             hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
    01516
    01517         if( FAILED( hr ) )
    01518             Except( hr, "Error setting depth buffer test state", "D3D9RenderSystem::_setDepthBufferCheckEnabled" );
    01519     }
    01520     //---------------------------------------------------------------------
    01521     void D3D9RenderSystem::_setDepthBufferWriteEnabled( bool enabled )
    01522     {
    01523         HRESULT hr;
    01524
    01525         if( FAILED( hr = __SetRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
    01526             Except( hr, "Error setting depth buffer write state", "D3D9RenderSystem::_setDepthBufferWriteEnabled" );
    01527     }
    01528     //---------------------------------------------------------------------
    01529     void D3D9RenderSystem::_setDepthBufferFunction( CompareFunction func )
    01530     {
    01531         HRESULT hr;
    01532         if( FAILED( hr = __SetRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
    01533             Except( hr, "Error setting depth buffer test function", "D3D9RenderSystem::_setDepthBufferFunction" );
    01534     }
    01535     //---------------------------------------------------------------------
    01536     void D3D9RenderSystem::_setDepthBias(ushort bias)
    01537     {
    01538         HRESULT hr = __SetRenderState(D3DRS_DEPTHBIAS, bias);
    01539         if (FAILED(hr))
    01540             Except(hr, "Error setting depth bias", "D3D9RenderSystem::_setDepthBias");
    01541     }
    01542     //---------------------------------------------------------------------
    01543     void D3D9RenderSystem::_setColourBufferWriteEnabled(bool red, bool green,
    01544         bool blue, bool alpha)
    01545     {
    01546         DWORD val = 0;
    01547         if (red)
    01548             val |= D3DCOLORWRITEENABLE_RED;
    01549         if (green)
    01550             val |= D3DCOLORWRITEENABLE_GREEN;
    01551         if (blue)
    01552             val |= D3DCOLORWRITEENABLE_BLUE;
    01553         if (alpha)
    01554             val |= D3DCOLORWRITEENABLE_ALPHA;
    01555         HRESULT hr = __SetRenderState(D3DRS_COLORWRITEENABLE, val);
    01556         if (FAILED(hr))
    01557             Except(hr, "Error setting colour write enable flags",
    01558             "D3D9RenderSystem::_setColourBufferWriteEnabled");
    01559     }
    01560     //---------------------------------------------------------------------
    01561     void D3D9RenderSystem::_setFog( FogMode mode, const ColourValue& colour, Real densitiy, Real start, Real end )
    01562     {
    01563         HRESULT hr;
    01564
    01565         D3DRENDERSTATETYPE fogType, fogTypeNot;
    01566
    01567         if (mCaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
    01568         {
    01569             fogType = D3DRS_FOGTABLEMODE;
    01570             fogTypeNot = D3DRS_FOGVERTEXMODE;
    01571         }
    01572         else
    01573         {
    01574             fogType = D3DRS_FOGVERTEXMODE;
    01575             fogTypeNot = D3DRS_FOGTABLEMODE;
    01576         }
    01577
    01578         if( mode == FOG_NONE)
    01579         {
    01580             // just disable
    01581             hr = __SetRenderState(fogType, D3DFOG_NONE );
    01582             hr = __SetRenderState(D3DRS_FOGENABLE, FALSE);
    01583         }
    01584         else
    01585         {
    01586             // Allow fog
    01587             hr = __SetRenderState( D3DRS_FOGENABLE, TRUE );
    01588             hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
    01589             hr = __SetRenderState( fogType, D3D9Mappings::get(mode) );
    01590
    01591             hr = __SetRenderState( D3DRS_FOGCOLOR, colour.getAsLongARGB() );
    01592             hr = __SetRenderState( D3DRS_FOGSTART, *((LPDWORD)(&start)) );
    01593             hr = __SetRenderState( D3DRS_FOGEND, *((LPDWORD)(&end)) );
    01594             hr = __SetRenderState( D3DRS_FOGDENSITY, *((LPDWORD)(&densitiy)) );
    01595         }
    01596
    01597         if( FAILED( hr ) )
    01598             Except( hr, "Error setting render state", "D3D9RenderSystem::_setFog" );
    01599     }
    01600     //---------------------------------------------------------------------
    01601     void D3D9RenderSystem::_setRasterisationMode(SceneDetailLevel level)
    01602     {
    01603         HRESULT hr = __SetRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
    01604         if (FAILED(hr))
    01605             Except(hr, "Error setting rasterisation mode.", "D3D9RenderSystem::setRasterisationMode");
    01606     }
    01607     //---------------------------------------------------------------------
    01608     void D3D9RenderSystem::setStencilCheckEnabled(bool enabled)
    01609     {
    01610         // Allow stencilling
    01611         HRESULT hr = __SetRenderState(D3DRS_STENCILENABLE, enabled);
    01612         if (FAILED(hr))
    01613             Except(hr, "Error enabling / disabling stencilling.",
    01614             "D3D9RenderSystem::setStencilCheckEnabled");
    01615     }
    01616     //---------------------------------------------------------------------
    01617     void D3D9RenderSystem::setStencilBufferParams(CompareFunction func, ulong refValue,
    01618         ulong mask, StencilOperation stencilFailOp,
    01619         StencilOperation depthFailOp, StencilOperation passOp,
    01620         bool twoSidedOperation)
    01621     {
    01622         HRESULT hr;
    01623
    01624         // 2-sided operation
    01625         if (twoSidedOperation)
    01626         {
    01627             if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
    01628                 Except(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
    01629                     "D3D9RenderSystem::setStencilBufferParams");
    01630             hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
    01631             if (FAILED(hr))
    01632                 Except(hr, "Error setting 2-sided stencil mode.",
    01633                 "D3D9RenderSystem::setStencilBufferParams");
    01634
    01635             // Set alternative versions of ops
    01636             // fail op
    01637             hr = __SetRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp, true));
    01638             if (FAILED(hr))
    01639                 Except(hr, "Error setting stencil fail operation (2-sided).",
    01640                 "D3D9RenderSystem::setStencilBufferParams");
    01641
    01642             // depth fail op
    01643             hr = __SetRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp, true));
    01644             if (FAILED(hr))
    01645                 Except(hr, "Error setting stencil depth fail operation (2-sided).",
    01646                 "D3D9RenderSystem::setStencilBufferParams");
    01647
    01648             // pass op
    01649             hr = __SetRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp, true));
    01650             if (FAILED(hr))
    01651                 Except(hr, "Error setting stencil pass operation (2-sided).",
    01652                 "D3D9RenderSystem::setStencilBufferParams");
    01653
    01654         }
    01655         else
    01656         {
    01657             hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
    01658             if (FAILED(hr))
    01659                 Except(hr, "Error setting 1-sided stencil mode.",
    01660                 "D3D9RenderSystem::setStencilBufferParams");
    01661         }
    01662
    01663         // func
    01664         hr = __SetRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
    01665         if (FAILED(hr))
    01666             Except(hr, "Error setting stencil buffer test function.",
    01667             "D3D9RenderSystem::setStencilBufferParams");
    01668
    01669         // reference value
    01670         hr = __SetRenderState(D3DRS_STENCILREF, refValue);
    01671         if (FAILED(hr))
    01672             Except(hr, "Error setting stencil buffer reference value.",
    01673             "D3D9RenderSystem::setStencilBufferParams");
    01674
    01675         // mask
    01676         hr = __SetRenderState(D3DRS_STENCILMASK, mask);
    01677         if (FAILED(hr))
    01678             Except(hr, "Error setting stencil buffer mask.",
    01679             "D3D9RenderSystem::setStencilBufferParams");
    01680
    01681         // fail op
    01682         hr = __SetRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp));
    01683         if (FAILED(hr))
    01684             Except(hr, "Error setting stencil fail operation.",
    01685             "D3D9RenderSystem::setStencilBufferParams");
    01686
    01687         // depth fail op
    01688         hr = __SetRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp));
    01689         if (FAILED(hr))
    01690             Except(hr, "Error setting stencil depth fail operation.",
    01691             "D3D9RenderSystem::setStencilBufferParams");
    01692
    01693         // pass op
    01694         hr = __SetRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp));
    01695         if (FAILED(hr))
    01696             Except(hr, "Error setting stencil pass operation.",
    01697             "D3D9RenderSystem::setStencilBufferParams");
    01698     }
    01699     //---------------------------------------------------------------------
    01700     void D3D9RenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype,
    01701         FilterOptions filter)
    01702     {
    01703         HRESULT hr;
    01704         D3D9Mappings::eD3DTexType texType = mTexStageDesc[unit].texType;
    01705         hr = __SetSamplerState( unit, D3D9Mappings::get(ftype),
    01706             D3D9Mappings::get(ftype, filter, mCaps, texType));
    01707         if (FAILED(hr))
    01708             Except(hr, "Failed to set texture filter ", "D3D9RenderSystem::_setTextureUnitFiltering");
    01709     }
    01710     //---------------------------------------------------------------------
    01711     DWORD D3D9RenderSystem::_getCurrentAnisotropy(size_t unit)
    01712     {
    01713         DWORD oldVal;
    01714         mpD3DDevice->GetSamplerState(unit, D3DSAMP_MAXANISOTROPY, &oldVal);
    01715             return oldVal;
    01716     }
    01717     //---------------------------------------------------------------------
    01718     void D3D9RenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
    01719     {
    01720         if ((DWORD)maxAnisotropy > mCaps.MaxAnisotropy)
    01721             maxAnisotropy = mCaps.MaxAnisotropy;
    01722
    01723         if (_getCurrentAnisotropy(unit) != maxAnisotropy)
    01724             __SetSamplerState( unit, D3DSAMP_MAXANISOTROPY, maxAnisotropy );
    01725     }
    01726     //---------------------------------------------------------------------
    01727     HRESULT D3D9RenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
    01728     {
    01729         HRESULT hr;
    01730         DWORD oldVal;
    01731
    01732         if ( FAILED( hr = mpD3DDevice->GetRenderState(state, &oldVal) ) )
    01733             return hr;
    01734         if ( oldVal == value )
    01735             return D3D_OK;
    01736         else
    01737             return mpD3DDevice->SetRenderState(state, value);
    01738     }
    01739     //---------------------------------------------------------------------
    01740     HRESULT D3D9RenderSystem::__SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
    01741     {
    01742         HRESULT hr;
    01743         DWORD oldVal;
    01744
    01745         if ( FAILED( hr = mpD3DDevice->GetSamplerState(sampler, type, &oldVal) ) )
    01746             return hr;
    01747         if ( oldVal == value )
    01748             return D3D_OK;
    01749         else
    01750             return mpD3DDevice->SetSamplerState(sampler, type, value);
    01751     }
    01752     //---------------------------------------------------------------------
    01753     HRESULT D3D9RenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
    01754     {
    01755         HRESULT hr;
    01756         DWORD oldVal;
    01757
    01758         if ( FAILED( hr = mpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) )
    01759             return hr;
    01760         if ( oldVal == value )
    01761             return D3D_OK;
    01762         else
    01763             return mpD3DDevice->SetTextureStageState(stage, type, value);
    01764     }
    01765     //---------------------------------------------------------------------
    01766     void D3D9RenderSystem::_setViewport( Viewport *vp )
    01767     {
    01768         if( vp != mActiveViewport || vp->_isUpdated() )
    01769         {
    01770             mActiveViewport = vp;
    01771             mActiveRenderTarget = vp->getTarget();
    01772
    01773             // ok, it's different, time to set render target and viewport params
    01774             D3DVIEWPORT9 d3dvp;
    01775             HRESULT hr;
    01776
    01777             // Set render target
    01778             RenderTarget* target;
    01779             target = vp->getTarget();
    01780
    01781             LPDIRECT3DSURFACE9 pBack = NULL;
    01782             target->getCustomAttribute( "DDBACKBUFFER", &pBack );
    01783             if (!pBack)
    01784                 return;
    01785
    01786             LPDIRECT3DSURFACE9 pDepth = NULL;
    01787             target->getCustomAttribute( "D3DZBUFFER", &pDepth );
    01788             if (!pDepth)
    01789                 return;
    01790
    01791             hr = mpD3DDevice->SetRenderTarget(0, pBack);
    01792             if (FAILED(hr))
    01793             {
    01794                 String msg = DXGetErrorDescription9(hr);
    01795                 Except( hr, "Failed to setRenderTarget : " + msg, "D3D9RenderSystem::_setViewport" );
    01796             }
    01797             hr = mpD3DDevice->SetDepthStencilSurface(pDepth);
    01798             if (FAILED(hr))
    01799             {
    01800                 String msg = DXGetErrorDescription9(hr);
    01801                 Except( hr, "Failed to setDepthStencil : " + msg, "D3D9RenderSystem::_setViewport" );
    01802             }
    01803
    01804             _setCullingMode( mCullingMode );
    01805
    01806             // set viewport dimensions
    01807             d3dvp.X = vp->getActualLeft();
    01808             d3dvp.Y = vp->getActualTop();
    01809             d3dvp.Width = vp->getActualWidth();
    01810             d3dvp.Height = vp->getActualHeight();
    01811
    01812             // Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
    01813             d3dvp.MinZ = 0.0f;
    01814             d3dvp.MaxZ = 1.0f;
    01815
    01816             if( FAILED( hr = mpD3DDevice->SetViewport( &d3dvp ) ) )
    01817                 Except( hr, "Failed to set viewport.", "D3D9RenderSystem::_setViewport" );
    01818
    01819             vp->_clearUpdatedFlag();
    01820         }
    01821     }
    01822     //---------------------------------------------------------------------
    01823     void D3D9RenderSystem::_beginFrame()
    01824     {
    01825         OgreGuard( "D3D9RenderSystem::_beginFrame" );
    01826
    01827         HRESULT hr;
    01828
    01829         if( !mActiveViewport )
    01830             Except( Exception::ERR_INTERNAL_ERROR, "Cannot begin frame - no viewport selected.", "D3D9RenderSystem::_beginFrame" );
    01831
    01832         // Clear the viewport if required
    01833         if( mActiveViewport->getClearEveryFrame() )
    01834         {
    01835             clearFrameBuffer(FBT_COLOUR | FBT_DEPTH,
    01836                 mActiveViewport->getBackgroundColour());
    01837         }
    01838
    01839         if( FAILED( hr = mpD3DDevice->BeginScene() ) )
    01840         {
    01841             String msg = DXGetErrorDescription9(hr);
    01842             Except( hr, "Error beginning frame :" + msg, "D3D9RenderSystem::_beginFrame" );
    01843         }
    01844
    01845         static bool firstTime = true;
    01846         if( firstTime )
    01847         {
    01848             // First-time
    01849             // setup some defaults
    01850             // Allow alpha blending
    01851             hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    01852             if (FAILED(hr))
    01853             {
    01854                 String msg = DXGetErrorDescription9(hr);
    01855                 Except(hr, "Error enabling alpha blending option : " + msg, "D3D9RenderSystem::_beginFrame");
    01856             }
    01857             // Allow specular
    01858             hr = __SetRenderState(D3DRS_SPECULARENABLE, TRUE);
    01859             if (FAILED(hr))
    01860             {
    01861                 String msg = DXGetErrorDescription9(hr);
    01862                 Except(hr, "Error enabling alpha blending option : " + msg, "D3D9RenderSystem::_beginFrame");
    01863             }
    01864             firstTime = false;
    01865         }
    01866
    01867         OgreUnguard();
    01868     }
    01869     //---------------------------------------------------------------------
    01870     void D3D9RenderSystem::_endFrame()
    01871     {
    01872         OgreGuard( "D3D9RenderSystem::_endFrame" );
    01873
    01874         HRESULT hr;
    01875         if( FAILED( hr = mpD3DDevice->EndScene() ) )
    01876             Except( hr, "Error ending frame", "D3D9RenderSystem::_endFrame" );
    01877
    01878         OgreUnguard();
    01879     }
    01880     //---------------------------------------------------------------------
    01881     inline bool D3D9RenderSystem::compareDecls( D3DVERTEXELEMENT9* pDecl1, D3DVERTEXELEMENT9* pDecl2, size_t size )
    01882     {
    01883         for( size_t i=0; i < size; i++ )
    01884         {
    01885             if( pDecl1[i].Method != pDecl2[i].Method ||
    01886                 pDecl1[i].Offset != pDecl2[i].Offset ||
    01887                 pDecl1[i].Stream != pDecl2[i].Stream ||
    01888                 pDecl1[i].Type != pDecl2[i].Type ||
    01889                 pDecl1[i].Usage != pDecl2[i].Usage ||
    01890                 pDecl1[i].UsageIndex != pDecl2[i].UsageIndex)
    01891             {
    01892                 return false;
    01893             }
    01894         }
    01895
    01896         return true;
    01897     }
    01898     //---------------------------------------------------------------------
    01899     void D3D9RenderSystem::setVertexDeclaration(VertexDeclaration* decl)
    01900     {
    01901         // Guard
    01902         OgreGuard ("D3D9RenderSystem::setVertexDeclaration");
    01903         HRESULT hr;
    01904
    01905         D3D9VertexDeclaration* d3ddecl =
    01906             static_cast<D3D9VertexDeclaration*>(decl);
    01907
    01908         static VertexDeclaration* lastDecl = 0;
    01909
    01910         // attempt to detect duplicates
    01911         if (!lastDecl || !(*lastDecl == *decl))
    01912         {
    01913
    01914             if (FAILED(hr = mpD3DDevice->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
    01915             {
    01916                 Except(hr, "Unable to set D3D9 vertex declaration",
    01917                     "D3D9RenderSystem::setVertexDeclaration");
    01918             }
    01919         }
    01920
    01921         // UnGuard
    01922         OgreUnguard();
    01923     }
    01924     //---------------------------------------------------------------------
    01925     void D3D9RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
    01926     {
    01927         // Guard
    01928         OgreGuard ("D3D9RenderSystem::setVertexBufferBinding");
    01929
    01930         HRESULT hr;
    01931
    01932         // TODO: attempt to detect duplicates
    01933         const VertexBufferBinding::VertexBufferBindingMap& binds = binding->getBindings();
    01934         VertexBufferBinding::VertexBufferBindingMap::const_iterator i, iend;
    01935         iend = binds.end();
    01936         for (i = binds.begin(); i != iend; ++i)
    01937         {
    01938             const D3D9HardwareVertexBuffer* d3d9buf =
    01939                 static_cast<const D3D9HardwareVertexBuffer*>(i->second.get());
    01940             hr = mpD3DDevice->SetStreamSource(
    01941                 static_cast<UINT>(i->first),
    01942                 d3d9buf->getD3D9VertexBuffer(),
    01943                 0, // no stream offset, this is handled in _render instead
    01944                 static_cast<UINT>(d3d9buf->getVertexSize()) // stride
    01945                 );
    01946             if (FAILED(hr))
    01947             {
    01948                 Except(hr, "Unable to set D3D9 stream source for buffer binding",
    01949                     "D3D9RenderSystem::setVertexBufferBinding");
    01950             }
    01951
    01952
    01953         }
    01954
    01955         // Unbind any unused sources
    01956         for (size_t unused = binds.size(); unused < mLastVertexSourceCount; ++unused)
    01957         {
    01958
    01959             hr = mpD3DDevice->SetStreamSource(static_cast<UINT>(unused), NULL, 0, 0);
    01960             if (FAILED(hr))
    01961             {
    01962                 Except(hr, "Unable to reset unused D3D9 stream source",
    01963                     "D3D9RenderSystem::setVertexBufferBinding");
    01964             }
    01965
    01966         }
    01967         mLastVertexSourceCount = binds.size();
    01968
    01969
    01970
    01971         // UnGuard
    01972         OgreUnguard();
    01973     }
    01974     //---------------------------------------------------------------------
    01975     void D3D9RenderSystem::_render(const RenderOperation& op)
    01976     {
    01977         // Guard
    01978         OgreGuard ("D3D9RenderSystem::_render");
    01979
    01980         // Exit immediately if there is nothing to render
    01981         // This caused a problem on FireGL 8800
    01982         if (op.vertexData->vertexCount == 0)
    01983             return;
    01984
    01985         // Call super class
    01986         RenderSystem::_render(op);
    01987
    01988         // To think about: possibly remove setVertexDeclaration and
    01989         // setVertexBufferBinding from RenderSystem since the sequence is
    01990         // a bit too D3D9-specific?
    01991         setVertexDeclaration(op.vertexData->vertexDeclaration);
    01992         setVertexBufferBinding(op.vertexData->vertexBufferBinding);
    01993
    01994         // Determine rendering operation
    01995         D3DPRIMITIVETYPE primType;
    01996         DWORD primCount = 0;
    01997         switch( op.operationType )
    01998         {
    01999         case RenderOperation::OT_POINT_LIST:
    02000             primType = D3DPT_POINTLIST;
    02001             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
    02002             break;
    02003
    02004         case RenderOperation::OT_LINE_LIST:
    02005             primType = D3DPT_LINELIST;
    02006             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
    02007             break;
    02008
    02009         case RenderOperation::OT_LINE_STRIP:
    02010             primType = D3DPT_LINESTRIP;
    02011             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
    02012             break;
    02013
    02014         case RenderOperation::OT_TRIANGLE_LIST:
    02015             primType = D3DPT_TRIANGLELIST;
    02016             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
    02017             break;
    02018
    02019         case RenderOperation::OT_TRIANGLE_STRIP:
    02020             primType = D3DPT_TRIANGLESTRIP;
    02021             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
    02022             break;
    02023
    02024         case RenderOperation::OT_TRIANGLE_FAN:
    02025             primType = D3DPT_TRIANGLEFAN;
    02026             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
    02027             break;
    02028         }
    02029
    02030         if (!primCount)
    02031             return;
    02032
    02033         // Issue the op
    02034         HRESULT hr;
    02035         if( op.useIndexes )
    02036         {
    02037             D3D9HardwareIndexBuffer* d3dIdxBuf =
    02038                 static_cast<D3D9HardwareIndexBuffer*>(op.indexData->indexBuffer.get());
    02039             hr = mpD3DDevice->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
    02040             if (FAILED(hr))
    02041             {
    02042                 Except( hr, "Failed to set index buffer", "D3D9RenderSystem::_render" );
    02043             }
    02044
    02045             // do indexed draw operation
    02046             hr = mpD3DDevice->DrawIndexedPrimitive(
    02047                 primType,
    02048                 static_cast<INT>(op.vertexData->vertexStart),
    02049                 0, // Min vertex index - assume we can go right down to 0
    02050                 static_cast<UINT>(op.vertexData->vertexCount),
    02051                 static_cast<UINT>(op.indexData->indexStart),
    02052                 static_cast<UINT>(primCount)
    02053                 );
    02054         }
    02055         else
    02056         {
    02057             // Unindexed, a little simpler!
    02058             hr = mpD3DDevice->DrawPrimitive(
    02059                 primType,
    02060                 static_cast<UINT>(op.vertexData->vertexStart),
    02061                 static_cast<UINT>(primCount)
    02062                 );
    02063         }
    02064
    02065         if( FAILED( hr ) )
    02066         {
    02067             String msg = DXGetErrorDescription9(hr);
    02068             Except( hr, "Failed to DrawPrimitive : " + msg, "D3D9RenderSystem::_render" );
    02069         }
    02070
    02071         // UnGuard
    02072         OgreUnguard();
    02073
    02074     }
    02075     //---------------------------------------------------------------------
    02076     void D3D9RenderSystem::setNormaliseNormals(bool normalise)
    02077     {
    02078         __SetRenderState(D3DRS_NORMALIZENORMALS,
    02079             normalise ? TRUE : FALSE);
    02080     }
    02081     //---------------------------------------------------------------------
    02082     void D3D9RenderSystem::bindGpuProgram(GpuProgram* prg)
    02083     {
    02084         HRESULT hr;
    02085         switch (prg->getType())
    02086         {
    02087         case GPT_VERTEX_PROGRAM:
    02088             hr = mpD3DDevice->SetVertexShader(
    02089                 static_cast<D3D9GpuVertexProgram*>(prg)->getVertexShader());
    02090             if (FAILED(hr))
    02091             {
    02092                 Except(hr, "Error calling SetVertexShader", "D3D9RenderSystem::bindGpuProgram");
    02093             }
    02094             break;
    02095         case GPT_FRAGMENT_PROGRAM:
    02096             hr = mpD3DDevice->SetPixelShader(
    02097                 static_cast<D3D9GpuFragmentProgram*>(prg)->getPixelShader());
    02098             if (FAILED(hr))
    02099             {
    02100                 Except(hr, "Error calling SetPixelShader", "D3D9RenderSystem::bindGpuProgram");
    02101             }
    02102             break;
    02103         };
    02104
    02105     }
    02106     //---------------------------------------------------------------------
    02107     void D3D9RenderSystem::unbindGpuProgram(GpuProgramType gptype)
    02108     {
    02109         HRESULT hr;
    02110         switch(gptype)
    02111         {
    02112         case GPT_VERTEX_PROGRAM:
    02113             hr = mpD3DDevice->SetVertexShader(NULL);
    02114             if (FAILED(hr))
    02115             {
    02116                 Except(hr, "Error resetting SetVertexShader to NULL",
    02117                     "D3D9RenderSystem::unbindGpuProgram");
    02118             }
    02119             break;
    02120         case GPT_FRAGMENT_PROGRAM:
    02121             hr = mpD3DDevice->SetPixelShader(NULL);
    02122             if (FAILED(hr))
    02123             {
    02124                 Except(hr, "Error resetting SetPixelShader to NULL",
    02125                     "D3D9RenderSystem::unbindGpuProgram");
    02126             }
    02127             break;
    02128         };
    02129     }
    02130     //---------------------------------------------------------------------
    02131     void D3D9RenderSystem::bindGpuProgramParameters(GpuProgramType gptype,
    02132         GpuProgramParametersSharedPtr params)
    02133     {
    02134         HRESULT hr;
    02135         unsigned int index;
    02136         GpuProgramParameters::IntConstantIterator intIt = params->getIntConstantIterator();
    02137         GpuProgramParameters::RealConstantIterator realIt = params->getRealConstantIterator();
    02138
    02139         switch(gptype)
    02140         {
    02141         case GPT_VERTEX_PROGRAM:
    02142             // Bind floats
    02143             if (params->hasRealConstantParams())
    02144             {
    02145                 // Iterate over params and set the relevant ones
    02146                 index = 0;
    02147                 while (realIt.hasMoreElements())
    02148                 {
    02149                     const GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
    02150                     if (e->isSet)
    02151                     {
    02152                         if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantF(
    02153                             index, e->val, 1)))
    02154                         {
    02155                             Except(hr, "Unable to upload shader float parameters",
    02156                                 "D3D9RenderSystem::bindGpuProgramParameters");
    02157                         }
    02158                     }
    02159                     index++;
    02160                     realIt.moveNext();
    02161                 }
    02162             }
    02163             // Bind ints
    02164             if (params->hasIntConstantParams())
    02165             {
    02166                 // Iterate over params and set the relevant ones
    02167                 index = 0;
    02168                 while (intIt.hasMoreElements())
    02169                 {
    02170                     const GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
    02171                     if (e->isSet)
    02172                     {
    02173                         if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantI(
    02174                             index, e->val, 1)))
    02175                         {
    02176                             Except(hr, "Unable to upload shader float parameters",
    02177                                 "D3D9RenderSystem::bindGpuProgramParameters");
    02178                         }
    02179                     }
    02180                     index++;
    02181                     intIt.moveNext();
    02182                 }
    02183             }
    02184             break;
    02185         case GPT_FRAGMENT_PROGRAM:
    02186             // Bind floats
    02187             if (params->hasRealConstantParams())
    02188             {
    02189                 // Iterate over params and set the relevant ones
    02190                 index = 0;
    02191                 while (realIt.hasMoreElements())
    02192                 {
    02193                     const GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
    02194                     if (e->isSet)
    02195                     {
    02196                         /*
    02197                         // TEST
    02198                         LogManager::getSingleton().logMessage(
    02199                             "  Set Constant " + StringConverter::toString(index) + " to float4(" +
    02200                             StringConverter::toString(e->val[0]) + ", " +
    02201                             StringConverter::toString(e->val[1]) + ", " +
    02202                             StringConverter::toString(e->val[2]) + ", " +
    02203                             StringConverter::toString(e->val[3]) + ")");
    02204                         */
    02205
    02206                         if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantF(
    02207                             index, e->val, 1)))
    02208                         {
    02209                             Except(hr, "Unable to upload shader float parameters",
    02210                                 "D3D9RenderSystem::bindGpuProgramParameters");
    02211                         }
    02212                     }
    02213                     index++;
    02214                     realIt.moveNext();
    02215                 }
    02216             }
    02217             // Bind ints
    02218             if (params->hasIntConstantParams())
    02219             {
    02220                 // Iterate over params and set the relevant ones
    02221                 index = 0;
    02222                 while (intIt.hasMoreElements())
    02223                 {
    02224                     const GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
    02225                     if (e->isSet)
    02226                     {
    02227                         if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantI(
    02228                             index, e->val, 1)))
    02229                         {
    02230                             Except(hr, "Unable to upload shader float parameters",
    02231                                 "D3D9RenderSystem::bindGpuProgramParameters");
    02232                         }
    02233                     }
    02234                     index++;
    02235                     intIt.moveNext();
    02236                 }
    02237             }
    02238             break;
    02239         };
    02240     }
    02241     //---------------------------------------------------------------------
    02242     void D3D9RenderSystem::setClipPlanes(const PlaneList& clipPlanes)
    02243     {
    02244         size_t i;
    02245         size_t numClipPlanes;
    02246         float dx9ClipPlane[4];
    02247         DWORD mask = 0;
    02248         HRESULT hr;
    02249
    02250         numClipPlanes = clipPlanes.size();
    02251         for (i = 0; i < numClipPlanes; ++i)
    02252         {
    02253             const Plane& plane = clipPlanes[i];
    02254
    02255             dx9ClipPlane[0] = plane.normal.x;
    02256             dx9ClipPlane[1] = plane.normal.y;
    02257             dx9ClipPlane[2] = plane.normal.z;
    02258             dx9ClipPlane[3] = -plane.d;
    02259
    02260             hr = mpD3DDevice->SetClipPlane(i, dx9ClipPlane);
    02261             if (FAILED(hr))
    02262             {
    02263                 Except(hr, "Unable to set clip plane",
    02264                     "D3D9RenderSystem::setClipPlanes");
    02265             }
    02266
    02267             mask |= (1 << i);
    02268         }
    02269
    02270         hr = __SetRenderState(D3DRS_CLIPPLANEENABLE, mask);
    02271         if (FAILED(hr))
    02272         {
    02273             Except(hr, "Unable to set render state for clip planes",
    02274                 "D3D9RenderSystem::setClipPlanes");
    02275         }
    02276     }
    02277     //---------------------------------------------------------------------
    02278     void D3D9RenderSystem::setScissorTest(bool enabled, size_t left, size_t top, size_t right,
    02279         size_t bottom)
    02280     {
    02281         HRESULT hr;
    02282         if (enabled)
    02283         {
    02284             if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
    02285             {
    02286                 Except(hr, "Unable to enable scissor rendering state; " + getErrorDescription(hr),
    02287                     "D3D9RenderSystem::setScissorTest");
    02288             }
    02289             RECT rect;
    02290             rect.left = left;
    02291             rect.top = top;
    02292             rect.bottom = bottom;
    02293             rect.right = right;
    02294             if (FAILED(hr = mpD3DDevice->SetScissorRect(&rect)))
    02295             {
    02296                 Except(hr, "Unable to set scissor rectangle; " + getErrorDescription(hr),
    02297                     "D3D9RenderSystem::setScissorTest");
    02298             }
    02299         }
    02300         else
    02301         {
    02302             if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
    02303             {
    02304                 Except(hr, "Unable to disable scissor rendering state; " + getErrorDescription(hr),
    02305                     "D3D9RenderSystem::setScissorTest");
    02306             }
    02307         }
    02308     }
    02309     //---------------------------------------------------------------------
    02310     void D3D9RenderSystem::clearFrameBuffer(unsigned int buffers,
    02311         const ColourValue& colour, Real depth, unsigned short stencil)
    02312     {
    02313         DWORD flags = 0;
    02314         if (buffers & FBT_COLOUR)
    02315         {
    02316             flags |= D3DCLEAR_TARGET;
    02317         }
    02318         if (buffers & FBT_DEPTH)
    02319         {
    02320             flags |= D3DCLEAR_ZBUFFER;
    02321         }
    02322         // Only try to clear the stencil buffer if supported
    02323         if (buffers & FBT_STENCIL && mCapabilities->hasCapability(RSC_HWSTENCIL))
    02324         {
    02325             flags |= D3DCLEAR_STENCIL;
    02326         }
    02327         HRESULT hr;
    02328         if( FAILED( hr = mpD3DDevice->Clear(
    02329             0,
    02330             NULL,
    02331             flags,
    02332             colour.getAsLongARGB(),
    02333             depth,
    02334             stencil ) ) )
    02335         {
    02336             String msg = DXGetErrorDescription9(hr);
    02337             Except( hr, "Error clearing frame buffer : "
    02338                 + msg, "D3D9RenderSystem::clearFrameBuffer" );
    02339         }
    02340     }
    02341     //---------------------------------------------------------------------
    02342     void D3D9RenderSystem::_makeProjectionMatrix(Real left, Real right,
    02343         Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
    02344         bool forGpuProgram)
    02345     {
    02346         Real width = right - left;
    02347         Real height = top - bottom;
    02348         Real q, qn;
    02349         if (farPlane == 0)
    02350         {
    02351             q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
    02352             qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
    02353         }
    02354         else
    02355         {
    02356             q = farPlane / ( farPlane - nearPlane );
    02357             qn = -q * nearPlane;
    02358         }
    02359         dest = Matrix4::ZERO;
    02360         dest[0][0] = 2 * nearPlane / width;
    02361         dest[0][2] = (right+left) / width;
    02362         dest[1][1] = 2 * nearPlane / height;
    02363         dest[1][2] = (top+bottom) / height;
    02364         if (forGpuProgram)
    02365         {
    02366             dest[2][2] = -q;
    02367             dest[3][2] = -1.0f;
    02368         }
    02369         else
    02370         {
    02371             dest[2][2] = q;
    02372             dest[3][2] = 1.0f;
    02373         }
    02374         dest[2][3] = qn;
    02375     }
    02376
    02377     // ------------------------------------------------------------------
    02378     void D3D9RenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
    02379     {
    02380         float plane[4] = { A, B, C, D };
    02381         mpD3DDevice->SetClipPlane (index, plane);
    02382     }
    02383
    02384     // ------------------------------------------------------------------
    02385     void D3D9RenderSystem::enableClipPlane (ushort index, bool enable)
    02386     {
    02387         DWORD prev;
    02388         mpD3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
    02389         __SetRenderState(D3DRS_CLIPPLANEENABLE, prev | (1 << index));
    02390     }
    02391     //---------------------------------------------------------------------
    02392     HardwareOcclusionQuery* D3D9RenderSystem::createHardwareOcclusionQuery(void)
    02393     {
    02394         return new D3D9HardwareOcclusionQuery(mpD3DDevice);
    02395     }
    02396     //---------------------------------------------------------------------
    02397     Real D3D9RenderSystem::getHorizontalTexelOffset(void)
    02398     {
    02399         // D3D considers the origin to be in the center of a pixel
    02400         return -0.5f;
    02401     }
    02402     //---------------------------------------------------------------------
    02403     Real D3D9RenderSystem::getVerticalTexelOffset(void)
    02404     {
    02405         // D3D considers the origin to be in the center of a pixel
    02406         return -0.5f;
    02407     }
    02408     //---------------------------------------------------------------------
    02409     void D3D9RenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane,
    02410         bool forGpuProgram)
    02411     {
    02412         // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
    02413
    02414         // Calculate the clip-space corner point opposite the clipping plane
    02415         // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
    02416         // transform it into camera space by multiplying it
    02417         // by the inverse of the projection matrix
    02418
    02419         /* generalised version
    02420         Vector4 q = matrix.inverse() *
    02421             Vector4(Math::Sign(plane.normal.x), Math::Sign(plane.normal.y), 1.0f, 1.0f);
    02422         */
    02423         Vector4 q;
    02424         q.x = Math::Sign(plane.normal.x) / matrix[0][0];
    02425         q.y = Math::Sign(plane.normal.y) / matrix[1][1];
    02426         q.z = 1.0F;
    02427         // flip the next bit from Lengyel since we're right-handed
    02428         if (forGpuProgram)
    02429         {
    02430             q.w = (1.0F - matrix[2][2]) / matrix[2][3];
    02431         }
    02432         else
    02433         {
    02434             q.w = (1.0F + matrix[2][2]) / matrix[2][3];
    02435         }
    02436
    02437         // Calculate the scaled plane vector
    02438         Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
    02439         Vector4 c = clipPlane4d * (1.0F / (clipPlane4d.dotProduct(q)));
    02440
    02441         // Replace the third row of the projection matrix
    02442         matrix[2][0] = c.x;
    02443         matrix[2][1] = c.y;
    02444         // flip the next bit from Lengyel since we're right-handed
    02445         if (forGpuProgram)
    02446         {
    02447             matrix[2][2] = c.z;
    02448         }
    02449         else
    02450         {
    02451             matrix[2][2] = -c.z;
    02452         }
    02453         matrix[2][3] = c.w;
    02454     }
    02455     //---------------------------------------------------------------------
    02456     Real D3D9RenderSystem::getMinimumDepthInputValue(void)
    02457     {
    02458         // Range [0.0f, 1.0f]
    02459         return 0.0f;
    02460     }
    02461     //---------------------------------------------------------------------
    02462     Real D3D9RenderSystem::getMaximumDepthInputValue(void)
    02463     {
    02464         // Range [0.0f, 1.0f]
    02465         // D3D inverts even identity view matrices, so maximum INPUT is -1.0
    02466         return -1.0f;
    02467     }
    02468 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:21 2004