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

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:04 2004