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