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