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