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 <malloc.h> 00026 #include "OgreD3D7RenderSystem.h" 00027 #include "OgreDDDriver.h" 00028 #include "OgreD3D7Device.h" 00029 #include "OgreD3D7DeviceList.h" 00030 #include "OgreDDDriverList.h" 00031 #include "OgreDDVideoModeList.h" 00032 #include "OgreDDVideoMode.h" 00033 #include "OgreRenderWindow.h" 00034 #include "OgreLogManager.h" 00035 #include "OgreRenderSystem.h" 00036 #include "OgreException.h" 00037 #include "OgreSceneManager.h" 00038 #include "OgreD3D7TextureManager.h" 00039 #include "OgreViewport.h" 00040 #include "OgreLight.h" 00041 #include "OgreMatrix4.h" 00042 #include "OgreMath.h" 00043 #include "OgreD3D7RenderWindow.h" 00044 #include "OgreFrustum.h" 00045 #include "OgreD3D7GpuProgramManager.h" 00046 00047 00048 namespace Ogre { 00049 const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE( 00050 0.5, 0, 0, -0.5, 00051 0, -0.5, 0, -0.5, 00052 0, 0, 0, 1, 00053 0, 0, 0, 1); 00054 00055 const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO( 00056 -0.5, 0, 0, -0.5, 00057 0, 0.5, 0, -0.5, 00058 0, 0, 0, 1, 00059 0, 0, 0, 1); 00060 00061 //----------------------------------------------------------------------- 00062 D3DRenderSystem::D3DRenderSystem(HINSTANCE hInstance) 00063 { 00064 OgreGuard( "D3DRenderSystem::D3DRenderSystem" ); 00065 00066 LogManager::getSingleton().logMessage(getName() + " created."); 00067 00068 mlpD3DDevice = NULL; 00069 // Reset driver list 00070 mDriverList = NULL; 00071 mActiveDDDriver = NULL; 00072 mhInstance = hInstance; 00073 mHardwareBufferManager = NULL; 00074 mGpuProgramManager = NULL; 00075 00076 initConfigOptions(); 00077 00078 // Initialise D3DX library 00079 D3DXInitialize(); 00080 00081 // set stages desc. to defaults 00082 for (int n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++) 00083 { 00084 mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE; 00085 mTexStageDesc[n].coordIndex = 0; 00086 mTexStageDesc[n].texType = D3D_TEX_TYPE_NORMAL; 00087 mTexStageDesc[n].pTex = NULL; 00088 } 00089 00090 mCurrentLights = 0; 00091 00092 OgreUnguard(); 00093 } 00094 00095 //----------------------------------------------------------------------- 00096 D3DRenderSystem::~D3DRenderSystem() 00097 { 00098 OgreGuard( "D3DRenderSystem::~D3DRenderSystem" ); 00099 00100 SAFE_DELETE(mTextureManager); 00101 SAFE_DELETE(mDriverList); 00102 SAFE_DELETE(mCapabilities); 00103 SAFE_DELETE(mHardwareBufferManager); 00104 SAFE_DELETE(mGpuProgramManager); 00105 00106 D3DXUninitialize(); 00107 LogManager::getSingleton().logMessage(getName() + " destroyed."); 00108 00109 OgreUnguard(); 00110 } 00111 00112 //----------------------------------------------------------------------- 00113 const String& D3DRenderSystem::getName(void) const 00114 { 00115 static String strName("Direct3D7 Rendering Subsystem"); 00116 return strName; 00117 } 00118 00119 //----------------------------------------------------------------------- 00120 void D3DRenderSystem::initConfigOptions(void) 00121 { 00122 OgreGuard( "D3DRenderSystem::initConfigOptions" ); 00123 00124 DDDriverList* ddList; 00125 DDDriver* dd; 00126 00127 ConfigOption optDevice; 00128 ConfigOption optVideoMode; 00129 ConfigOption optFullScreen; 00130 ConfigOption optVSync; 00131 00132 ddList = this->getDirectDrawDrivers(); 00133 00134 // Create option for devices 00135 optDevice.name = "Rendering Device"; 00136 optDevice.currentValue = ""; 00137 optDevice.possibleValues.clear(); 00138 optDevice.immutable = false; 00139 00140 // Option for video modes 00141 optVideoMode.name = "Video Mode"; 00142 optVideoMode.currentValue = ""; 00143 optVideoMode.immutable = false; 00144 00145 // Option for full screen 00146 optFullScreen.name = "Full Screen"; 00147 optFullScreen.possibleValues.push_back("Yes"); 00148 optFullScreen.possibleValues.push_back("No"); 00149 optFullScreen.currentValue = "Yes"; 00150 00151 00152 unsigned k = ddList->count(); 00153 // First, get DirectDraw driver options 00154 for( unsigned j = 0; j < ddList->count(); j++ ) 00155 { 00156 dd = ddList->item(j); 00157 // Add to device option list 00158 optDevice.possibleValues.push_back( dd->DriverDescription() ); 00159 00160 // Make first one default 00161 if( j==0 ) 00162 { 00163 optDevice.currentValue = dd->DriverDescription(); 00164 00165 } 00166 00167 00168 } 00169 00170 // VSync option 00171 optVSync.name = "VSync"; 00172 optVSync.immutable = false; 00173 optVSync.possibleValues.push_back("Yes"); 00174 optVSync.possibleValues.push_back("No"); 00175 optVSync.currentValue = "Yes"; 00176 00177 00178 mOptions[optDevice.name] = optDevice; 00179 mOptions[optVideoMode.name] = optVideoMode; 00180 mOptions[optFullScreen.name] = optFullScreen; 00181 mOptions[optVSync.name] = optVSync; 00182 00183 // Set default-based settings 00184 refreshDDSettings(); 00185 00186 OgreUnguard(); 00187 } 00188 00189 //----------------------------------------------------------------------- 00190 void D3DRenderSystem::refreshDDSettings(void) 00191 { 00192 OgreGuard( "D3DRenderSystem::refreshDDSettings" ); 00193 00194 DDVideoMode* vid; 00195 ConfigOption* optVideoMode; 00196 ConfigOption* optFullScreen; 00197 DDDriver* dd; 00198 00199 // Stuffs DD-Driver specific settings 00200 00201 // Find DD Driver selected in options 00202 ConfigOptionMap::iterator opt = mOptions.find("Rendering Device"); 00203 00204 if( opt != mOptions.end() ) 00205 { 00206 for( unsigned j = 0; j < getDirectDrawDrivers()->count(); j++ ) 00207 { 00208 dd = getDirectDrawDrivers()->item(j); 00209 if( dd->DriverDescription() == opt->second.currentValue ) 00210 break; 00211 } 00212 00213 // Get fullScreen and Video mode options 00214 opt = mOptions.find("Video Mode"); 00215 optVideoMode = &opt->second; 00216 opt = mOptions.find("Full Screen"); 00217 optFullScreen = &opt->second; 00218 00219 // Full screen forced? 00220 if (!(dd->CanRenderWindowed())) 00221 { 00222 setConfigOption("Full Screen", "Yes"); 00223 optFullScreen->immutable = true; 00224 } 00225 else 00226 optFullScreen->immutable = false; 00227 00228 // Get video modes for this device 00229 optVideoMode->possibleValues.clear(); 00230 00231 for( unsigned k = 0; k<dd->getVideoModeList()->count(); k++ ) 00232 { 00233 vid = dd->getVideoModeList()->item(k); 00234 optVideoMode->possibleValues.push_back(vid->Description()); 00235 } 00236 } 00237 00238 OgreUnguard(); 00239 } 00240 00241 00242 //----------------------------------------------------------------------- 00243 ConfigOptionMap& D3DRenderSystem::getConfigOptions(void) 00244 { 00245 // Return a COPY of the current config options 00246 return mOptions; 00247 00248 } 00249 00250 //----------------------------------------------------------------------- 00251 void D3DRenderSystem::setConfigOption(const String &name, const String &value) 00252 { 00253 OgreGuard( "D3DRenderSystem::setConfigOption" ); 00254 00255 char msg[128]; 00256 00257 sprintf(msg, "RenderSystem Option: %s = %s", name.c_str(), value.c_str()); 00258 LogManager::getSingleton().logMessage(msg); 00259 00260 // Find option 00261 ConfigOptionMap::iterator it = mOptions.find(name); 00262 00263 // Update 00264 if( it != mOptions.end()) 00265 it->second.currentValue = value; 00266 else 00267 { 00268 sprintf(msg, "Option named %s does not exist.", name.c_str()); 00269 Except(Exception::ERR_INVALIDPARAMS, 00270 msg, "D3DRenderSystem::setConfigOption"); 00271 } 00272 00273 // Refresh other options if DD Driver changed 00274 if (name == "Rendering Device") 00275 refreshDDSettings(); 00276 00277 if (name == "Full Screen") 00278 { 00279 if (value == "No") 00280 { 00281 // Video mode is not applicable 00282 it = mOptions.find("Video Mode"); 00283 it->second.currentValue = "N/A"; 00284 it->second.immutable = true; 00285 } 00286 else 00287 { 00288 // Video mode is applicable 00289 it = mOptions.find("Video Mode"); 00290 // default to 640 x 480 x 16 00291 it->second.currentValue = "640 x 480 @ 16-bit colour"; 00292 it->second.immutable = false; 00293 } 00294 } 00295 00296 OgreUnguard(); 00297 } 00298 //----------------------------------------------------------------------- 00299 String D3DRenderSystem::validateConfigOptions(void) 00300 { 00301 // Check video mode specified in full screen mode 00302 ConfigOptionMap::iterator o = mOptions.find("Full Screen"); 00303 if (o->second.currentValue == "Yes") 00304 { 00305 // Check video mode 00306 o = mOptions.find("Video Mode"); 00307 if (o->second.currentValue == "") 00308 { 00309 return "A video mode must be selected for running in full-screen mode."; 00310 } 00311 } 00312 00313 o = mOptions.find( "Rendering Device" ); 00314 bool foundDriver = false; 00315 DDDriverList* driverList = getDirectDrawDrivers(); 00316 for( ushort j=0; j < driverList->count(); j++ ) 00317 { 00318 if( driverList->item(j)->DriverDescription() == o->second.currentValue ) 00319 { 00320 foundDriver = true; 00321 break; 00322 } 00323 } 00324 if (!foundDriver) 00325 { 00326 // Just pick the first driver 00327 setConfigOption("Rendering Device", driverList->item(0)->DriverDescription()); 00328 return "Your DirectX driver name has changed since the last time you ran OGRE; " 00329 "the 'Rendering Device' has been changed."; 00330 } 00331 return ""; 00332 00333 } 00334 //----------------------------------------------------------------------- 00335 RenderWindow* D3DRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle) 00336 { 00337 RenderWindow* autoWindow = 0; 00338 00339 00340 LogManager::getSingleton().logMessage( 00341 "***************************************\n" 00342 "*** Direct3D Subsystem Initialising ***\n" 00343 "***************************************" ); 00344 00345 // --------------------------- 00346 // Init using current settings 00347 // --------------------------- 00348 00349 // DirectDraw driver 00350 mActiveDDDriver = 0; 00351 ConfigOptionMap::iterator opt = mOptions.find("Rendering Device"); 00352 for( unsigned j = 0; j<getDirectDrawDrivers()->count(); j++ ) 00353 { 00354 if (getDirectDrawDrivers()->item(j)->DriverDescription() == opt->second.currentValue) 00355 { 00356 mActiveDDDriver = getDirectDrawDrivers()->item(j); 00357 break; 00358 } 00359 } 00360 00361 if (!mActiveDDDriver) 00362 Except(Exception::ERR_INVALIDPARAMS, "Problems finding requested DirectDraw driver!", 00363 "D3DRenderSystem::initialise"); 00364 00365 00366 // Sort out the creation of a new window if required 00367 if (autoCreateWindow) 00368 { 00369 // Full screen? 00370 bool fullScreen; 00371 opt = mOptions.find("Full Screen"); 00372 if( opt == mOptions.end() ) 00373 Except(999, "Can't find full screen option!", 00374 "D3DRenderSystem::initialise"); 00375 if (opt->second.currentValue == "Yes") 00376 fullScreen = true; 00377 else 00378 fullScreen = false; 00379 00380 // Get video mode 00381 DDVideoMode* vid; 00382 unsigned int height, width, colourDepth; 00383 00384 vid = 0; 00385 String temp; 00386 if (fullScreen) 00387 { 00388 opt = mOptions.find("Video Mode"); 00389 00390 for( unsigned j=0; j<mActiveDDDriver->getVideoModeList()->count(); j++ ) 00391 { 00392 temp = mActiveDDDriver->getVideoModeList()->item(j)->Description(); 00393 if (temp == opt->second.currentValue) 00394 { 00395 vid = mActiveDDDriver->getVideoModeList()->item(j); 00396 break; 00397 } 00398 } 00399 00400 if (!vid) 00401 Except(9999, "Can't find requested video mode.", 00402 "D3DRenderSystem::initilise"); 00403 width = vid->mWidth; 00404 height = vid->mHeight; 00405 colourDepth = vid->mColourDepth; 00406 00407 } 00408 else 00409 { 00410 // Notional height / width 00411 width = 800; 00412 height = 600; 00413 colourDepth = 0; // colour depth based on desktop 00414 } 00415 00416 // Create myself a window 00417 autoWindow = this->createRenderWindow(windowTitle, width, height, colourDepth, fullScreen); 00418 00419 00420 00421 } 00422 00423 opt = mOptions.find("VSync"); 00424 if (opt!=mOptions.end()) 00425 { 00426 if (opt->second.currentValue == "Yes") 00427 { 00428 setWaitForVerticalBlank(true); 00429 } 00430 else 00431 { 00432 setWaitForVerticalBlank(false); 00433 } 00434 } 00435 00436 00437 LogManager::getSingleton().logMessage("*****************************************"); 00438 LogManager::getSingleton().logMessage("*** Direct3D Subsystem Initialised Ok ***"); 00439 LogManager::getSingleton().logMessage("*****************************************"); 00440 00441 // call superclass method 00442 RenderSystem::initialise(autoCreateWindow); 00443 00444 // Create buffer manager 00445 mHardwareBufferManager = new D3D7HardwareBufferManager(); 00446 // Create dummy gpu manager 00447 mGpuProgramManager = new D3D7GpuProgramManager(); 00448 00449 00450 return autoWindow; 00451 00452 } 00453 00454 //----------------------------------------------------------------------- 00455 void D3DRenderSystem::reinitialise(void) 00456 { 00457 this->shutdown(); 00458 this->initialise(true); 00459 } 00460 00461 00462 //----------------------------------------------------------------------- 00463 void D3DRenderSystem::shutdown(void) 00464 { 00465 RenderSystem::shutdown(); 00466 00467 // Cleanup 00468 // Release all DirectX resources 00469 //D3DTextr_InvalidateAllTextures(); 00470 if (mActiveDDDriver) 00471 { 00472 mActiveDDDriver->Cleanup(); 00473 } 00474 00475 // Delete system objects 00476 SAFE_DELETE(mDriverList); 00477 00478 mActiveDDDriver = NULL; 00479 00480 00481 00482 // Write termination message 00483 LogManager::getSingleton().logMessage("*-*-* Direct3D Subsystem shutting down cleanly."); 00484 00485 00486 } 00487 00488 //----------------------------------------------------------------------- 00489 void D3DRenderSystem::setAmbientLight(float r, float g, float b) 00490 { 00491 // Call D3D 00492 D3DCOLOR col = D3DRGB(r,g,b); 00493 00494 HRESULT hr = __SetRenderState(D3DRENDERSTATE_AMBIENT, col); 00495 if (FAILED(hr)) 00496 Except(hr, "Error setting ambient light.", "D3DRenderSystem::setAmbientLight"); 00497 } 00498 00499 //----------------------------------------------------------------------- 00500 void D3DRenderSystem::setShadingType(ShadeOptions so) 00501 { 00502 D3DSHADEMODE d3dMode; 00503 switch(so) 00504 { 00505 case SO_FLAT: 00506 d3dMode = D3DSHADE_FLAT; 00507 break; 00508 case SO_GOURAUD: 00509 d3dMode = D3DSHADE_GOURAUD; 00510 break; 00511 case SO_PHONG: 00512 d3dMode = D3DSHADE_PHONG; 00513 break; 00514 00515 } 00516 00517 HRESULT hr = __SetRenderState(D3DRENDERSTATE_SHADEMODE, d3dMode); 00518 if (FAILED(hr)) 00519 Except(hr, "Error setting shading mode.", "D3DRenderSystem::setShadingType"); 00520 00521 } 00522 00523 00524 //----------------------------------------------------------------------- 00525 RenderWindow* D3DRenderSystem::createRenderWindow(const String &name, unsigned int width, unsigned int height, unsigned int colourDepth, 00526 bool fullScreen, int left, int top, bool depthBuffer, RenderWindow* parentWindowHandle) 00527 { 00528 static bool firstWindow = true; 00529 OgreGuard( "D3DRenderSystem::createRenderWindow" ); 00530 00531 String msg; 00532 00533 // Make sure we don't already have a render target of the 00534 // same name as the one supplied 00535 if( mRenderTargets.find( name ) != mRenderTargets.end() ) 00536 { 00537 msg = msg + "A render target of the same name (" + name + ") already " 00538 "exists. You cannot create a new window with this name."; 00539 Except(999,msg,"D3DRenderSystem::createRenderWindow"); 00540 } 00541 00542 RenderWindow* win = new D3D7RenderWindow(); 00543 // Create window, supplying DD interface & hInstance 00544 win->create(name, width, height, colourDepth, fullScreen, 00545 left, top, depthBuffer, &mhInstance, mActiveDDDriver, parentWindowHandle); 00546 00547 attachRenderTarget( *win ); 00548 00549 // If this is the first window, get the D3D device 00550 // and create the texture manager, setup caps 00551 if (firstWindow) 00552 { 00553 win->getCustomAttribute("D3DDEVICE", &mlpD3DDevice); 00554 // Get caps 00555 mlpD3DDevice->GetCaps(&mD3DDeviceDesc); 00556 // Create my texture manager for use by others 00557 // Note this is a Singleton; pointer is held static by superclass 00558 mTextureManager = new D3DTextureManager(mlpD3DDevice); 00559 00560 // Check for hardware stencil support 00561 // Get render target, then depth buffer and check format 00562 LPDIRECTDRAWSURFACE7 lpTarget; 00563 win->getCustomAttribute("DDBACKBUFFER", &lpTarget); 00564 DDSCAPS2 ddscaps; 00565 ZeroMemory(&ddscaps, sizeof(DDSCAPS2)); 00566 ddscaps.dwCaps = DDSCAPS_ZBUFFER; 00567 lpTarget->GetAttachedSurface(&ddscaps, &lpTarget); 00568 lpTarget->Release(); 00569 DDSURFACEDESC2 ddsd; 00570 ddsd.dwSize = sizeof(DDSURFACEDESC2); 00571 lpTarget->GetSurfaceDesc(&ddsd); 00572 DWORD stencil = ddsd.ddpfPixelFormat.dwStencilBitDepth; 00573 if(stencil > 0) 00574 { 00575 mCapabilities->setCapability(RSC_HWSTENCIL); 00576 mCapabilities->setStencilBufferBitDepth(stencil); 00577 if ((mD3DDeviceDesc.dwStencilCaps & D3DSTENCILCAPS_INCR) && 00578 (mD3DDeviceDesc.dwStencilCaps & D3DSTENCILCAPS_DECR)) 00579 mCapabilities->setCapability(RSC_STENCIL_WRAP); 00580 } 00581 00582 // Anisotropy? 00583 if (mD3DDeviceDesc.dwMaxAnisotropy > 1) 00584 mCapabilities->setCapability(RSC_ANISOTROPY); 00585 // Blending between stages supported 00586 mCapabilities->setCapability(RSC_BLENDING); 00587 // Cubemapping 00588 if (mD3DDeviceDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP) 00589 mCapabilities->setCapability(RSC_CUBEMAPPING); 00590 00591 // DOT3 00592 if (mD3DDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) 00593 mCapabilities->setCapability(RSC_DOT3); 00594 00595 // Set the number of texture units based on details from current device 00596 mCapabilities->setNumTextureUnits(mD3DDeviceDesc.wMaxSimultaneousTextures); 00597 00598 mCapabilities->log(LogManager::getSingleton().getDefaultLog()); 00599 00600 firstWindow = false; 00601 } 00602 00603 OgreUnguardRet( win ); 00604 } 00605 00606 RenderTexture * D3DRenderSystem::createRenderTexture( const String & name, unsigned int width, unsigned int height ) 00607 { 00608 RenderTexture * rt = new D3D7RenderTexture( name, width, height ); 00609 attachRenderTarget( *rt ); 00610 return rt; 00611 } 00612 00613 //----------------------------------------------------------------------- 00614 // Low-level overridden members 00615 //----------------------------------------------------------------------- 00616 //--------------------------------------------------------------------- 00617 void D3DRenderSystem::_useLights(const LightList& lights, unsigned short limit) 00618 { 00619 LightList::const_iterator i, iend; 00620 iend = lights.end(); 00621 unsigned short num = 0; 00622 for (i = lights.begin(); i != iend && num < limit; ++i, ++num) 00623 { 00624 setD3DLight(num, *i); 00625 } 00626 // Disable extra lights 00627 for (; num < mCurrentLights; ++num) 00628 { 00629 setD3DLight(num, NULL); 00630 } 00631 mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size())); 00632 00633 } 00634 //----------------------------------------------------------------------- 00635 void D3DRenderSystem::setD3DLight(size_t index, Light* lt) 00636 { 00637 // Add to D3D 00638 HRESULT hr; 00639 D3DLIGHT7 d3dLight; 00640 00641 if (!lt) 00642 { 00643 hr = mlpD3DDevice->LightEnable(index, FALSE); 00644 if (FAILED(hr)) 00645 Except(hr, "Unable to disable light.", "D3DRenderSystem::setD3DLight"); 00646 } 00647 else 00648 { 00649 switch (lt->getType()) 00650 { 00651 case Light::LT_POINT: 00652 d3dLight.dltType = D3DLIGHT_POINT; 00653 break; 00654 case Light::LT_DIRECTIONAL: 00655 d3dLight.dltType = D3DLIGHT_DIRECTIONAL; 00656 break; 00657 case Light::LT_SPOTLIGHT: 00658 d3dLight.dltType = D3DLIGHT_SPOT; 00659 d3dLight.dvFalloff = lt->getSpotlightFalloff(); 00660 d3dLight.dvTheta = Math::AngleUnitsToRadians(lt->getSpotlightInnerAngle()); 00661 d3dLight.dvPhi = Math::AngleUnitsToRadians(lt->getSpotlightOuterAngle()); 00662 break; 00663 } 00664 00665 // Colours 00666 ColourValue col; 00667 col = lt->getDiffuseColour(); 00668 d3dLight.dcvDiffuse.r = col.r; 00669 d3dLight.dcvDiffuse.g = col.g; 00670 d3dLight.dcvDiffuse.b = col.b; 00671 d3dLight.dcvDiffuse.a = col.a; 00672 00673 col = lt->getSpecularColour(); 00674 d3dLight.dcvSpecular.r = col.r; 00675 d3dLight.dcvSpecular.g = col.g; 00676 d3dLight.dcvSpecular.b = col.b; 00677 d3dLight.dcvSpecular.a = col.a; 00678 00679 // Never use ambient for a movable light 00680 d3dLight.dcvAmbient.r = 0.0; 00681 d3dLight.dcvAmbient.g = 0.0; 00682 d3dLight.dcvAmbient.b = 0.0; 00683 d3dLight.dcvAmbient.a = 0.0; 00684 00685 // Position (Irrelevant for directional) 00686 Vector3 vec; 00687 if (lt->getType() != Light::LT_DIRECTIONAL) 00688 { 00689 vec = lt->getDerivedPosition(); 00690 00691 d3dLight.dvPosition.x = vec.x; 00692 d3dLight.dvPosition.y = vec.y; 00693 d3dLight.dvPosition.z = vec.z; 00694 } 00695 // Direction (Irrelevant for point lights) 00696 if (lt->getType() != Light::LT_POINT) 00697 { 00698 vec = lt->getDerivedDirection(); 00699 d3dLight.dvDirection.x = vec.x; 00700 d3dLight.dvDirection.y = vec.y; 00701 d3dLight.dvDirection.z = vec.z; 00702 } 00703 // Attenuation parameters 00704 d3dLight.dvRange = lt->getAttenuationRange(); 00705 d3dLight.dvAttenuation0 = lt->getAttenuationConstant(); 00706 d3dLight.dvAttenuation1 = lt->getAttenuationLinear(); 00707 d3dLight.dvAttenuation2 = lt->getAttenuationQuadric(); 00708 00709 00710 00711 // Set light state 00712 hr = mlpD3DDevice->SetLight(index, &d3dLight); 00713 00714 if (FAILED(hr)) 00715 Except(hr, "Unable to set light details", "D3DRenderSystem::setD3DLight"); 00716 00717 hr = mlpD3DDevice->LightEnable(index, TRUE); 00718 if (FAILED(hr)) 00719 Except(hr, "Unable to enable light.", "D3DRenderSystem::setD3DLight"); 00720 } 00721 00722 00723 } 00724 //----------------------------------------------------------------------- 00725 D3DMATRIX D3DRenderSystem::makeD3DMatrix(const Matrix4& mat) 00726 { 00727 // Transpose matrix 00728 // D3D uses row vectors i.e. V*M 00729 // Ogre, OpenGL and everything else uses coloumn vectors i.e. M*V 00730 D3DMATRIX d3dMat; 00731 00732 d3dMat.m[0][0] = mat[0][0]; 00733 d3dMat.m[0][1] = mat[1][0]; 00734 d3dMat.m[0][2] = mat[2][0]; 00735 d3dMat.m[0][3] = mat[3][0]; 00736 00737 d3dMat.m[1][0] = mat[0][1]; 00738 d3dMat.m[1][1] = mat[1][1]; 00739 d3dMat.m[1][2] = mat[2][1]; 00740 d3dMat.m[1][3] = mat[3][1]; 00741 00742 d3dMat.m[2][0] = mat[0][2]; 00743 d3dMat.m[2][1] = mat[1][2]; 00744 d3dMat.m[2][2] = mat[2][2]; 00745 d3dMat.m[2][3] = mat[3][2]; 00746 00747 d3dMat.m[3][0] = mat[0][3]; 00748 d3dMat.m[3][1] = mat[1][3]; 00749 d3dMat.m[3][2] = mat[2][3]; 00750 d3dMat.m[3][3] = mat[3][3]; 00751 00752 return d3dMat; 00753 } 00754 00755 Matrix4 D3DRenderSystem::convertD3DMatrix(const D3DMATRIX& d3dmat) 00756 { 00757 // The reverse of makeD3DMatrix 00758 // Transpose matrix 00759 // D3D uses row vectors i.e. V*M 00760 // Ogre, OpenGL and everything else uses coloumn vectors i.e. M*V 00761 Matrix4 mat; 00762 for (unsigned row = 0; row < 4; ++row) 00763 for (unsigned col = 0; col < 4; ++col) 00764 mat[col][row] = d3dmat.m[row][col]; 00765 00766 return mat; 00767 00768 00769 } 00770 //----------------------------------------------------------------------- 00771 void D3DRenderSystem::_setWorldMatrix(const Matrix4 &m) 00772 { 00773 D3DMATRIX d3dmat; 00774 00775 d3dmat = makeD3DMatrix(m); 00776 00777 HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &d3dmat); 00778 00779 if (FAILED(hr)) 00780 Except(hr, "Cannot set D3D world matrix", 00781 "D3DRenderSystem::_setWorldMatrix"); 00782 } 00783 00784 //----------------------------------------------------------------------- 00785 void D3DRenderSystem::_setViewMatrix(const Matrix4 &m) 00786 { 00787 // save latest view matrix 00788 mViewMatrix = m; 00789 mViewMatrix[2][0] = -mViewMatrix[2][0]; 00790 mViewMatrix[2][1] = -mViewMatrix[2][1]; 00791 mViewMatrix[2][2] = -mViewMatrix[2][2]; 00792 mViewMatrix[2][3] = -mViewMatrix[2][3]; 00793 00794 D3DMATRIX d3dmat = makeD3DMatrix(mViewMatrix); 00795 00796 HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &d3dmat); 00797 00798 if (FAILED(hr)) 00799 Except(hr, "Cannot set D3D view matrix", 00800 "D3DRenderSystem::_setViewMatrix"); 00801 00802 } 00803 //----------------------------------------------------------------------- 00804 void D3DRenderSystem::_setProjectionMatrix(const Matrix4 &m) 00805 { 00806 D3DMATRIX d3dmat = makeD3DMatrix(m); 00807 00808 if( mActiveRenderTarget->requiresTextureFlipping() ) 00809 { 00810 d3dmat._22 = - d3dmat._22; 00811 } 00812 00813 HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &d3dmat); 00814 00815 if (FAILED(hr)) 00816 Except(hr, "Cannot set D3D projection matrix", 00817 "D3DRenderSystem::_setProjectionMatrix"); 00818 } 00819 00820 00821 //----------------------------------------------------------------------- 00822 void D3DRenderSystem::_setSurfaceParams(const ColourValue &ambient, 00823 const ColourValue &diffuse, const ColourValue &specular, 00824 const ColourValue &emissive, const Real shininess) 00825 { 00826 // Remember last call 00827 static ColourValue lastAmbient = ColourValue::Black; 00828 static ColourValue lastDiffuse = ColourValue::Black; 00829 static ColourValue lastSpecular = ColourValue::Black; 00830 static ColourValue lastEmissive = ColourValue::Black; 00831 static Real lastShininess = 0.0; 00832 00833 // Only update if changed 00834 if (ambient != lastAmbient || diffuse != lastDiffuse || 00835 specular != lastSpecular || emissive != lastEmissive || 00836 shininess != lastShininess) 00837 { 00838 00839 // Convert to D3D 00840 D3DMATERIAL7 d3dMat; 00841 00842 d3dMat.dcvDiffuse.r = diffuse.r; 00843 d3dMat.dcvDiffuse.g = diffuse.g; 00844 d3dMat.dcvDiffuse.b = diffuse.b; 00845 d3dMat.dcvDiffuse.a = diffuse.a; 00846 00847 d3dMat.dcvAmbient.r = ambient.r; 00848 d3dMat.dcvAmbient.g = ambient.g; 00849 d3dMat.dcvAmbient.b = ambient.b; 00850 d3dMat.dcvAmbient.a = ambient.a; 00851 00852 d3dMat.dcvSpecular.r = specular.r; 00853 d3dMat.dcvSpecular.g = specular.g; 00854 d3dMat.dcvSpecular.b = specular.b; 00855 d3dMat.dcvSpecular.a = specular.a; 00856 00857 d3dMat.dcvEmissive.r = emissive.r; 00858 d3dMat.dcvEmissive.g = emissive.g; 00859 d3dMat.dcvEmissive.b = emissive.b; 00860 d3dMat.dcvEmissive.a = emissive.a; 00861 00862 d3dMat.dvPower = shininess; 00863 00864 HRESULT hr = mlpD3DDevice->SetMaterial(&d3dMat); 00865 if (FAILED(hr)) 00866 Except(hr, "Error setting D3D material.", "D3DRenderSystem::_setSurfaceParams"); 00867 00868 } 00869 } 00870 //----------------------------------------------------------------------- 00871 void D3DRenderSystem::_setTexture(size_t stage, bool enabled, const String &texname) 00872 { 00873 HRESULT hr; 00874 D3DTexture* dt = static_cast< D3DTexture* >(TextureManager::getSingleton().getByName(texname)); 00875 if (enabled && dt) 00876 { 00877 LPDIRECTDRAWSURFACE7 pTex = dt->getDDSurface(); 00878 if (pTex != mTexStageDesc[stage].pTex) 00879 { 00880 hr = mlpD3DDevice->SetTexture(stage, pTex ); 00881 if (FAILED(hr)) 00882 Except(hr, "Unable to set texture in D3D.", "D3DRenderSystem::_setTexture"); 00883 00884 // set stage desc. 00885 mTexStageDesc[stage].texType = _ogreTexTypeToD3DTexType(dt->getTextureType()); 00886 mTexStageDesc[stage].pTex = pTex; 00887 } 00888 } 00889 else 00890 { 00891 hr = mlpD3DDevice->SetTexture(stage, 0); 00892 if (FAILED(hr)) 00893 Except(hr, "Unable to disable texture in D3D.", "D3DRenderSystem::_setTexture"); 00894 hr = __SetTextureStageState( stage, D3DTSS_COLOROP, D3DTOP_DISABLE ); 00895 if (FAILED(hr)) 00896 Except(hr, "Unable to disable texture in D3D.", "D3DRenderSystem::_setTexture"); 00897 00898 // set stage desc. to defaults 00899 mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE; 00900 mTexStageDesc[stage].coordIndex = 0; 00901 mTexStageDesc[stage].texType = D3D_TEX_TYPE_NORMAL; 00902 mTexStageDesc[stage].pTex = NULL; 00903 } 00904 } 00905 //----------------------------------------------------------------------- 00906 void D3DRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m, 00907 const Frustum* frustum) 00908 { 00909 HRESULT hr = S_OK; 00910 // record the stage state 00911 mTexStageDesc[stage].autoTexCoordType = m; 00912 mTexStageDesc[stage].frustum = frustum; 00913 00914 switch( m ) 00915 { 00916 case TEXCALC_NONE: 00917 // if no calc we've already set index through D3D9RenderSystem::_setTextureCoordSet 00918 break; 00919 case TEXCALC_ENVIRONMENT_MAP: 00920 // D3D7 does not support spherical reflection 00921 hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL ); 00922 break; 00923 case TEXCALC_ENVIRONMENT_MAP_REFLECTION: 00924 hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR ); 00925 break; 00926 case TEXCALC_ENVIRONMENT_MAP_PLANAR: 00927 case TEXCALC_PROJECTIVE_TEXTURE: 00928 hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION ); 00929 break; 00930 case TEXCALC_ENVIRONMENT_MAP_NORMAL: 00931 hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL ); 00932 break; 00933 } 00934 if( FAILED( hr ) ) 00935 Except( hr, "Error setting texture coord calculation", "D3DRenderSystem::_setTextureCoordCalculation" ); 00936 00937 } 00938 //----------------------------------------------------------------------- 00939 void D3DRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xForm) 00940 { 00941 HRESULT hr; 00942 D3DMATRIX d3dMat; // the matrix we'll maybe apply 00943 Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format 00944 00945 00946 /* If envmap is applied, since D3D7 doesn't support spheremap, 00947 then we have to use texture transform to make the camera space normal 00948 reference the envmap properly. This isn't exactly the same as spheremap 00949 (it looks nasty on flat areas because the camera space normals are the same) 00950 but it's the best approximation we have in the absence of a proper spheremap */ 00951 if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP) 00952 { 00953 // concatenate with the xForm 00954 newMat = newMat.concatenate(Matrix4::CLIPSPACE2DTOIMAGESPACE); 00955 } 00956 00957 // If this is a cubic reflection, we need to modify using the view matrix 00958 if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION) 00959 { 00960 D3DMATRIX viewMatrix; 00961 00962 // Get view matrix 00963 mlpD3DDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, &viewMatrix); 00964 // Get transposed 3x3, ie since D3D is transposed just copy 00965 // We want to transpose since that will invert an orthonormal matrix ie rotation 00966 Matrix4 ogreViewTransposed; 00967 ogreViewTransposed[0][0] = viewMatrix.m[0][0]; 00968 ogreViewTransposed[0][1] = viewMatrix.m[0][1]; 00969 ogreViewTransposed[0][2] = viewMatrix.m[0][2]; 00970 ogreViewTransposed[0][3] = 0.0f; 00971 00972 ogreViewTransposed[1][0] = viewMatrix.m[1][0]; 00973 ogreViewTransposed[1][1] = viewMatrix.m[1][1]; 00974 ogreViewTransposed[1][2] = viewMatrix.m[1][2]; 00975 ogreViewTransposed[1][3] = 0.0f; 00976 00977 ogreViewTransposed[2][0] = viewMatrix.m[2][0]; 00978 ogreViewTransposed[2][1] = viewMatrix.m[2][1]; 00979 ogreViewTransposed[2][2] = viewMatrix.m[2][2]; 00980 ogreViewTransposed[2][3] = 0.0f; 00981 00982 ogreViewTransposed[3][0] = 0.0f; 00983 ogreViewTransposed[3][1] = 0.0f; 00984 ogreViewTransposed[3][2] = 0.0f; 00985 ogreViewTransposed[3][3] = 1.0f; 00986 00987 newMat = newMat.concatenate(ogreViewTransposed); 00988 } 00989 00990 if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE) 00991 { 00992 // Derive camera space to projector space transform 00993 // To do this, we need to undo the camera view matrix, then 00994 // apply the projector view & projection matrices 00995 newMat = mViewMatrix.inverse() * newMat; 00996 newMat = mTexStageDesc[stage].frustum->getViewMatrix() * newMat; 00997 newMat = mTexStageDesc[stage].frustum->getProjectionMatrix() * newMat; 00998 if (mTexStageDesc[stage].frustum->getProjectionType() == PT_PERSPECTIVE) 00999 { 01000 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * newMat; 01001 } 01002 else 01003 { 01004 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO * newMat; 01005 } 01006 01007 } 01008 01009 // convert our matrix to D3D format 01010 d3dMat = makeD3DMatrix(newMat); 01011 01012 // need this if texture is a cube map, to invert D3D's z coord 01013 if (mTexStageDesc[stage].autoTexCoordType != TEXCALC_NONE) 01014 { 01015 d3dMat._13 = -d3dMat._13; 01016 d3dMat._23 = -d3dMat._23; 01017 d3dMat._33 = -d3dMat._33; 01018 d3dMat._43 = -d3dMat._43; 01019 } 01020 01021 // set the matrix if it's not the identity 01022 if (!(newMat == Matrix4::IDENTITY)) 01023 { 01024 // tell D3D the dimension of tex. coord. 01025 int texCoordDim; 01026 if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE) 01027 { 01028 texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT3; 01029 } 01030 else 01031 { 01032 switch (mTexStageDesc[stage].texType) 01033 { 01034 case D3D_TEX_TYPE_NORMAL: 01035 texCoordDim = D3DTTFF_COUNT2; 01036 break; 01037 case D3D_TEX_TYPE_CUBE: 01038 case D3D_TEX_TYPE_VOLUME: 01039 texCoordDim = D3DTTFF_COUNT3; 01040 } 01041 } 01042 01043 hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim ); 01044 if (FAILED(hr)) 01045 Except( hr, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" ); 01046 01047 hr = mlpD3DDevice->SetTransform( 01048 (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + stage), &d3dMat ); 01049 if (FAILED(hr)) 01050 Except( hr, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" ); 01051 } 01052 else 01053 { 01054 // disable all of this 01055 hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); 01056 if( FAILED( hr ) ) 01057 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" ); 01058 01059 // set the identity matrix 01060 D3DUtil_SetIdentityMatrix( d3dMat ); 01061 hr = mlpD3DDevice->SetTransform( 01062 (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + stage), &d3dMat ); 01063 if( FAILED( hr ) ) 01064 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" ); 01065 } 01066 } 01067 //--------------------------------------------------------------------- 01068 void D3DRenderSystem::_setTextureCoordSet( size_t stage, size_t index ) 01069 { 01070 HRESULT hr; 01071 hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, index ); 01072 if( FAILED( hr ) ) 01073 Except( hr, "Unable to set texture coord. set index", "D3DRenderSystem::_setTextureCoordSet" ); 01074 // Record settings 01075 mTexStageDesc[stage].coordIndex = index; 01076 } 01077 //----------------------------------------------------------------------- 01078 void D3DRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm) 01079 { 01080 HRESULT hr; 01081 D3DTEXTURESTAGESTATETYPE tss; 01082 DWORD value; 01083 01084 if (bm.blendType == LBT_COLOUR) 01085 { 01086 tss = D3DTSS_COLOROP; 01087 } 01088 else if (bm.blendType == LBT_ALPHA) 01089 { 01090 tss= D3DTSS_ALPHAOP; 01091 } 01092 01093 switch (bm.operation) 01094 { 01095 case LBX_SOURCE1: 01096 value = D3DTOP_SELECTARG1; 01097 break; 01098 case LBX_SOURCE2: 01099 value = D3DTOP_SELECTARG2; 01100 break; 01101 case LBX_MODULATE: 01102 value = D3DTOP_MODULATE; 01103 break; 01104 case LBX_MODULATE_X2: 01105 value = D3DTOP_MODULATE2X; 01106 break; 01107 case LBX_MODULATE_X4: 01108 value = D3DTOP_MODULATE4X; 01109 break; 01110 case LBX_ADD: 01111 value = D3DTOP_ADD; 01112 break; 01113 case LBX_ADD_SIGNED: 01114 value = D3DTOP_ADDSIGNED; 01115 break; 01116 case LBX_ADD_SMOOTH: 01117 value = D3DTOP_ADDSMOOTH; 01118 break; 01119 case LBX_SUBTRACT: 01120 value = D3DTOP_SUBTRACT; 01121 break; 01122 case LBX_BLEND_DIFFUSE_ALPHA: 01123 value = D3DTOP_BLENDDIFFUSEALPHA; 01124 break; 01125 case LBX_BLEND_TEXTURE_ALPHA: 01126 value = D3DTOP_BLENDTEXTUREALPHA; 01127 break; 01128 case LBX_BLEND_CURRENT_ALPHA: 01129 value = D3DTOP_BLENDCURRENTALPHA; 01130 break; 01131 case LBX_BLEND_MANUAL: 01132 value = D3DTOP_BLENDFACTORALPHA; 01133 // Set factor in render state 01134 hr = __SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, 01135 D3DRGBA(0,0,0,bm.factor)); 01136 break; 01137 case LBX_DOTPRODUCT: 01138 if (mD3DDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) 01139 value = D3DTOP_DOTPRODUCT3; 01140 else 01141 value = D3DTOP_MODULATE; 01142 break; 01143 } 01144 01145 // Make call to set operation 01146 hr = __SetTextureStageState(stage, tss, value); 01147 01148 // Now set up sources 01149 D3DCOLOR manualD3D; 01150 if (bm.blendType == LBT_COLOUR) 01151 { 01152 tss = D3DTSS_COLORARG1; 01153 manualD3D = D3DRGBA(bm.colourArg1.r,bm.colourArg1.g,bm.colourArg1.b,1.0); 01154 } 01155 else if (bm.blendType == LBT_ALPHA) 01156 { 01157 tss = D3DTSS_ALPHAARG1; 01158 manualD3D = D3DRGBA(0,0,0,bm.alphaArg1); 01159 } 01160 LayerBlendSource bs = bm.source1; 01161 for (int i = 0; i < 2; ++i) 01162 { 01163 switch (bs) 01164 { 01165 case LBS_CURRENT: 01166 value = D3DTA_CURRENT; 01167 break; 01168 case LBS_TEXTURE: 01169 value = D3DTA_TEXTURE; 01170 break; 01171 case LBS_DIFFUSE: 01172 value = D3DTA_DIFFUSE; 01173 break; 01174 case LBS_SPECULAR: 01175 value = D3DTA_SPECULAR; 01176 break; 01177 case LBS_MANUAL: 01178 value = D3DTA_TFACTOR; 01179 // Set factor in render state 01180 hr = __SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, manualD3D); 01181 break; 01182 } 01183 01184 // Set source 01185 hr = __SetTextureStageState(stage, tss, value); 01186 01187 // Source2 01188 bs = bm.source2; 01189 if (bm.blendType == LBT_COLOUR) 01190 { 01191 tss = D3DTSS_COLORARG2; 01192 manualD3D = D3DRGBA(bm.colourArg2.r,bm.colourArg2.g,bm.colourArg2.b,1.0); 01193 } 01194 else if (bm.blendType == LBT_ALPHA) 01195 { 01196 tss = D3DTSS_ALPHAARG2; 01197 manualD3D = D3DRGBA(0,0,0,bm.alphaArg2); 01198 } 01199 } 01200 } 01201 //----------------------------------------------------------------------- 01202 void D3DRenderSystem::_setTextureAddressingMode(size_t stage, TextureUnitState::TextureAddressingMode tam) 01203 { 01204 HRESULT hr; 01205 D3DTEXTUREADDRESS d3dType; 01206 01207 switch(tam) 01208 { 01209 case TextureUnitState::TAM_WRAP: 01210 d3dType = D3DTADDRESS_WRAP; 01211 break; 01212 case TextureUnitState::TAM_MIRROR: 01213 d3dType = D3DTADDRESS_MIRROR; 01214 break; 01215 case TextureUnitState::TAM_CLAMP: 01216 d3dType = D3DTADDRESS_CLAMP; 01217 break; 01218 } 01219 01220 01221 hr = __SetTextureStageState(stage, D3DTSS_ADDRESS, d3dType); 01222 } 01223 //----------------------------------------------------------------------- 01224 void D3DRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor) 01225 { 01226 HRESULT hr; 01227 D3DBLEND d3dSrcBlend, d3dDestBlend; 01228 01229 D3DBLEND* pBlend = &d3dSrcBlend; 01230 SceneBlendFactor ogreBlend = sourceFactor; 01231 01232 for (int i = 0 ; i < 2; ++i) 01233 { 01234 switch(ogreBlend) 01235 { 01236 case SBF_ONE: 01237 *pBlend = D3DBLEND_ONE; 01238 break; 01239 case SBF_ZERO: 01240 *pBlend = D3DBLEND_ZERO; 01241 break; 01242 case SBF_DEST_COLOUR: 01243 *pBlend = D3DBLEND_DESTCOLOR; 01244 break; 01245 case SBF_SOURCE_COLOUR: 01246 *pBlend = D3DBLEND_SRCCOLOR; 01247 break; 01248 case SBF_ONE_MINUS_DEST_COLOUR: 01249 *pBlend = D3DBLEND_INVDESTCOLOR; 01250 break; 01251 case SBF_ONE_MINUS_SOURCE_COLOUR: 01252 *pBlend = D3DBLEND_INVSRCCOLOR; 01253 break; 01254 case SBF_DEST_ALPHA: 01255 *pBlend = D3DBLEND_DESTALPHA; 01256 break; 01257 case SBF_SOURCE_ALPHA: 01258 *pBlend = D3DBLEND_SRCALPHA; 01259 break; 01260 case SBF_ONE_MINUS_DEST_ALPHA: 01261 *pBlend = D3DBLEND_INVDESTALPHA; 01262 break; 01263 case SBF_ONE_MINUS_SOURCE_ALPHA: 01264 *pBlend = D3DBLEND_INVSRCALPHA; 01265 break; 01266 } 01267 ogreBlend = destFactor; 01268 pBlend = &d3dDestBlend; 01269 01270 } 01271 01272 hr = __SetRenderState(D3DRENDERSTATE_SRCBLEND, d3dSrcBlend); 01273 01274 hr = __SetRenderState(D3DRENDERSTATE_DESTBLEND, d3dDestBlend); 01275 01276 // Save last scene blend, because colour write off is simulated 01277 // through scene blend 01278 mSavedDestFactor = destFactor; 01279 mSavedSrcFactor = sourceFactor; 01280 01281 01282 } 01283 //----------------------------------------------------------------------- 01284 void D3DRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value) 01285 { 01286 HRESULT hr; 01287 if (func != CMPF_ALWAYS_PASS) 01288 { 01289 if( FAILED( hr = __SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, TRUE ) ) ) 01290 Except( hr, "Failed to enable alpha testing", 01291 "D3DRenderSystem::_setAlphaRejectSettings" ); 01292 } 01293 else 01294 { 01295 if( FAILED( hr = __SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE ) ) ) 01296 Except( hr, "Failed to disable alpha testing", 01297 "D3DRenderSystem::_setAlphaRejectSettings" ); 01298 } 01299 01300 // Set always just be sure 01301 hr = __SetRenderState(D3DRENDERSTATE_ALPHAFUNC, 01302 convertCompareFunction(func)); 01303 01304 hr = __SetRenderState(D3DRENDERSTATE_ALPHAREF, value); 01305 } 01306 //----------------------------------------------------------------------- 01307 void D3DRenderSystem::_setViewport(Viewport *vp) 01308 { 01309 // Check if viewport is different 01310 if (vp != mActiveViewport || vp->_isUpdated()) 01311 { 01312 mActiveViewport = vp; 01313 mActiveRenderTarget = vp->getTarget(); 01314 // Ok, it's different. Time to set render target (maybe) 01315 // and viewport params. 01316 D3DVIEWPORT7 d3dvp; 01317 HRESULT hr; 01318 01319 // Set render target 01320 // TODO - maybe only set when required? 01321 RenderTarget* target; 01322 target = vp->getTarget(); 01323 // Get DD Back buffer 01324 LPDIRECTDRAWSURFACE7 pBack; 01325 target->getCustomAttribute("DDBACKBUFFER", &pBack); 01326 01327 hr = mlpD3DDevice->SetRenderTarget( pBack, 0 ); 01328 01329 _setCullingMode( mCullingMode ); 01330 01331 // Set viewport dimensions 01332 d3dvp.dwX = vp->getActualLeft(); 01333 d3dvp.dwY = vp->getActualTop(); 01334 d3dvp.dwWidth = vp->getActualWidth(); 01335 d3dvp.dwHeight = vp->getActualHeight(); 01336 01337 // Z-values from 0.0 to 1.0 (TODO - standardise with OpenGL?) 01338 d3dvp.dvMinZ = 0.0f; 01339 d3dvp.dvMaxZ = 1.0f; 01340 01341 hr = mlpD3DDevice->SetViewport(&d3dvp); 01342 01343 if (FAILED(hr)) 01344 Except(hr, "Error setting D3D viewport.", 01345 "D3DRenderSystem::_setViewport"); 01346 01347 vp->_clearUpdatedFlag(); 01348 01349 } 01350 } 01351 01352 //----------------------------------------------------------------------- 01353 void D3DRenderSystem::_beginFrame(void) 01354 { 01355 OgreGuard( "D3DRenderSystem::_beginFrame" ); 01356 01357 HRESULT hr; 01358 01359 if (!mActiveViewport) 01360 Except(999, "Cannot begin frame - no viewport selected.", 01361 "D3DRenderSystem::_beginFrame"); 01362 01363 // Clear the viewport if required 01364 if (mActiveViewport->getClearEveryFrame()) 01365 { 01366 clearFrameBuffer(FBT_COLOUR | FBT_DEPTH, 01367 mActiveViewport->getBackgroundColour()); 01368 } 01369 01370 hr = mlpD3DDevice->BeginScene(); 01371 if (FAILED(hr)) 01372 Except(hr, "Error beginning frame.", 01373 "D3DRenderSystem::_beginFrame"); 01374 01375 // Moved here from _render, no point checking every rendering call 01376 static bool firstTime = true; 01377 if (firstTime) 01378 { 01379 // First-time setup 01380 // Set up some defaults 01381 01382 // Allow alpha blending 01383 hr = __SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE); 01384 if (FAILED(hr)) 01385 Except(hr, "Error enabling alpha blending option.", 01386 "D3DRenderSystem::_beginFrame"); 01387 01388 // Allow specular effects 01389 hr = __SetRenderState(D3DRENDERSTATE_SPECULARENABLE, TRUE); 01390 if (FAILED(hr)) 01391 Except(hr, "Error enabling specular option.", 01392 "D3DRenderSystem::_beginFrame"); 01393 01394 firstTime = false; 01395 } 01396 01397 OgreUnguard(); 01398 } 01399 01400 //----------------------------------------------------------------------- 01401 void D3DRenderSystem::_render(const RenderOperation& op) 01402 { 01403 OgreGuard( "D3DRenderSystem::_render" ); 01404 HRESULT hr; 01405 01406 // Exit immediately if there is nothing to render 01407 // This caused a problem on FireGL 8800 01408 if (op.vertexData->vertexCount == 0) 01409 return; 01410 01411 // call superclass 01412 RenderSystem::_render(op); 01413 // Set up vertex flags 01414 DWORD d3dVertexFormat = 0; 01415 unsigned int numTexCoords = 0; 01416 01417 // Assume no more than 10 buffers! 01418 static unsigned char* pBufPtrs[10]; 01419 01420 // Lock all the buffers first 01421 // They're system memory buffers anyway 01422 const VertexBufferBinding::VertexBufferBindingMap binds = 01423 op.vertexData->vertexBufferBinding->getBindings(); 01424 VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi, bindend; 01425 bindend = binds.end(); 01426 for (bindi = binds.begin(); bindi != bindend; ++bindi) 01427 { 01428 // lock from vertex start only 01429 pBufPtrs[bindi->first] = static_cast<unsigned char*>( 01430 bindi->second->lock( 01431 op.vertexData->vertexStart * bindi->second->getVertexSize(), 01432 op.vertexData->vertexCount * bindi->second->getVertexSize(), 01433 HardwareBuffer::HBL_READ_ONLY) 01434 ); 01435 01436 } 01437 01438 // Determine vertex format 01439 01440 // Struct for data pointers 01441 D3DDRAWPRIMITIVESTRIDEDDATA strideData; 01442 01443 // Iterate over elements 01444 VertexDeclaration::VertexElementList::const_iterator elemi, elemend; 01445 const VertexDeclaration::VertexElementList elems = 01446 op.vertexData->vertexDeclaration->getElements(); 01447 elemend = elems.end(); 01448 for (elemi = elems.begin(); elemi != elemend; ++elemi) 01449 { 01450 // Get a few basic details 01451 const VertexElement& elem = *elemi; 01452 unsigned short source = elem.getSource(); 01453 size_t vertexSize = op.vertexData->vertexDeclaration->getVertexSize(source); 01454 size_t offset = elem.getOffset(); 01455 // semantic-specific stuff 01456 switch (elem.getSemantic()) 01457 { 01458 case VES_POSITION: 01459 d3dVertexFormat |= D3DFVF_XYZ; // Untransformed 01460 strideData.position.lpvData = pBufPtrs[source] + offset; 01461 strideData.position.dwStride = static_cast<DWORD>(vertexSize); 01462 // Set up pointer 01463 break; 01464 case VES_NORMAL: 01465 d3dVertexFormat |= D3DFVF_NORMAL; 01466 strideData.normal.lpvData = pBufPtrs[source] + offset; 01467 strideData.normal.dwStride = static_cast<DWORD>(vertexSize); 01468 break; 01469 case VES_DIFFUSE: 01470 d3dVertexFormat |= D3DFVF_DIFFUSE; 01471 strideData.diffuse.lpvData = pBufPtrs[source] + offset; 01472 strideData.diffuse.dwStride = static_cast<DWORD>(vertexSize); 01473 break; 01474 case VES_SPECULAR: 01475 d3dVertexFormat |= D3DFVF_SPECULAR; 01476 strideData.specular.lpvData = pBufPtrs[source] + offset; 01477 strideData.specular.dwStride = static_cast<DWORD>(vertexSize); 01478 break; 01479 case VES_TEXTURE_COORDINATES: 01480 // texcoords must go in order 01481 if (elem.getIndex() != numTexCoords) 01482 { 01483 Except(Exception::ERR_INVALIDPARAMS, "Invalid vertex format, texture coordinates" 01484 " must be in order wih no gaps.", "D3DRenderSystem::_render"); 01485 } 01486 // Don't add D3DFVF_TEXn flag here, wait until we know how many total 01487 // However, specify size 01488 switch (elem.getType()) 01489 { 01490 case VET_FLOAT1: 01491 d3dVertexFormat |= D3DFVF_TEXCOORDSIZE1(numTexCoords); 01492 break; 01493 case VET_FLOAT2: 01494 d3dVertexFormat |= D3DFVF_TEXCOORDSIZE2(numTexCoords); 01495 break; 01496 case VET_FLOAT3: 01497 d3dVertexFormat |= D3DFVF_TEXCOORDSIZE3(numTexCoords); 01498 break; 01499 case VET_FLOAT4: 01500 d3dVertexFormat |= D3DFVF_TEXCOORDSIZE4(numTexCoords); 01501 break; 01502 } 01503 01504 strideData.textureCoords[numTexCoords].lpvData = pBufPtrs[source] + offset; 01505 strideData.textureCoords[numTexCoords].dwStride = static_cast<DWORD>(vertexSize); 01506 01507 // Increment number of coords 01508 ++numTexCoords; 01509 } 01510 01511 } 01512 // Add combined texture flag 01513 switch(numTexCoords) 01514 { 01515 case 0: 01516 // do nothing 01517 break; 01518 case 1: 01519 d3dVertexFormat |= D3DFVF_TEX1; 01520 break; 01521 case 2: 01522 d3dVertexFormat |= D3DFVF_TEX2; 01523 break; 01524 case 3: 01525 d3dVertexFormat |= D3DFVF_TEX3; 01526 break; 01527 case 4: 01528 d3dVertexFormat |= D3DFVF_TEX4; 01529 break; 01530 case 5: 01531 d3dVertexFormat |= D3DFVF_TEX5; 01532 break; 01533 case 6: 01534 d3dVertexFormat |= D3DFVF_TEX6; 01535 break; 01536 case 7: 01537 d3dVertexFormat |= D3DFVF_TEX7; 01538 break; 01539 case 8: 01540 d3dVertexFormat |= D3DFVF_TEX8; 01541 break; 01542 } 01543 01544 // Determine rendering operation 01545 D3DPRIMITIVETYPE primType; 01546 switch (op.operationType) 01547 { 01548 case RenderOperation::OT_POINT_LIST: 01549 primType = D3DPT_POINTLIST; 01550 break; 01551 case RenderOperation::OT_LINE_LIST: 01552 primType = D3DPT_LINELIST; 01553 break; 01554 case RenderOperation::OT_LINE_STRIP: 01555 primType = D3DPT_LINESTRIP; 01556 break; 01557 case RenderOperation::OT_TRIANGLE_LIST: 01558 primType = D3DPT_TRIANGLELIST; 01559 break; 01560 case RenderOperation::OT_TRIANGLE_STRIP: 01561 primType = D3DPT_TRIANGLESTRIP; 01562 break; 01563 case RenderOperation::OT_TRIANGLE_FAN: 01564 primType = D3DPT_TRIANGLEFAN; 01565 break; 01566 } 01567 01568 01569 if (op.useIndexes) 01570 { 01571 // Get pointer to index buffer 01572 // D3D7 only allows 16-bit indexes, this is enforced in buffer manager 01573 unsigned short* pIdx = static_cast<unsigned short*>( 01574 op.indexData->indexBuffer->lock( 01575 op.indexData->indexStart, 01576 op.indexData->indexCount * sizeof(unsigned short), 01577 HardwareBuffer::HBL_READ_ONLY) ); 01578 01579 hr = mlpD3DDevice->DrawIndexedPrimitiveStrided(primType, 01580 d3dVertexFormat, 01581 &strideData, 01582 static_cast<DWORD>(op.vertexData->vertexCount), 01583 pIdx, 01584 static_cast<DWORD>(op.indexData->indexCount) 01585 , 0); 01586 } 01587 else 01588 { 01589 hr = mlpD3DDevice->DrawPrimitiveStrided(primType, 01590 d3dVertexFormat, 01591 &strideData, 01592 static_cast<DWORD>(op.vertexData->vertexCount), 01593 0); 01594 } 01595 01596 // unlock buffers 01597 for (bindi = binds.begin(); bindi != bindend; ++bindi) 01598 { 01599 bindi->second->unlock(); 01600 } 01601 01602 if (FAILED(hr)) 01603 { 01604 char szBuffer[512]; 01605 D3DXGetErrorString( hr, 512, szBuffer ); 01606 Except( hr, szBuffer, "D3DRenderSystem::_render"); 01607 } 01608 01609 01610 01611 01612 OgreUnguard(); 01613 } 01614 01615 //----------------------------------------------------------------------- 01616 void D3DRenderSystem::_endFrame(void) 01617 { 01618 OgreGuard( "D3DRenderSystem::_endFrame" ); 01619 01620 HRESULT hr; 01621 hr = mlpD3DDevice->EndScene(); 01622 01623 if (FAILED(hr)) 01624 Except(hr, "Error ending frame.", 01625 "D3DRenderSystem::_endFrame"); 01626 01627 OgreUnguard(); 01628 } 01629 01630 //----------------------------------------------------------------------- 01631 void D3DRenderSystem::_setCullingMode(CullingMode mode) 01632 { 01633 HRESULT hr; 01634 DWORD d3dMode; 01635 01636 mCullingMode = mode; 01637 01638 if (mode == CULL_NONE) 01639 { 01640 d3dMode = D3DCULL_NONE; 01641 } 01642 else if( mode == CULL_CLOCKWISE ) 01643 { 01644 if( (mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) || 01645 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)) 01646 d3dMode = D3DCULL_CCW; 01647 else 01648 d3dMode = D3DCULL_CW; 01649 } 01650 else if (mode == CULL_ANTICLOCKWISE) 01651 { 01652 if( (mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) || 01653 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding)) 01654 d3dMode = D3DCULL_CW; 01655 else 01656 d3dMode = D3DCULL_CCW; 01657 } 01658 01659 hr = __SetRenderState(D3DRENDERSTATE_CULLMODE, d3dMode); 01660 if (FAILED(hr)) 01661 Except(hr, "Unable to set D3D culling mode.", 01662 "D3DRenderSystem::_setCullingMode"); 01663 01664 } 01665 01666 //----------------------------------------------------------------------- 01667 void D3DRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction) 01668 { 01669 _setDepthBufferCheckEnabled(depthTest); 01670 _setDepthBufferWriteEnabled(depthWrite); 01671 _setDepthBufferFunction(depthFunction); 01672 01673 } 01674 //----------------------------------------------------------------------- 01675 void D3DRenderSystem::_setDepthBufferCheckEnabled(bool enabled) 01676 { 01677 HRESULT hr; 01678 01679 if (enabled) 01680 { 01681 // Use w-buffer if available 01682 if (mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_WBUFFER) 01683 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_USEW); 01684 else 01685 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); 01686 if (FAILED(hr)) 01687 Except(hr, "Error setting depth buffer test state.", 01688 "D3DRenderSystem::_setDepthBufferCheckEnabled"); 01689 } 01690 else 01691 { 01692 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); 01693 if (FAILED(hr)) 01694 Except(hr, "Error setting depth buffer test state.", 01695 "D3DRenderSystem::_setDepthBufferCheckEnabled"); 01696 } 01697 } 01698 //----------------------------------------------------------------------- 01699 void D3DRenderSystem::_setDepthBufferWriteEnabled(bool enabled) 01700 { 01701 HRESULT hr; 01702 01703 hr = __SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, enabled); 01704 if (FAILED(hr)) 01705 Except(hr, "Error setting depth buffer write state.", 01706 "D3DRenderSystem::_setDepthBufferWriteEnabled"); 01707 } 01708 //----------------------------------------------------------------------- 01709 void D3DRenderSystem::_setDepthBufferFunction(CompareFunction func) 01710 { 01711 HRESULT hr = __SetRenderState(D3DRENDERSTATE_ZFUNC, 01712 convertCompareFunction(func)); 01713 if (FAILED(hr)) 01714 Except(hr, "Error setting depth buffer test function.", 01715 "D3DRenderSystem::_setDepthBufferFunction"); 01716 } 01717 //----------------------------------------------------------------------- 01718 void D3DRenderSystem::_setDepthBias(ushort bias) 01719 { 01720 HRESULT hr = __SetRenderState(D3DRENDERSTATE_ZBIAS, 01721 bias); 01722 if (FAILED(hr)) 01723 Except(hr, "Error setting depth bias.", 01724 "D3DRenderSystem::_setDepthBias"); 01725 } 01726 //----------------------------------------------------------------------- 01727 String D3DRenderSystem::getErrorDescription(long errCode) const 01728 { 01729 char* errDesc; 01730 DWORD i; 01731 01732 errDesc = new char[255]; 01733 // Try windows errors first 01734 i = FormatMessage( 01735 FORMAT_MESSAGE_FROM_HMODULE | 01736 FORMAT_MESSAGE_FROM_SYSTEM | 01737 FORMAT_MESSAGE_IGNORE_INSERTS, 01738 NULL, 01739 DDERR_SURFACELOST, 01740 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 01741 (LPTSTR) errDesc, 01742 255, 01743 NULL 01744 ); 01745 01746 01747 if (i == 0) 01748 { 01749 // Not found in windows message descriptions 01750 switch (errCode) 01751 { 01752 case DD_OK: 01753 strcpy(errDesc, "DD_OK: The request completed successfully."); 01754 break; 01755 case DDERR_ALREADYINITIALIZED: 01756 strcpy(errDesc, "DDERR_ALREADYINITIALIZED: The object has already been initialized."); 01757 break; 01758 case DDERR_BLTFASTCANTCLIP : 01759 strcpy(errDesc, "DDERR_BLTFASTCANTCLIP: A DirectDrawClipper object is attached to a source surface that has passed into a call to the IDirectDrawSurface7::BltFast method."); 01760 break; 01761 case DDERR_CANNOTATTACHSURFACE: 01762 strcpy(errDesc, "DDERR_CANNOTATTACHSURFACE: A surface cannot be attached to another requested surface."); 01763 break; 01764 case DDERR_CANNOTDETACHSURFACE: 01765 strcpy(errDesc, "DDERR_CANNOTATTACHSURFACE: A surface cannot be detached from another requested surface."); 01766 break; 01767 case DDERR_CANTCREATEDC: 01768 strcpy(errDesc, "DDERR_CANTCREATEDC: Windows can not create any more device contexts (DCs), or a DC was requested for a palette-indexed surface when the surface had no palette and the display mode was not palette-indexed."); 01769 break; 01770 case DDERR_CANTDUPLICATE: 01771 strcpy(errDesc, "DDERR_CANTDUPLICATE: Primary and 3-D surfaces, or surfaces that are implicitly created, cannot be duplicated."); 01772 break; 01773 case DDERR_CANTLOCKSURFACE: 01774 strcpy(errDesc, "DDERR_CANTLOCKSURFACE: Access to this surface is refused because an attempt was made to lock the primary surface without DCI support."); 01775 break; 01776 case DDERR_CANTPAGELOCK: 01777 strcpy(errDesc, "DDERR_CANTPAGELOCK: An attempt to page lock a surface failed. Page lock will not work on a display-memory surface or an emulated primary surface."); 01778 break; 01779 case DDERR_CANTPAGEUNLOCK: 01780 strcpy(errDesc, "DDERR_CANTPAGEUNLOCK: An attempt to page unlock a surface failed. Page unlock will not work on a display-memory surface or an emulated primary surface."); 01781 break; 01782 case DDERR_CLIPPERISUSINGHWND: 01783 strcpy(errDesc, "DDERR_CLIPPERISUSINGHWND: An attempt was made to set a clip list for a DirectDrawClipper object that is already monitoring a window handle."); 01784 break; 01785 case DDERR_COLORKEYNOTSET: 01786 strcpy(errDesc, "DDERR_COLORKEYNOTSET: No source color key is specified for this operation."); 01787 break; 01788 case DDERR_CURRENTLYNOTAVAIL: 01789 strcpy(errDesc, "DDERR_CURRENTLYNOTAVAIL: No support is currently available."); 01790 break; 01791 case DDERR_DCALREADYCREATED: 01792 strcpy(errDesc, "DDERR_DCALREADYCREATED: A device context (DC) has already been returned for this surface. Only one DC can be retrieved for each surface."); 01793 break; 01794 case DDERR_DEVICEDOESNTOWNSURFACE: 01795 strcpy(errDesc, "DDERR_DEVICEDOESNTOWNSURFACE: Surfaces created by one DirectDraw device cannot be used directly by another DirectDraw device."); 01796 break; 01797 case DDERR_DIRECTDRAWALREADYCREATED: 01798 strcpy(errDesc, "DDERR_DIRECTDRAWALREADYCREATED: A DirectDraw object representing this driver has already been created for this process."); 01799 break; 01800 case DDERR_EXCEPTION: 01801 strcpy(errDesc, "DDERR_EXCEPTION: An exception was encountered while performing the requested operation."); 01802 break; 01803 case DDERR_EXCLUSIVEMODEALREADYSET: 01804 strcpy(errDesc, "DDERR_EXCLUSIVEMODEALREADYSET: An attempt was made to set the cooperative level when it was already set to exclusive."); 01805 break; 01806 case DDERR_EXPIRED: 01807 strcpy(errDesc, "DDERR_EXPIRED: The data has expired and is therefore no longer valid."); 01808 break; 01809 case DDERR_GENERIC: 01810 strcpy(errDesc, "DDERR_GENERIC: There is an undefined error condition."); 01811 break; 01812 case DDERR_HEIGHTALIGN: 01813 strcpy(errDesc, "DDERR_HEIGHTALIGN: The height of the provided rectangle is not a multiple of the required alignment."); 01814 break; 01815 case DDERR_HWNDALREADYSET: 01816 strcpy(errDesc, "DDERR_HWNDALREADYSET: The DirectDraw cooperative level window handle has already been set. It cannot be reset while the process has surfaces or palettes created."); 01817 break; 01818 case DDERR_HWNDSUBCLASSED: 01819 strcpy(errDesc, "DDERR_HWNDSUBCLASSED: DirectDraw is prevented from restoring state because the DirectDraw cooperative level window handle has been subclassed."); 01820 break; 01821 case DDERR_IMPLICITLYCREATED: 01822 strcpy(errDesc, "DDERR_IMPLICITLYCREATED: The surface cannot be restored because it is an implicitly created surface."); 01823 break; 01824 case DDERR_INCOMPATIBLEPRIMARY: 01825 strcpy(errDesc, "DDERR_INCOMPATIBLEPRIMARY: The primary surface creation request does not match with the existing primary surface."); 01826 break; 01827 case DDERR_INVALIDCAPS: 01828 strcpy(errDesc, "DDERR_INVALIDCAPS: One or more of the capability bits passed to the callback function are incorrect."); 01829 break; 01830 case DDERR_INVALIDCLIPLIST: 01831 strcpy(errDesc, "DDERR_INVALIDCLIPLIST: DirectDraw does not support the provided clip list."); 01832 break; 01833 case DDERR_INVALIDDIRECTDRAWGUID: 01834 strcpy(errDesc, "DDERR_INVALIDDIRECTDRAWGUID: The globally unique identifier (GUID) passed to the DirectDrawCreate function is not a valid DirectDraw driver identifier."); 01835 break; 01836 case DDERR_INVALIDMODE: 01837 strcpy(errDesc, "DDERR_INVALIDMODE: DirectDraw does not support the requested mode."); 01838 break; 01839 case DDERR_INVALIDOBJECT: 01840 strcpy(errDesc, "DDERR_INVALIDOBJECT: DirectDraw received a pointer that was an invalid DirectDraw object."); 01841 break; 01842 case DDERR_INVALIDPARAMS: 01843 strcpy(errDesc, "DDERR_INVALIDPARAMS: One or more of the parameters passed to the method are incorrect."); 01844 break; 01845 case DDERR_INVALIDPIXELFORMAT: 01846 strcpy(errDesc, "DDERR_INVALIDPIXELFORMAT: The pixel format was invalid as specified."); 01847 break; 01848 case DDERR_INVALIDPOSITION: 01849 strcpy(errDesc, "DDERR_INVALIDPOSITION: The position of the overlay on the destination is no longer legal."); 01850 break; 01851 case DDERR_INVALIDRECT: 01852 strcpy(errDesc, "DDERR_INVALIDRECT: The provided rectangle was invalid."); 01853 break; 01854 case DDERR_INVALIDSTREAM: 01855 strcpy(errDesc, "DDERR_INVALIDSTREAM: The specified stream contains invalid data."); 01856 break; 01857 case DDERR_INVALIDSURFACETYPE: 01858 strcpy(errDesc, "DDERR_INVALIDSURFACETYPE: The requested operation could not be performed because the surface was of the wrong type."); 01859 break; 01860 case DDERR_LOCKEDSURFACES: 01861 strcpy(errDesc, "DDERR_LOCKEDSURFACES: One or more surfaces are locked, causing the failure of the requested operation."); 01862 break; 01863 case DDERR_MOREDATA: 01864 strcpy(errDesc, "DDERR_MOREDATA: There is more data available than the specified buffer size can hold."); 01865 break; 01866 case DDERR_NO3D: 01867 strcpy(errDesc, "DDERR_NO3D: No 3-D hardware or emulation is present."); 01868 break; 01869 case DDERR_NOALPHAHW: 01870 strcpy(errDesc, "DDERR_NOALPHAHW: No alpha acceleration hardware is present or available, causing the failure of the requested operation."); 01871 break; 01872 case DDERR_NOBLTHW: 01873 strcpy(errDesc, "DDERR_NOBLTHW: No blitter hardware is present."); 01874 break; 01875 case DDERR_NOCLIPLIST: 01876 strcpy(errDesc, "DDERR_NOCLIPLIST: No clip list is available."); 01877 break; 01878 case DDERR_NOCLIPPERATTACHED: 01879 strcpy(errDesc, "DDERR_NOCLIPPERATTACHED: No DirectDrawClipper object is attached to the surface object."); 01880 break; 01881 case DDERR_NOCOLORCONVHW: 01882 strcpy(errDesc, "DDERR_NOCOLORCONVHW: The operation cannot be carried out because no color-conversion hardware is present or available."); 01883 break; 01884 case DDERR_NOCOLORKEY: 01885 strcpy(errDesc, "DDERR_NOCOLORKEY: The surface does not currently have a color key."); 01886 break; 01887 case DDERR_NOCOLORKEYHW: 01888 strcpy(errDesc, "DDERR_NOCOLORKEYHW: The operation cannot be carried out because there is no hardware support for the destination color key."); 01889 break; 01890 case DDERR_NOCOOPERATIVELEVELSET: 01891 strcpy(errDesc, "DDERR_NOCOOPERATIVELEVELSET: A create function is called without the IDirectDraw7::SetCooperativeLevel method being called."); 01892 break; 01893 case DDERR_NODC: 01894 strcpy(errDesc, "DDERR_NODC: No DC has ever been created for this surface."); 01895 break; 01896 case DDERR_NODDROPSHW: 01897 strcpy(errDesc, "DDERR_NODDROPSHW: No DirectDraw raster operation (ROP) hardware is available."); 01898 break; 01899 case DDERR_NODIRECTDRAWHW: 01900 strcpy(errDesc, "DDERR_NODIRECTDRAWHW: Hardware-only DirectDraw object creation is not possible; the driver does not support any hardware."); 01901 break; 01902 case DDERR_NODIRECTDRAWSUPPORT: 01903 strcpy(errDesc, "DDERR_NODIRECTDRAWSUPPORT: DirectDraw support is not possible with the current display driver."); 01904 break; 01905 case DDERR_NOEMULATION: 01906 strcpy(errDesc, "DDERR_NOEMULATION: Software emulation is not available."); 01907 break; 01908 case DDERR_NOEXCLUSIVEMODE: 01909 strcpy(errDesc, "DDERR_NOEXCLUSIVEMODE: The operation requires the application to have exclusive mode, but the application does not have exclusive mode."); 01910 break; 01911 case DDERR_NOFLIPHW: 01912 strcpy(errDesc, "DDERR_NOFLIPHW: Flipping visible surfaces is not supported."); 01913 break; 01914 case DDERR_NOFOCUSWINDOW: 01915 strcpy(errDesc, "DDERR_NOFOCUSWINDOW: An attempt was made to create or set a device window without first setting the focus window."); 01916 break; 01917 case DDERR_NOGDI: 01918 strcpy(errDesc, "DDERR_NOGDI: No GDI is present."); 01919 break; 01920 case DDERR_NOHWND: 01921 strcpy(errDesc, "DDERR_NOHWND: Clipper notification requires a window handle, or no window handle has been previously set as the cooperative level window handle."); 01922 break; 01923 case DDERR_NOMIPMAPHW: 01924 strcpy(errDesc, "DDERR_NOMIPMAPHW: The operation cannot be carried out because no mipmap capable texture mapping hardware is present or available."); 01925 break; 01926 case DDERR_NOMIRRORHW: 01927 strcpy(errDesc, "DDERR_NOMIRRORHW: The operation cannot be carried out because no mirroring hardware is present or available."); 01928 break; 01929 case DDERR_NONONLOCALVIDMEM: 01930 strcpy(errDesc, "DDERR_NONONLOCALVIDMEM: An attempt was made to allocate non-local video memory from a device that does not support non-local video memory."); 01931 break; 01932 case DDERR_NOOPTIMIZEHW: 01933 strcpy(errDesc, "DDERR_NOOPTIMIZEHW: The device does not support optimized surfaces."); 01934 break; 01935 case DDERR_NOOVERLAYDEST: 01936 strcpy(errDesc, "DDERR_NOOVERLAYDEST: The IDirectDrawSurface4::GetOverlayPosition method is called on an overlay that the IDirectDrawSurface7::UpdateOverlay method has not been called on to establish a destination."); 01937 break; 01938 case DDERR_NOOVERLAYHW: 01939 strcpy(errDesc, "DDERR_NOOVERLAYHW: The operation cannot be carried out because no overlay hardware is present or available."); 01940 break; 01941 case DDERR_NOPALETTEATTACHED: 01942 strcpy(errDesc, "DDERR_NOPALETTEATTACHED: No palette object is attached to this surface."); 01943 break; 01944 case DDERR_NOPALETTEHW: 01945 strcpy(errDesc, "DDERR_NOPALETTEHW: There is no hardware support for 16- or 256-color palettes."); 01946 break; 01947 case DDERR_NORASTEROPHW: 01948 strcpy(errDesc, "DDERR_NORASTEROPHW: The operation cannot be carried out because no appropriate raster operation hardware is present or available."); 01949 break; 01950 case DDERR_NOROTATIONHW: 01951 strcpy(errDesc, "DDERR_NOROTATIONHW: The operation cannot be carried out because no rotation hardware is present or available."); 01952 break; 01953 case DDERR_NOSTRETCHHW: 01954 strcpy(errDesc, "DDERR_NOSTRETCHHW: The operation cannot be carried out because there is no hardware support for stretching."); 01955 break; 01956 case DDERR_NOT4BITCOLOR: 01957 strcpy(errDesc, "DDERR_NOT4BITCOLOR: The DirectDrawSurface object is not using a 4-bit color palette and the requested operation requires a 4-bit color palette."); 01958 break; 01959 case DDERR_NOT4BITCOLORINDEX: 01960 strcpy(errDesc, "DDERR_NOT4BITCOLORINDEX: The DirectDrawSurface object is not using a 4-bit color index palette and the requested operation requires a 4-bit color index palette."); 01961 break; 01962 case DDERR_NOT8BITCOLOR: 01963 strcpy(errDesc, "DDERR_NOT8BITCOLOR: The DirectDrawSurface object is not using an 8-bit color palette and the requested operation requires an 8-bit color palette."); 01964 break; 01965 case DDERR_NOTAOVERLAYSURFACE: 01966 strcpy(errDesc, "DDERR_NOTAOVERLAYSURFACE: An overlay component is called for a non-overlay surface."); 01967 break; 01968 case DDERR_NOTEXTUREHW: 01969 strcpy(errDesc, "DDERR_NOTEXTUREHW: The operation cannot be carried out because no texture-mapping hardware is present or available."); 01970 break; 01971 case DDERR_NOTFLIPPABLE: 01972 strcpy(errDesc, "DDERR_NOTFLIPPABLE: An attempt has been made to flip a surface that cannot be flipped."); 01973 break; 01974 case DDERR_NOTFOUND: 01975 strcpy(errDesc, "DDERR_NOTFOUND: The requested item was not found."); 01976 break; 01977 case DDERR_NOTINITIALIZED: 01978 strcpy(errDesc, "DDERR_NOTINITIALIZED: An attempt was made to call an interface method of a DirectDraw object created by CoCreateInstance before the object was initialized."); 01979 break; 01980 case DDERR_NOTLOADED: 01981 strcpy(errDesc, "DDERR_NOTLOADED: The surface is an optimized surface, but it has not yet been allocated any memory."); 01982 break; 01983 case DDERR_NOTLOCKED: 01984 strcpy(errDesc, "DDERR_NOTLOCKED: An attempt is made to unlock a surface that was not locked."); 01985 break; 01986 case DDERR_NOTPAGELOCKED: 01987 strcpy(errDesc, "DDERR_NOTPAGELOCKED: An attempt is made to page unlock a surface with no outstanding page locks."); 01988 break; 01989 case DDERR_NOTPALETTIZED: 01990 strcpy(errDesc, "DDERR_NOTPALETTIZED: The surface being used is not a palette-based surface."); 01991 break; 01992 case DDERR_NOVSYNCHW: 01993 strcpy(errDesc, "DDERR_NOVSYNCHW: The operation cannot be carried out because there is no hardware support for vertical blank synchronized operations."); 01994 break; 01995 case DDERR_NOZBUFFERHW: 01996 strcpy(errDesc, "DDERR_NOZBUFFERHW: The operation to create a z-buffer in display memory or to perform a blit using a z-buffer cannot be carried out because there is no hardware support for z-buffers."); 01997 break; 01998 case DDERR_NOZOVERLAYHW: 01999 strcpy(errDesc, "DDERR_NOZOVERLAYHW: The overlay surfaces cannot be z-layered based on the z-order because the hardware does not support z-ordering of overlays."); 02000 break; 02001 case DDERR_OUTOFCAPS: 02002 strcpy(errDesc, "DDERR_OUTOFCAPS: The hardware needed for the requested operation has already been allocated."); 02003 break; 02004 case DDERR_OUTOFMEMORY: 02005 strcpy(errDesc, "DDERR_OUTOFMEMORY: DirectDraw does not have enough memory to perform the operation."); 02006 break; 02007 case DDERR_OUTOFVIDEOMEMORY: 02008 strcpy(errDesc, "DDERR_OUTOFVIDEOMEMORY: DirectDraw does not have enough display memory to perform the operation."); 02009 break; 02010 case DDERR_OVERLAPPINGRECTS: 02011 strcpy(errDesc, "DDERR_OVERLAPPINGRECTS: Operation could not be carried out because the source and destination rectangles are on the same surface and overlap each other."); 02012 break; 02013 case DDERR_OVERLAYCANTCLIP: 02014 strcpy(errDesc, "DDERR_OVERLAYCANTCLIP: The hardware does not support clipped overlays."); 02015 break; 02016 case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: 02017 strcpy(errDesc, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE: An attempt was made to have more than one color key active on an overlay."); 02018 break; 02019 case DDERR_OVERLAYNOTVISIBLE: 02020 strcpy(errDesc, "DDERR_OVERLAYNOTVISIBLE: The IDirectDrawSurface7::GetOverlayPosition method is called on a hidden overlay."); 02021 break; 02022 case DDERR_PALETTEBUSY: 02023 strcpy(errDesc, "DDERR_PALETTEBUSY: Access to this palette is refused because the palette is locked by another thread."); 02024 break; 02025 case DDERR_PRIMARYSURFACEALREADYEXISTS: 02026 strcpy(errDesc, "DDERR_PRIMARYSURFACEALREADYEXISTS: This process has already created a primary surface."); 02027 break; 02028 case DDERR_REGIONTOOSMALL: 02029 strcpy(errDesc, "DDERR_REGIONTOOSMALL: The region passed to the IDirectDrawClipper::GetClipList method is too small."); 02030 break; 02031 case DDERR_SURFACEALREADYATTACHED: 02032 strcpy(errDesc, "DDERR_SURFACEALREADYATTACHED: An attempt was made to attach a surface to another surface to which it is already attached."); 02033 break; 02034 case DDERR_SURFACEALREADYDEPENDENT: 02035 strcpy(errDesc, "DDERR_SURFACEALREADYDEPENDENT: An attempt was made to make a surface a dependency of another surface to which it is already dependent."); 02036 break; 02037 case DDERR_SURFACEBUSY: 02038 strcpy(errDesc, "DDERR_SURFACEBUSY: Access to the surface is refused because the surface is locked by another thread."); 02039 break; 02040 case DDERR_SURFACEISOBSCURED: 02041 strcpy(errDesc, "DDERR_SURFACEISOBSCURED: Access to the surface is refused because the surface is obscured."); 02042 break; 02043 case DDERR_SURFACELOST: 02044 strcpy(errDesc, "DDERR_SURFACELOST: Access to the surface is refused because the surface memory is gone. Call the IDirectDrawSurface7::Restore method on this surface to restore the memory associated with it."); 02045 break; 02046 case DDERR_SURFACENOTATTACHED: 02047 strcpy(errDesc, "DDERR_SURFACENOTATTACHED: The requested surface is not attached."); 02048 break; 02049 case DDERR_TOOBIGHEIGHT: 02050 strcpy(errDesc, "DDERR_TOOBIGHEIGHT: The height requested by DirectDraw is too large."); 02051 break; 02052 case DDERR_TOOBIGSIZE: 02053 strcpy(errDesc, "DDERR_TOOBIGSIZE: The size requested by DirectDraw is too large. However, the individual height and width are valid sizes."); 02054 break; 02055 case DDERR_TOOBIGWIDTH: 02056 strcpy(errDesc, "DDERR_TOOBIGWIDTH: The width requested by DirectDraw is too large."); 02057 break; 02058 case DDERR_UNSUPPORTED: 02059 strcpy(errDesc, "DDERR_UNSUPPORTED: The operation is not supported."); 02060 break; 02061 case DDERR_UNSUPPORTEDFORMAT: 02062 strcpy(errDesc, "DDERR_UNSUPPORTEDFORMAT: The FourCC format requested is not supported by DirectDraw."); 02063 break; 02064 case DDERR_UNSUPPORTEDMASK: 02065 strcpy(errDesc, "DDERR_UNSUPPORTEDMASK: The bitmask in the pixel format requested is not supported by DirectDraw."); 02066 break; 02067 case DDERR_UNSUPPORTEDMODE: 02068 strcpy(errDesc, "DDERR_UNSUPPORTEDMODE: The display is currently in an unsupported mode."); 02069 break; 02070 case DDERR_VERTICALBLANKINPROGRESS: 02071 strcpy(errDesc, "DDERR_VERTICALBLANKINPROGRESS: A vertical blank is in progress."); 02072 break; 02073 case DDERR_VIDEONOTACTIVE: 02074 strcpy(errDesc, "DDERR_VIDEONOTACTIVE: The video port is not active."); 02075 break; 02076 case DDERR_WASSTILLDRAWING: 02077 strcpy(errDesc, "DDERR_WASSTILLDRAWING: The previous blit operation that is transferring information to or from this surface is incomplete."); 02078 break; 02079 case DDERR_WRONGMODE: 02080 strcpy(errDesc, "DDERR_WRONGMODE: This surface cannot be restored because it was created in a different mode."); 02081 break; 02082 case DDERR_XALIGN: 02083 strcpy(errDesc, "DDERR_XALIGN: The provided rectangle was not horizontally aligned on a required boundary."); 02084 break; 02085 default: 02086 strcpy(errDesc, "Unknown error code."); 02087 } 02088 } 02089 return errDesc; 02090 } 02091 02092 /* 02093 D3D_OK 02094 D3DERR_BADMAJORVERSION 02095 D3DERR_BADMINORVERSION 02096 D3DERR_COLORKEYATTACHED 02097 D3DERR_CONFLICTINGTEXTUREFILTER 02098 D3DERR_CONFLICTINGTEXTUREPALETTE 02099 D3DERR_CONFLICTINGRENDERSTATE 02100 D3DERR_DEVICEAGGREGATED (new for DirectX 5.0) 02101 D3DERR_EXECUTE_CLIPPED_FAILED 02102 D3DERR_EXECUTE_CREATE_FAILED 02103 D3DERR_EXECUTE_DESTROY_FAILED 02104 D3DERR_EXECUTE_FAILED 02105 D3DERR_EXECUTE_LOCK_FAILED 02106 D3DERR_EXECUTE_LOCKED 02107 D3DERR_EXECUTE_NOT_LOCKED 02108 D3DERR_EXECUTE_UNLOCK_FAILED 02109 D3DERR_INITFAILED (new for DirectX 5.0) 02110 D3DERR_INBEGIN (new for DirectX 5.0) 02111 D3DERR_INVALID_DEVICE (new for DirectX 5.0) 02112 D3DERR_INVALIDCURRENTVIEWPORT (new for DirectX 5.0) 02113 D3DERR_INVALIDMATRIX 02114 D3DERR_INVALIDPALETTE(new for DirectX 5.0) 02115 D3DERR_INVALIDPRIMITIVETYPE (new for DirectX 5.0) 02116 D3DERR_INVALIDRAMPTEXTURE (new for DirectX 5.0) 02117 D3DERR_INVALIDVERTEXFORMAT (new for DirectX 6.0) 02118 D3DERR_INVALIDVERTEXTYPE (new for DirectX 5.0) 02119 D3DERR_LIGHT_SET_FAILED 02120 D3DERR_LIGHTHASVIEWPORT (new for DirectX 5.0) 02121 D3DERR_LIGHTNOTINTHISVIEWPORT (new for DirectX 5.0) 02122 D3DERR_MATERIAL_CREATE_FAILED 02123 D3DERR_MATERIAL_DESTROY_FAILED 02124 D3DERR_MATERIAL_GETDATA_FAILED 02125 D3DERR_MATERIAL_SETDATA_FAILED 02126 D3DERR_MATRIX_CREATE_FAILED 02127 D3DERR_MATRIX_DESTROY_FAILED 02128 D3DERR_MATRIX_GETDATA_FAILED 02129 D3DERR_MATRIX_SETDATA_FAILED 02130 D3DERR_NOCURRENTVIEWPORT (new for DirectX 5.0) 02131 D3DERR_NOTINBEGIN (new for DirectX 5.0) 02132 D3DERR_NOVIEWPORTS (new for DirectX 5.0) 02133 D3DERR_SCENE_BEGIN_FAILED 02134 D3DERR_SCENE_END_FAILED 02135 D3DERR_SCENE_IN_SCENE 02136 D3DERR_SCENE_NOT_IN_SCENE 02137 D3DERR_SETVIEWPORTDATA_FAILED 02138 D3DERR_STENCILBUFFER_NOTPRESENT 02139 D3DERR_SURFACENOTINVIDMEM (new for DirectX 5.0) 02140 D3DERR_TEXTURE_BADSIZE (new for DirectX 5.0) 02141 D3DERR_TEXTURE_CREATE_FAILED 02142 D3DERR_TEXTURE_DESTROY_FAILED 02143 D3DERR_TEXTURE_GETSURF_FAILED 02144 D3DERR_TEXTURE_LOAD_FAILED 02145 D3DERR_TEXTURE_LOCK_FAILED 02146 D3DERR_TEXTURE_LOCKED 02147 D3DERR_TEXTURE_NO_SUPPORT 02148 D3DERR_TEXTURE_NOT_LOCKED 02149 D3DERR_TEXTURE_SWAP_FAILED 02150 D3DERR_TEXTURE_UNLOCK_FAILED 02151 D3DERR_TOOMANYOPERATIONS 02152 D3DERR_TOOMANYPRIMITIVES 02153 D3DERR_UNSUPPORTEDALPHAARG 02154 D3DERR_UNSUPPORTEDALPHAOPERATION 02155 D3DERR_UNSUPPORTEDCOLORARG 02156 D3DERR_UNSUPPORTEDCOLOROPERATION 02157 D3DERR_UNSUPPORTEDFACTORVALUE 02158 D3DERR_UNSUPPORTEDTEXTUREFILTER 02159 D3DERR_VBUF_CREATE_FAILED 02160 D3DERR_VERTEXBUFFERLOCKED 02161 D3DERR_VERTEXBUFFEROPTIMIZED 02162 D3DERR_VIEWPORTDATANOTSET (new for DirectX 5.0) 02163 D3DERR_VIEWPORTHASNODEVICE (new for DirectX 5.0) 02164 D3DERR_WRONGTEXTUREFORMAT 02165 D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY (new for DirectX 5.0) 02166 D3DERR_ZBUFF_NEEDS_VIDEOMEMORY (new for DirectX 5.0) 02167 D3DERR_ZBUFFER_NOTPRESENT 02168 */ 02169 02170 //----------------------------------------------------------------------- 02171 DDDriverList* D3DRenderSystem::getDirectDrawDrivers(void) 02172 { 02173 if (!mDriverList) 02174 { 02175 mDriverList = new DDDriverList; 02176 } 02177 02178 return mDriverList; 02179 } 02180 //----------------------------------------------------------------------- 02181 void D3DRenderSystem::setLightingEnabled(bool enabled) 02182 { 02183 // Call D3D 02184 HRESULT hr = __SetRenderState(D3DRENDERSTATE_LIGHTING, enabled); 02185 if (FAILED(hr)) 02186 Except(hr, "Error lighting status.", "D3DRenderSystem::setLightingEnabled"); 02187 } 02188 //----------------------------------------------------------------------- 02189 void D3DRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end) 02190 { 02191 HRESULT hr; 02192 02193 D3DRENDERSTATETYPE fogType, fogTypeNot; 02194 02195 if (mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) 02196 { 02197 fogType = D3DRENDERSTATE_FOGTABLEMODE; 02198 fogTypeNot = D3DRENDERSTATE_FOGVERTEXMODE; 02199 } 02200 else 02201 { 02202 fogType = D3DRENDERSTATE_FOGVERTEXMODE; 02203 fogTypeNot = D3DRENDERSTATE_FOGTABLEMODE; 02204 } 02205 02206 if( mode == FOG_NONE) 02207 { 02208 // just disable 02209 hr = __SetRenderState(fogType, D3DFOG_NONE ); 02210 hr = __SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE); 02211 } 02212 else 02213 { 02214 // Allow fog 02215 hr = __SetRenderState( D3DRENDERSTATE_FOGENABLE, TRUE ); 02216 hr = __SetRenderState( fogTypeNot, D3DFOG_NONE ); 02217 switch(mode) 02218 { 02219 case FOG_EXP: 02220 hr = __SetRenderState( fogType, D3DFOG_EXP); 02221 break; 02222 case FOG_EXP2: 02223 hr = __SetRenderState( fogType, D3DFOG_EXP2); 02224 break; 02225 case FOG_LINEAR: 02226 hr = __SetRenderState( fogType, D3DFOG_LINEAR); 02227 break; 02228 02229 } 02230 02231 hr = __SetRenderState( D3DRENDERSTATE_FOGCOLOR, colour.getAsLongARGB() ); 02232 hr = __SetRenderState( D3DRENDERSTATE_FOGSTART, *((LPDWORD)(&start)) ); 02233 hr = __SetRenderState( D3DRENDERSTATE_FOGEND, *((LPDWORD)(&end)) ); 02234 hr = __SetRenderState( D3DRENDERSTATE_FOGDENSITY, *((LPDWORD)(&density)) ); 02235 } 02236 02237 02238 } 02239 02240 //--------------------------------------------------------------------- 02241 void D3DRenderSystem::convertColourValue(const ColourValue& colour, unsigned long* pDest) 02242 { 02243 *pDest = colour.getAsLongARGB(); 02244 } 02245 //--------------------------------------------------------------------- 02246 void D3DRenderSystem::_makeProjectionMatrix(Real fovy, Real aspect, 02247 Real nearPlane, Real farPlane, Matrix4& dest, bool forGpuProgram) 02248 { 02249 Real theta = Math::AngleUnitsToRadians(fovy * 0.5); 02250 Real h = 1 / Math::Tan(theta); 02251 Real w = h / aspect; 02252 Real q, qn; 02253 if (farPlane == 0) 02254 { 02255 q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST; 02256 qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1); 02257 } 02258 else 02259 { 02260 q = farPlane / ( farPlane - nearPlane ); 02261 qn = -q * nearPlane; 02262 } 02263 02264 dest = Matrix4::ZERO; 02265 dest[0][0] = w; 02266 dest[1][1] = h; 02267 dest[2][2] = q; 02268 dest[3][2] = 1.0f; 02269 dest[2][3] = qn; 02270 02271 } 02272 //--------------------------------------------------------------------- 02273 void D3DRenderSystem::_makeOrthoMatrix(Real fovy, Real aspect, Real nearPlane, Real farPlane, 02274 Matrix4& dest, bool forGpuProgram ) 02275 { 02276 Real thetaY = Math::AngleUnitsToRadians(fovy / 2.0f); 02277 Real sinThetaY = Math::Sin(thetaY); 02278 Real thetaX = thetaY * aspect; 02279 Real sinThetaX = Math::Sin(thetaX); 02280 Real w = 1.0 / (sinThetaX * nearPlane); 02281 Real h = 1.0 / (sinThetaY * nearPlane); 02282 Real q; 02283 if (farPlane == 0) 02284 { 02285 q = 0; 02286 } 02287 else 02288 { 02289 q = 1.0 / (farPlane - nearPlane); 02290 } 02291 02292 02293 dest = Matrix4::ZERO; 02294 dest[0][0] = w; 02295 dest[1][1] = h; 02296 dest[2][2] = q; 02297 dest[3][3] = 1; 02298 } 02299 //--------------------------------------------------------------------- 02300 void D3DRenderSystem::_setRasterisationMode(SceneDetailLevel level) 02301 { 02302 D3DFILLMODE d3dmode; 02303 02304 switch(level) 02305 { 02306 case SDL_POINTS: 02307 d3dmode = D3DFILL_POINT; 02308 break; 02309 case SDL_WIREFRAME: 02310 d3dmode = D3DFILL_WIREFRAME; 02311 break; 02312 case SDL_SOLID: 02313 d3dmode = D3DFILL_SOLID; 02314 break; 02315 02316 } 02317 02318 HRESULT hr = __SetRenderState(D3DRENDERSTATE_FILLMODE, d3dmode); 02319 if (FAILED(hr)) 02320 { 02321 Except(hr, "Error setting rasterisation mode.", 02322 "D3DRenderSystem::setRasterisationMode"); 02323 } 02324 02325 02326 } 02327 //--------------------------------------------------------------------- 02328 void D3DRenderSystem::setStencilCheckEnabled(bool enabled) 02329 { 02330 // Allow stencilling 02331 HRESULT hr = __SetRenderState(D3DRENDERSTATE_STENCILENABLE, enabled); 02332 if (FAILED(hr)) 02333 Except(hr, "Error enabling / disabling stencilling.", 02334 "D3DRenderSystem::setStencilCheckEnabled"); 02335 02336 } 02337 //--------------------------------------------------------------------- 02338 void D3DRenderSystem::setStencilBufferParams(CompareFunction func, ulong refValue, 02339 ulong mask, StencilOperation stencilFailOp, 02340 StencilOperation depthFailOp, StencilOperation passOp, 02341 bool twoSidedOperation) 02342 { 02343 HRESULT hr; 02344 02345 // D3D7 does not support 2-sided stencil operations 02346 if (twoSidedOperation) 02347 Except(Exception::ERR_INVALIDPARAMS, "Direct3D7 does not support 2-sided stencil ops", 02348 "D3DRenderSystem::setStencilBufferParams"); 02349 02350 // Function 02351 hr = __SetRenderState(D3DRENDERSTATE_STENCILFUNC, 02352 convertCompareFunction(func)); 02353 02354 if (FAILED(hr)) 02355 Except(hr, "Error setting stencil buffer test function.", 02356 "D3DRenderSystem::setStencilBufferParams"); 02357 02358 // reference value 02359 hr = __SetRenderState(D3DRENDERSTATE_STENCILREF, refValue); 02360 if (FAILED(hr)) 02361 Except(hr, "Error setting stencil buffer reference value.", 02362 "D3DRenderSystem::setStencilBufferParams"); 02363 02364 // mask 02365 hr = __SetRenderState(D3DRENDERSTATE_STENCILMASK, mask); 02366 if (FAILED(hr)) 02367 Except(hr, "Error setting stencil buffer mask.", 02368 "D3DRenderSystem::setStencilBufferParams"); 02369 02370 // fail op 02371 hr = __SetRenderState(D3DRENDERSTATE_STENCILFAIL, 02372 convertStencilOp(stencilFailOp)); 02373 if (FAILED(hr)) 02374 Except(hr, "Error setting stencil fail operation.", 02375 "D3DRenderSystem::setStencilBufferParams"); 02376 02377 // depth fail op 02378 hr = __SetRenderState(D3DRENDERSTATE_STENCILZFAIL, 02379 convertStencilOp(depthFailOp)); 02380 if (FAILED(hr)) 02381 Except(hr, "Error setting stencil depth fail operation.", 02382 "D3DRenderSystem::setStencilBufferParams"); 02383 02384 // pass op 02385 hr = __SetRenderState(D3DRENDERSTATE_STENCILPASS, 02386 convertStencilOp(passOp)); 02387 if (FAILED(hr)) 02388 Except(hr, "Error setting stencil pass operation.", 02389 "D3DRenderSystem::setStencilBufferParams"); 02390 } 02391 //--------------------------------------------------------------------- 02392 D3DCMPFUNC D3DRenderSystem::convertCompareFunction(CompareFunction func) 02393 { 02394 switch(func) 02395 { 02396 case CMPF_ALWAYS_FAIL: 02397 return D3DCMP_NEVER; 02398 case CMPF_ALWAYS_PASS: 02399 return D3DCMP_ALWAYS; 02400 case CMPF_LESS: 02401 return D3DCMP_LESS; 02402 case CMPF_LESS_EQUAL: 02403 return D3DCMP_LESSEQUAL; 02404 case CMPF_EQUAL: 02405 return D3DCMP_EQUAL; 02406 case CMPF_NOT_EQUAL: 02407 return D3DCMP_NOTEQUAL; 02408 case CMPF_GREATER_EQUAL: 02409 return D3DCMP_GREATEREQUAL; 02410 case CMPF_GREATER: 02411 return D3DCMP_GREATER; 02412 }; 02413 // to shut the compiler up 02414 return D3DCMP_ALWAYS; 02415 } 02416 //--------------------------------------------------------------------- 02417 D3DSTENCILOP D3DRenderSystem::convertStencilOp(StencilOperation op) 02418 { 02419 switch(op) 02420 { 02421 case SOP_KEEP: 02422 return D3DSTENCILOP_KEEP; 02423 case SOP_ZERO: 02424 return D3DSTENCILOP_ZERO; 02425 case SOP_REPLACE: 02426 return D3DSTENCILOP_REPLACE; 02427 case SOP_INCREMENT: 02428 return D3DSTENCILOP_INCRSAT; 02429 case SOP_DECREMENT: 02430 return D3DSTENCILOP_DECRSAT; 02431 case SOP_INCREMENT_WRAP: 02432 return D3DSTENCILOP_INCR; 02433 case SOP_DECREMENT_WRAP: 02434 return D3DSTENCILOP_DECR; 02435 case SOP_INVERT: 02436 return D3DSTENCILOP_INVERT; 02437 }; 02438 // To shut the compiler up 02439 return D3DSTENCILOP_KEEP; 02440 } 02441 02442 DWORD D3DRenderSystem::_getCurrentAnisotropy(size_t unit) 02443 { 02444 DWORD oldVal; 02445 mlpD3DDevice->GetTextureStageState(unit, D3DTSS_MAXANISOTROPY, &oldVal); 02446 return oldVal; 02447 } 02448 02449 02450 void D3DRenderSystem::_setTextureUnitFiltering(size_t unit, 02451 FilterType ftype, FilterOptions filter) 02452 { 02453 __SetTextureStageState(unit, _getFilterCode(ftype), _getFilter(ftype, filter)); 02454 } 02455 02456 void D3DRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy) 02457 { 02458 if ((DWORD)maxAnisotropy > mD3DDeviceDesc.dwMaxAnisotropy) 02459 maxAnisotropy = mD3DDeviceDesc.dwMaxAnisotropy; 02460 02461 if (_getCurrentAnisotropy(unit) != maxAnisotropy) 02462 __SetTextureStageState( unit, D3DTSS_MAXANISOTROPY, maxAnisotropy ); 02463 } 02464 02465 void D3DRenderSystem::setVertexDeclaration(VertexDeclaration* decl) 02466 { 02467 // TODO 02468 } 02469 02470 void D3DRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding) 02471 { 02472 // TODO 02473 } 02474 //----------------------------------------------------------------------- 02475 D3DTEXTURESTAGESTATETYPE D3DRenderSystem::_getFilterCode(FilterType ft) const 02476 { 02477 switch (ft) 02478 { 02479 case FT_MIN: 02480 return D3DTSS_MINFILTER; 02481 break; 02482 case FT_MAG: 02483 return D3DTSS_MAGFILTER; 02484 break; 02485 case FT_MIP: 02486 return D3DTSS_MIPFILTER; 02487 break; 02488 } 02489 02490 // to keep compiler happy 02491 return D3DTSS_MINFILTER; 02492 } 02493 //----------------------------------------------------------------------- 02494 DWORD D3DRenderSystem::_getFilter(FilterType ft, FilterOptions fo) const 02495 { 02496 switch (ft) 02497 { 02498 case FT_MIN: 02499 switch( fo ) 02500 { 02501 // NOTE: Fall through if device doesn't support requested type 02502 case FO_ANISOTROPIC: 02503 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC ) 02504 { 02505 return D3DTFN_ANISOTROPIC; 02506 break; 02507 } 02508 case FO_LINEAR: 02509 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR ) 02510 { 02511 return D3DTFN_LINEAR; 02512 break; 02513 } 02514 case FO_POINT: 02515 case TFO_NONE: 02516 return D3DTFN_POINT; 02517 break; 02518 } 02519 break; 02520 case FT_MAG: 02521 switch( fo ) 02522 { 02523 // NOTE: Fall through if device doesn't support requested type 02524 case FO_ANISOTROPIC: 02525 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC ) 02526 { 02527 return D3DTFG_ANISOTROPIC; 02528 break; 02529 } 02530 case FO_LINEAR: 02531 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR ) 02532 { 02533 return D3DTFG_LINEAR; 02534 break; 02535 } 02536 case FO_POINT: 02537 case FO_NONE: 02538 return D3DTFG_POINT; 02539 break; 02540 } 02541 break; 02542 case FT_MIP: 02543 switch( fo ) 02544 { 02545 case FO_ANISOTROPIC: 02546 case FO_LINEAR: 02547 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR ) 02548 { 02549 return D3DTFP_LINEAR; 02550 break; 02551 } 02552 case FO_POINT: 02553 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR ) 02554 { 02555 return D3DTFP_POINT; 02556 break; 02557 } 02558 case TFO_NONE: 02559 return D3DTFP_NONE; 02560 break; 02561 } 02562 break; 02563 } 02564 02565 // should never get here 02566 return 0; 02567 } 02568 //--------------------------------------------------------------------- 02569 void D3DRenderSystem::setNormaliseNormals(bool normalise) 02570 { 02571 __SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, 02572 normalise ? TRUE : FALSE); 02573 } 02574 //--------------------------------------------------------------------- 02575 HRESULT D3DRenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value) 02576 { 02577 HRESULT hr; 02578 DWORD oldVal; 02579 02580 if ( FAILED( hr = mlpD3DDevice->GetRenderState(state, &oldVal) ) ) 02581 return hr; 02582 if ( oldVal == value ) 02583 return D3D_OK; 02584 else 02585 return mlpD3DDevice->SetRenderState(state, value); 02586 } 02587 //--------------------------------------------------------------------- 02588 HRESULT D3DRenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value) 02589 { 02590 HRESULT hr; 02591 DWORD oldVal; 02592 02593 if ( FAILED( hr = mlpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) ) 02594 return hr; 02595 if ( oldVal == value ) 02596 return D3D_OK; 02597 else 02598 return mlpD3DDevice->SetTextureStageState(stage, type, value); 02599 } 02600 02601 //--------------------------------------------------------------------- 02602 void D3DRenderSystem::clearFrameBuffer(unsigned int buffers, 02603 const ColourValue& colour, Real depth, unsigned short stencil) 02604 { 02605 DWORD flags = 0; 02606 if (buffers & FBT_COLOUR) 02607 { 02608 flags |= D3DCLEAR_TARGET; 02609 } 02610 if (buffers & FBT_DEPTH) 02611 { 02612 flags |= D3DCLEAR_ZBUFFER; 02613 } 02614 // Only try to clear the stencil if supported, otherwise it will fail 02615 if (buffers & FBT_STENCIL && mCapabilities->hasCapability(RSC_HWSTENCIL)) 02616 { 02617 flags |= D3DCLEAR_STENCIL; 02618 } 02619 HRESULT hr; 02620 if( FAILED( hr = mlpD3DDevice->Clear( 02621 0, 02622 NULL, 02623 flags, 02624 colour.getAsLongARGB(), 02625 depth, 02626 stencil ) ) ) 02627 { 02628 String msg = getErrorDescription(hr); 02629 Except( hr, "Error clearing frame buffer : " 02630 + msg, "D3DRenderSystem::clearFrameBuffer" ); 02631 } 02632 } 02633 //--------------------------------------------------------------------- 02634 void D3DRenderSystem::_makeProjectionMatrix(Real left, Real right, 02635 Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest, 02636 bool forGpuProgram) 02637 { 02638 Real width = right - left; 02639 Real height = top - bottom; 02640 Real q, qn; 02641 if (farPlane == 0) 02642 { 02643 q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST; 02644 qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1); 02645 } 02646 else 02647 { 02648 q = farPlane / ( farPlane - nearPlane ); 02649 qn = -q * nearPlane; 02650 } 02651 dest = Matrix4::ZERO; 02652 dest[0][0] = 2 * nearPlane / width; 02653 dest[0][2] = (right+left) / width; 02654 dest[1][1] = 2 * nearPlane / height; 02655 dest[1][2] = (top+bottom) / height; 02656 dest[2][2] = q; 02657 dest[3][2] = 1.0f; 02658 dest[2][3] = qn; 02659 } 02660 02661 //--------------------------------------------------------------------- 02662 void D3DRenderSystem::setClipPlanes(const PlaneList& clipPlanes) 02663 { 02664 size_t i; 02665 size_t numClipPlanes; 02666 D3DVALUE dx7ClipPlane[4]; 02667 DWORD mask = 0; 02668 HRESULT hr; 02669 numClipPlanes = clipPlanes.size(); 02670 02671 for (i = 0; i < numClipPlanes; ++i) 02672 { 02673 const Plane& plane = clipPlanes[i]; 02674 02675 dx7ClipPlane[0] = plane.normal.x; 02676 dx7ClipPlane[1] = plane.normal.y; 02677 dx7ClipPlane[2] = plane.normal.z; 02678 dx7ClipPlane[3] = -plane.d; 02679 02680 hr = mlpD3DDevice->SetClipPlane(i, dx7ClipPlane); 02681 if (FAILED(hr)) 02682 { 02683 Except(hr, "Unable to set clip plane", 02684 "D3D7RenderSystem::setClipPlanes"); 02685 } 02686 02687 mask |= (1 << i); 02688 } 02689 02690 hr = mlpD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, mask); 02691 if (FAILED(hr)) 02692 { 02693 Except(hr, "Unable to set render state for clip planes", 02694 "D3D7RenderSystem::setClipPlanes"); 02695 } 02696 } 02697 02698 // ------------------------------------------------------------------ 02699 void D3DRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D) 02700 { 02701 float plane[4] = { A, B, C, D }; 02702 mlpD3DDevice->SetClipPlane (index, plane); 02703 } 02704 02705 // ------------------------------------------------------------------ 02706 void D3DRenderSystem::enableClipPlane (ushort index, bool enable) 02707 { 02708 DWORD prev; 02709 mlpD3DDevice->GetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, &prev); 02710 __SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, prev | (1 << index)); 02711 } 02712 //--------------------------------------------------------------------- 02713 HardwareOcclusionQuery* D3DRenderSystem::createHardwareOcclusionQuery(void) 02714 { 02715 return (HardwareOcclusionQuery*) 0; // Hardware occlusion is not supported when DirectX7 is used 02716 } 02717 //----------------------------------------------------------------------- 02718 void D3DRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha) 02719 { 02720 // D3D7 does not have a colour write mask setting, so emulate it using 02721 // scene blending, on the assumption that setSceneBlend will be called 02722 // before this 02723 if (red || green || blue || alpha) 02724 { 02725 // restore saved scene blend 02726 _setSceneBlending(mSavedSrcFactor, mSavedDestFactor); 02727 } 02728 else 02729 { 02730 _setSceneBlending(SBF_ZERO, SBF_ONE); 02731 } 02732 } 02733 02734 }
Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:00 2004