1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
\r
6 #include "CD3D9Driver.h"
\r
8 #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
\r
11 #include "S3DVertex.h"
\r
12 #include "CD3D9Texture.h"
\r
13 #include "CD3D9RenderTarget.h"
\r
14 #include "CD3D9MaterialRenderer.h"
\r
15 #include "CD3D9ShaderMaterialRenderer.h"
\r
16 #include "CD3D9NormalMapRenderer.h"
\r
17 #include "CD3D9ParallaxMapRenderer.h"
\r
18 #include "CD3D9HLSLMaterialRenderer.h"
\r
19 #include "SIrrCreationParameters.h"
\r
28 inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
\r
32 CD3D9Driver::CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io)
\r
33 : CNullDriver(io, params.WindowSize), BridgeCalls(0), CurrentRenderMode(ERM_NONE),
\r
34 ResetRenderStates(true), Transformation3DChanged(false),
\r
35 D3DLibrary(0), pID3D(0), pID3DDevice(0), BackBufferSurface(0),
\r
36 DepthStencilSurface(0), WindowId(0), SceneSourceRect(0),
\r
37 LastVertexType((video::E_VERTEX_TYPE)-1), VendorID(0),
\r
38 MaxTextureUnits(0), MaxFixedPipelineTextureUnits(0), MaxUserClipPlanes(0),
\r
39 MaxLightDistance(0.f), LastSetLight(-1),
\r
40 ColorFormat(ECF_A8R8G8B8), DeviceLost(false),
\r
41 DriverWasReset(true), OcclusionQuerySupport(false),
\r
42 AlphaToCoverageSupport(false), Params(params)
\r
45 setDebugName("CD3D9Driver");
\r
50 for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
\r
52 CurrentTexture[i] = 0;
\r
53 LastTextureMipMapsAvailable[i] = false;
\r
55 MaxLightDistance = sqrtf(FLT_MAX);
\r
56 // create sphere map matrix
\r
58 SphereMapMatrixD3D9._11 = 0.5f; SphereMapMatrixD3D9._12 = 0.0f;
\r
59 SphereMapMatrixD3D9._13 = 0.0f; SphereMapMatrixD3D9._14 = 0.0f;
\r
60 SphereMapMatrixD3D9._21 = 0.0f; SphereMapMatrixD3D9._22 =-0.5f;
\r
61 SphereMapMatrixD3D9._23 = 0.0f; SphereMapMatrixD3D9._24 = 0.0f;
\r
62 SphereMapMatrixD3D9._31 = 0.0f; SphereMapMatrixD3D9._32 = 0.0f;
\r
63 SphereMapMatrixD3D9._33 = 1.0f; SphereMapMatrixD3D9._34 = 0.0f;
\r
64 SphereMapMatrixD3D9._41 = 0.5f; SphereMapMatrixD3D9._42 = 0.5f;
\r
65 SphereMapMatrixD3D9._43 = 0.0f; SphereMapMatrixD3D9._44 = 1.0f;
\r
68 UnitMatrixD3D9 = *(D3DMATRIX*)((void*)mat.pointer());
\r
70 // init direct 3d is done in the factory function
\r
75 CD3D9Driver::~CD3D9Driver()
\r
77 deleteMaterialRenders();
\r
78 deleteAllTextures();
\r
79 removeAllOcclusionQueries();
\r
80 removeAllHardwareBuffers();
\r
82 if (DepthStencilSurface)
\r
83 DepthStencilSurface->Release();
\r
90 pID3DDevice->Release();
\r
97 void CD3D9Driver::createMaterialRenderers()
\r
99 // create D3D9 material renderers
\r
101 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID(pID3DDevice, this));
\r
102 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID_2_LAYER(pID3DDevice, this));
\r
104 // add the same renderer for all lightmap types
\r
106 CD3D9MaterialRenderer_LIGHTMAP* lmr = new CD3D9MaterialRenderer_LIGHTMAP(pID3DDevice, this);
\r
107 addMaterialRenderer(lmr); // for EMT_LIGHTMAP:
\r
108 addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD:
\r
109 addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2:
\r
110 addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4:
\r
111 addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING:
\r
112 addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2:
\r
113 addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4:
\r
116 // add remaining fixed function pipeline material renderers
\r
118 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_DETAIL_MAP(pID3DDevice, this));
\r
119 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SPHERE_MAP(pID3DDevice, this));
\r
120 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_REFLECTION_2_LAYER(pID3DDevice, this));
\r
121 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(pID3DDevice, this));
\r
122 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(pID3DDevice, this));
\r
123 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(pID3DDevice, this));
\r
124 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(pID3DDevice, this));
\r
125 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(pID3DDevice, this));
\r
127 // add normal map renderers
\r
130 video::IMaterialRenderer* renderer = 0;
\r
132 renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
\r
133 MaterialRenderers[EMT_SOLID].Renderer);
\r
136 renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
\r
137 MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
\r
140 renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
\r
141 MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
\r
144 // add parallax map renderers
\r
146 renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
\r
147 MaterialRenderers[EMT_SOLID].Renderer);
\r
150 renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
\r
151 MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
\r
154 renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
\r
155 MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
\r
158 // add basic 1 texture blending
\r
159 addAndDropMaterialRenderer(new CD3D9MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this));
\r
163 //! initialises the Direct3D API
\r
164 bool CD3D9Driver::initDriver(HWND hwnd, bool pureSoftware)
\r
168 D3DLibrary = LoadLibrary( __TEXT("d3d9.dll") );
\r
172 os::Printer::log("Error, could not load d3d9.dll.", ELL_ERROR);
\r
176 typedef IDirect3D9 * (__stdcall *D3DCREATETYPE)(UINT);
\r
177 D3DCREATETYPE d3dCreate = (D3DCREATETYPE) GetProcAddress(D3DLibrary, "Direct3DCreate9");
\r
181 os::Printer::log("Error, could not get proc adress of Direct3DCreate9.", ELL_ERROR);
\r
185 //just like pID3D = Direct3DCreate9(D3D_SDK_VERSION);
\r
186 pID3D = (*d3dCreate)(D3D_SDK_VERSION);
\r
190 os::Printer::log("Error initializing D3D.", ELL_ERROR);
\r
195 // print device information
\r
196 D3DADAPTER_IDENTIFIER9 dai;
\r
197 if (!FAILED(pID3D->GetAdapterIdentifier(Params.DisplayAdapter, 0, &dai)))
\r
201 s32 Product = HIWORD(dai.DriverVersion.HighPart);
\r
202 s32 Version = LOWORD(dai.DriverVersion.HighPart);
\r
203 s32 SubVersion = HIWORD(dai.DriverVersion.LowPart);
\r
204 s32 Build = LOWORD(dai.DriverVersion.LowPart);
\r
206 sprintf(tmp, "%s %s %d.%d.%d.%d", dai.Description, dai.Driver, Product, Version,
\r
207 SubVersion, Build);
\r
208 os::Printer::log(tmp, ELL_INFORMATION);
\r
210 // Assign vendor name based on vendor id.
\r
211 VendorID= static_cast<u16>(dai.VendorId);
\r
212 switch(dai.VendorId)
\r
214 case 0x1002 : VendorName = "ATI Technologies Inc."; break;
\r
215 case 0x10DE : VendorName = "NVIDIA Corporation"; break;
\r
216 case 0x102B : VendorName = "Matrox Electronic Systems Ltd."; break;
\r
217 case 0x121A : VendorName = "3dfx Interactive Inc"; break;
\r
218 case 0x5333 : VendorName = "S3 Graphics Co., Ltd."; break;
\r
219 case 0x8086 : VendorName = "Intel Corporation"; break;
\r
220 default: VendorName = "Unknown VendorId: ";VendorName += (u32)dai.VendorId; break;
\r
224 D3DDISPLAYMODE d3ddm;
\r
225 if (FAILED(pID3D->GetAdapterDisplayMode(Params.DisplayAdapter, &d3ddm)))
\r
227 os::Printer::log("Error: Could not get Adapter Display mode.", ELL_ERROR);
\r
231 ZeroMemory(&present, sizeof(present));
\r
233 present.BackBufferCount = 1;
\r
234 present.EnableAutoDepthStencil = TRUE;
\r
236 present.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
\r
238 present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
\r
240 if (Params.Fullscreen)
\r
242 present.BackBufferWidth = Params.WindowSize.Width;
\r
243 present.BackBufferHeight = Params.WindowSize.Height;
\r
244 // request 32bit mode if user specified 32 bit, added by Thomas Stuefe
\r
245 if (Params.Bits == 32)
\r
246 present.BackBufferFormat = D3DFMT_X8R8G8B8;
\r
248 present.BackBufferFormat = D3DFMT_R5G6B5;
\r
249 present.SwapEffect = D3DSWAPEFFECT_FLIP;
\r
250 present.Windowed = FALSE;
\r
251 present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
\r
255 present.BackBufferFormat = d3ddm.Format;
\r
256 present.SwapEffect = D3DSWAPEFFECT_DISCARD;
\r
257 present.Windowed = TRUE;
\r
260 UINT adapter = Params.DisplayAdapter;
\r
261 D3DDEVTYPE devtype = D3DDEVTYPE_HAL;
\r
262 #ifndef _IRR_D3D_NO_SHADER_DEBUGGING
\r
263 devtype = D3DDEVTYPE_REF;
\r
264 #elif defined(_IRR_USE_NVIDIA_PERFHUD_)
\r
265 for (UINT adapter_i = 0; adapter_i < pID3D->GetAdapterCount(); ++adapter_i)
\r
267 D3DADAPTER_IDENTIFIER9 identifier;
\r
268 pID3D->GetAdapterIdentifier(adapter_i,0,&identifier);
\r
269 if (strstr(identifier.Description,"PerfHUD") != 0)
\r
271 adapter = adapter_i;
\r
272 devtype = D3DDEVTYPE_REF;
\r
278 // enable anti alias if possible and desired
\r
279 if (Params.AntiAlias > 0)
\r
281 if (Params.AntiAlias > 32)
\r
282 Params.AntiAlias = 32;
\r
284 DWORD qualityLevels = 0;
\r
286 while(Params.AntiAlias > 0)
\r
288 if(SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter,
\r
289 devtype, present.BackBufferFormat, !Params.Fullscreen,
\r
290 (D3DMULTISAMPLE_TYPE)Params.AntiAlias, &qualityLevels)))
\r
292 present.MultiSampleType = (D3DMULTISAMPLE_TYPE)Params.AntiAlias;
\r
293 present.MultiSampleQuality = qualityLevels-1;
\r
294 present.SwapEffect = D3DSWAPEFFECT_DISCARD;
\r
297 --Params.AntiAlias;
\r
300 if (Params.AntiAlias==0)
\r
302 os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING);
\r
306 // check stencil buffer compatibility
\r
307 if (Params.Stencilbuffer)
\r
309 present.AutoDepthStencilFormat = D3DFMT_D24S8;
\r
310 if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
\r
311 present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
\r
312 D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
\r
314 present.AutoDepthStencilFormat = D3DFMT_D24X4S4;
\r
315 if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
\r
316 present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
\r
317 D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
\r
319 present.AutoDepthStencilFormat = D3DFMT_D15S1;
\r
320 if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
\r
321 present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
\r
322 D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
\r
324 os::Printer::log("Device does not support stencilbuffer, disabling stencil buffer.", ELL_WARNING);
\r
325 Params.Stencilbuffer = false;
\r
330 if(FAILED(pID3D->CheckDepthStencilMatch(adapter, devtype,
\r
331 present.BackBufferFormat, present.BackBufferFormat, present.AutoDepthStencilFormat)))
\r
333 os::Printer::log("Depth-stencil format is not compatible with display format, disabling stencil buffer.", ELL_WARNING);
\r
334 Params.Stencilbuffer = false;
\r
337 // do not use else here to cope with flag change in previous block
\r
338 if (!Params.Stencilbuffer)
\r
340 present.AutoDepthStencilFormat = D3DFMT_D32;
\r
341 if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
\r
342 present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
\r
343 D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
\r
345 present.AutoDepthStencilFormat = D3DFMT_D24X8;
\r
346 if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
\r
347 present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
\r
348 D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
\r
350 present.AutoDepthStencilFormat = D3DFMT_D16;
\r
351 if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype,
\r
352 present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
\r
353 D3DRTYPE_SURFACE, present.AutoDepthStencilFormat)))
\r
355 os::Printer::log("Device does not support required depth buffer.", ELL_WARNING);
\r
364 DWORD fpuPrecision = Params.HighPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0;
\r
365 DWORD multithreaded = Params.DriverMultithreaded ? D3DCREATE_MULTITHREADED : 0;
\r
368 if (FAILED(pID3D->CreateDevice(Params.DisplayAdapter, D3DDEVTYPE_REF, hwnd,
\r
369 fpuPrecision | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice)))
\r
370 os::Printer::log("Was not able to create Direct3D9 software device.", ELL_ERROR);
\r
374 HRESULT hr = pID3D->CreateDevice(adapter, devtype, hwnd,
\r
375 fpuPrecision | multithreaded | D3DCREATE_HARDWARE_VERTEXPROCESSING, &present, &pID3DDevice);
\r
378 hr = pID3D->CreateDevice(adapter, devtype, hwnd,
\r
379 fpuPrecision | multithreaded | D3DCREATE_MIXED_VERTEXPROCESSING , &present, &pID3DDevice);
\r
382 hr = pID3D->CreateDevice(adapter, devtype, hwnd,
\r
383 fpuPrecision | multithreaded | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice);
\r
386 os::Printer::log("Was not able to create Direct3D9 device.", ELL_ERROR);
\r
391 os::Printer::log("Was not able to create DIRECT3D9 device.", ELL_ERROR);
\r
396 pID3DDevice->GetDeviceCaps(&Caps);
\r
398 os::Printer::log("Currently available Video Memory (kB)", core::stringc(pID3DDevice->GetAvailableTextureMem()/1024).c_str());
\r
400 // disable stencilbuffer if necessary
\r
401 if (Params.Stencilbuffer &&
\r
402 (!(Caps.StencilCaps & D3DSTENCILCAPS_DECRSAT) ||
\r
403 !(Caps.StencilCaps & D3DSTENCILCAPS_INCRSAT) ||
\r
404 !(Caps.StencilCaps & D3DSTENCILCAPS_KEEP)))
\r
406 os::Printer::log("Device not able to use stencil buffer, disabling stencil buffer.", ELL_WARNING);
\r
407 Params.Stencilbuffer = false;
\r
411 BridgeCalls = new CD3D9CallBridge(pID3DDevice, this);
\r
413 // set default vertex shader
\r
414 setVertexShader(EVT_STANDARD);
\r
417 setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
\r
419 // set exposed data
\r
420 ExposedData.D3D9.D3D9 = pID3D;
\r
421 ExposedData.D3D9.D3DDev9 = pID3DDevice;
\r
422 ExposedData.D3D9.HWnd = hwnd;
\r
424 ResetRenderStates = true;
\r
426 // create materials
\r
427 createMaterialRenderers();
\r
429 MaxFixedPipelineTextureUnits = (u32)Caps.MaxSimultaneousTextures;
\r
430 DriverAttributes->setAttribute("MaxSupportedTextures", (s32)MaxFixedPipelineTextureUnits);
\r
432 u32 maxTextureSamplers = (Caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) ? 16 : (Caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) ?
\r
433 6 : (Caps.PixelShaderVersion >= D3DPS_VERSION(1, 0)) ? 4 : 0;
\r
435 MaxTextureUnits = core::max_(MaxFixedPipelineTextureUnits, maxTextureSamplers);
\r
436 MaxTextureUnits = core::min_(MaxTextureUnits, MATERIAL_MAX_TEXTURES);
\r
437 MaxTextureUnits = core::min_(MaxTextureUnits, MATERIAL_MAX_TEXTURES_USED);
\r
439 MaxUserClipPlanes = (u32)Caps.MaxUserClipPlanes;
\r
440 OcclusionQuerySupport=(pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL) == S_OK);
\r
442 if (VendorID==0x10DE)//NVidia
\r
443 AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL,
\r
444 D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
\r
445 (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK);
\r
446 else if (VendorID==0x1002)//ATI
\r
447 AlphaToCoverageSupport = true; // TODO: Check unknown
\r
449 AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL,
\r
450 D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
\r
451 (D3DFORMAT)MAKEFOURCC('A','2','M','1')) == S_OK);
\r
454 DriverAttributes->setAttribute("MaxTextures", (s32)MaxTextureUnits);
\r
455 DriverAttributes->setAttribute("MaxLights", (s32)Caps.MaxActiveLights);
\r
456 DriverAttributes->setAttribute("MaxAnisotropy", (s32)Caps.MaxAnisotropy);
\r
457 DriverAttributes->setAttribute("MaxUserClipPlanes", (s32)Caps.MaxUserClipPlanes);
\r
458 DriverAttributes->setAttribute("MaxMultipleRenderTargets", (s32)Caps.NumSimultaneousRTs);
\r
459 DriverAttributes->setAttribute("MaxIndices", (s32)Caps.MaxVertexIndex);
\r
460 DriverAttributes->setAttribute("MaxTextureSize", (s32)core::min_(Caps.MaxTextureHeight,Caps.MaxTextureWidth));
\r
461 DriverAttributes->setAttribute("MaxTextureLODBias", 16);
\r
462 DriverAttributes->setAttribute("Version", 901);
\r
463 DriverAttributes->setAttribute("ShaderLanguageVersion", (s32)(((0x00ff00 & Caps.VertexShaderVersion)>>8)*100 + (Caps.VertexShaderVersion&0xff)));
\r
464 DriverAttributes->setAttribute("AntiAlias", Params.AntiAlias);
\r
466 // set the renderstates
\r
467 setRenderStates3DMode();
\r
469 // store the screen's depth buffer descriptor
\r
470 if (!SUCCEEDED(pID3DDevice->GetDepthStencilSurface(&DepthStencilSurface)))
\r
472 os::Printer::log("Was not able to get main depth buffer.", ELL_ERROR);
\r
476 D3DColorFormat = D3DFMT_A8R8G8B8;
\r
477 IDirect3DSurface9* bb = 0;
\r
478 if (SUCCEEDED(pID3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &bb)))
\r
480 D3DSURFACE_DESC desc;
\r
481 bb->GetDesc(&desc);
\r
482 D3DColorFormat = desc.Format;
\r
484 if (D3DColorFormat == D3DFMT_X8R8G8B8)
\r
485 D3DColorFormat = D3DFMT_A8R8G8B8;
\r
489 ColorFormat = getColorFormatFromD3DFormat(D3DColorFormat);
\r
491 ActiveRenderTarget.set_used((u32)Caps.NumSimultaneousRTs);
\r
493 for (u32 i = 0; i < ActiveRenderTarget.size(); ++i)
\r
494 ActiveRenderTarget[i] = false;
\r
500 bool CD3D9Driver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
\r
502 CNullDriver::beginScene(clearFlag, clearColor, clearDepth, clearStencil, videoData, sourceRect);
\r
503 WindowId = (HWND)videoData.D3D9.HWnd;
\r
504 SceneSourceRect = sourceRect;
\r
512 if ( !retrieveDevice(1) )
\r
516 clearBuffers(clearFlag, clearColor, clearDepth, clearStencil);
\r
518 hr = pID3DDevice->BeginScene();
\r
521 os::Printer::log("DIRECT3D9 begin scene failed.", ELL_WARNING);
\r
528 bool CD3D9Driver::endScene()
\r
530 CNullDriver::endScene();
\r
531 DriverWasReset=false;
\r
533 HRESULT hr = pID3DDevice->EndScene();
\r
536 os::Printer::log("DIRECT3D9 end scene failed.", ELL_WARNING);
\r
541 RECT sourceRectData;
\r
542 if ( SceneSourceRect )
\r
544 srcRct = &sourceRectData;
\r
545 sourceRectData.left = SceneSourceRect->UpperLeftCorner.X;
\r
546 sourceRectData.top = SceneSourceRect->UpperLeftCorner.Y;
\r
547 sourceRectData.right = SceneSourceRect->LowerRightCorner.X;
\r
548 sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y;
\r
551 IDirect3DSwapChain9* swChain;
\r
552 hr = pID3DDevice->GetSwapChain(0, &swChain);
\r
553 DWORD flags = (Params.HandleSRGB && (Caps.Caps3&D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION))?D3DPRESENT_LINEAR_CONTENT:0;
\r
554 hr = swChain->Present(srcRct, NULL, WindowId, NULL, flags);
\r
555 swChain->Release();
\r
560 if (hr == D3DERR_DEVICELOST)
\r
563 os::Printer::log("Present failed", "DIRECT3D9 device lost.", ELL_WARNING);
\r
565 #ifdef D3DERR_DEVICEREMOVED
\r
566 else if (hr == D3DERR_DEVICEREMOVED)
\r
568 os::Printer::log("Present failed", "Device removed.", ELL_WARNING);
\r
571 else if (hr == D3DERR_INVALIDCALL)
\r
573 os::Printer::log("Present failed", "Invalid Call", ELL_WARNING);
\r
576 os::Printer::log("DIRECT3D9 present failed.", ELL_WARNING);
\r
581 //! queries the features of the driver, returns true if feature is available
\r
582 bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
\r
584 if (!FeatureEnabled[feature])
\r
589 case EVDF_MULTITEXTURE:
\r
590 case EVDF_BILINEAR_FILTER:
\r
592 case EVDF_RENDER_TO_TARGET:
\r
593 return Caps.NumSimultaneousRTs > 0;
\r
594 case EVDF_HARDWARE_TL:
\r
595 return (Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0;
\r
597 return (Caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) != 0;
\r
598 case EVDF_MIP_MAP_AUTO_UPDATE:
\r
599 return (Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0;
\r
600 case EVDF_STENCIL_BUFFER:
\r
601 return Params.Stencilbuffer && Caps.StencilCaps;
\r
602 case EVDF_VERTEX_SHADER_1_1:
\r
603 return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
\r
604 case EVDF_VERTEX_SHADER_2_0:
\r
605 return Caps.VertexShaderVersion >= D3DVS_VERSION(2,0);
\r
606 case EVDF_VERTEX_SHADER_3_0:
\r
607 return Caps.VertexShaderVersion >= D3DVS_VERSION(3,0);
\r
608 case EVDF_PIXEL_SHADER_1_1:
\r
609 return Caps.PixelShaderVersion >= D3DPS_VERSION(1,1);
\r
610 case EVDF_PIXEL_SHADER_1_2:
\r
611 return Caps.PixelShaderVersion >= D3DPS_VERSION(1,2);
\r
612 case EVDF_PIXEL_SHADER_1_3:
\r
613 return Caps.PixelShaderVersion >= D3DPS_VERSION(1,3);
\r
614 case EVDF_PIXEL_SHADER_1_4:
\r
615 return Caps.PixelShaderVersion >= D3DPS_VERSION(1,4);
\r
616 case EVDF_PIXEL_SHADER_2_0:
\r
617 return Caps.PixelShaderVersion >= D3DPS_VERSION(2,0);
\r
618 case EVDF_PIXEL_SHADER_3_0:
\r
619 return Caps.PixelShaderVersion >= D3DPS_VERSION(3,0);
\r
621 return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
\r
622 case EVDF_TEXTURE_NSQUARE:
\r
623 return (Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) == 0;
\r
624 case EVDF_TEXTURE_NPOT:
\r
625 return (Caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0;
\r
626 case EVDF_COLOR_MASK:
\r
627 return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0;
\r
628 case EVDF_MULTIPLE_RENDER_TARGETS:
\r
629 return Caps.NumSimultaneousRTs > 1;
\r
630 case EVDF_MRT_COLOR_MASK:
\r
631 return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_INDEPENDENTWRITEMASKS) != 0;
\r
632 case EVDF_MRT_BLEND:
\r
633 return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) != 0;
\r
634 case EVDF_OCCLUSION_QUERY:
\r
635 return OcclusionQuerySupport;
\r
636 case EVDF_POLYGON_OFFSET:
\r
637 return (Caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS|D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) != 0;
\r
638 case EVDF_BLEND_OPERATIONS:
\r
640 case EVDF_BLEND_SEPARATE:
\r
641 return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) != 0;
\r
642 case EVDF_TEXTURE_MATRIX:
\r
644 case EVDF_TEXTURE_COMPRESSED_DXT:
\r
646 case EVDF_TEXTURE_CUBEMAP:
\r
654 //! sets transformation
\r
655 void CD3D9Driver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
\r
657 Transformation3DChanged = true;
\r
662 pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)mat.pointer()));
\r
665 pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)mat.pointer()));
\r
667 case ETS_PROJECTION:
\r
668 pID3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)((void*)mat.pointer()));
\r
674 const s32 stage = state - ETS_TEXTURE_0;
\r
676 if ( stage < static_cast<s32>(MaxTextureUnits)
\r
677 && stage < static_cast<s32>(MaxFixedPipelineTextureUnits)) // texture transforms for shader pipeline have to be passed by user
\r
679 if (mat.isIdentity())
\r
680 pID3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
\r
683 pID3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
\r
684 pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), (D3DMATRIX*)((void*)mat.pointer()));
\r
691 Matrices[state] = mat;
\r
695 //! sets the current Texture
\r
696 bool CD3D9Driver::setActiveTexture(u32 stage, const video::ITexture* texture)
\r
698 if (CurrentTexture[stage] == texture)
\r
701 if (texture && texture->getDriverType() != EDT_DIRECT3D9)
\r
703 os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
\r
707 CurrentTexture[stage] = texture;
\r
711 pID3DDevice->SetTexture(stage, 0);
\r
712 pID3DDevice->SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
\r
716 pID3DDevice->SetTexture(stage, ((const CD3D9Texture*)texture)->getDX9BaseTexture());
\r
719 pID3DDevice->SetTexture(D3DVERTEXTEXTURESAMPLER0 + stage, ((const CD3D9Texture*)texture)->getDX9BaseTexture());
\r
725 //! sets a material
\r
726 void CD3D9Driver::setMaterial(const SMaterial& material)
\r
728 Material = material;
\r
729 OverrideMaterial.apply(Material);
\r
731 for (u32 i=0; i<MaxTextureUnits; ++i)
\r
733 const ITexture* texture = Material.getTexture(i);
\r
734 setActiveTexture(i, texture);
\r
737 setTransform((E_TRANSFORMATION_STATE) ( ETS_TEXTURE_0 + i ),
\r
738 material.getTextureMatrix(i));
\r
743 ITexture* CD3D9Driver::createDeviceDependentTexture(const io::path& name, IImage* image)
\r
745 core::array<IImage*> imageArray(1);
\r
746 imageArray.push_back(image);
\r
748 CD3D9Texture* texture = new CD3D9Texture(name, imageArray, ETT_2D, this);
\r
749 if ( !texture->getDX9Texture() )
\r
758 ITexture* CD3D9Driver::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)
\r
760 CD3D9Texture* texture = new CD3D9Texture(name, image, ETT_CUBEMAP, this);
\r
762 if ( !texture->getDX9CubeTexture() )
\r
771 bool CD3D9Driver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)
\r
773 if (target && target->getDriverType() != EDT_DIRECT3D9)
\r
775 os::Printer::log("Fatal Error: Tried to set a render target not owned by this driver.", ELL_ERROR);
\r
781 // Store main render target.
\r
783 if (!BackBufferSurface)
\r
785 if (FAILED(pID3DDevice->GetRenderTarget(0, &BackBufferSurface)))
\r
787 os::Printer::log("Could not get main render target.", ELL_ERROR);
\r
792 // Set new color textures.
\r
794 CD3D9RenderTarget* renderTarget = static_cast<CD3D9RenderTarget*>(target);
\r
796 const u32 surfaceSize = core::min_(renderTarget->getSurfaceCount(), ActiveRenderTarget.size());
\r
798 for (u32 i = 0; i < surfaceSize; ++i)
\r
800 ActiveRenderTarget[i] = true;
\r
802 if (FAILED(pID3DDevice->SetRenderTarget(i, renderTarget->getSurface(i))))
\r
804 ActiveRenderTarget[i] = false;
\r
806 os::Printer::log("Error: Could not set render target.", ELL_ERROR);
\r
810 // Reset other render target channels.
\r
812 for (u32 i = surfaceSize; i < ActiveRenderTarget.size(); ++i)
\r
814 if (ActiveRenderTarget[i])
\r
816 pID3DDevice->SetRenderTarget(i, 0);
\r
817 ActiveRenderTarget[i] = false;
\r
821 // Set depth stencil buffer.
\r
823 IDirect3DSurface9* depthStencilSurface = renderTarget->getDepthStencilSurface();
\r
825 if (depthStencilSurface && FAILED(pID3DDevice->SetDepthStencilSurface(depthStencilSurface)))
\r
827 os::Printer::log("Error: Could not set depth-stencil buffer.", ELL_ERROR);
\r
830 // Set other settings.
\r
832 CurrentRenderTargetSize = renderTarget->getSize();
\r
833 Transformation3DChanged = true;
\r
835 else if (CurrentRenderTarget != target)
\r
837 // Set main render target.
\r
839 if (BackBufferSurface)
\r
841 ActiveRenderTarget[0] = true;
\r
843 if (FAILED(pID3DDevice->SetRenderTarget(0, BackBufferSurface)))
\r
845 os::Printer::log("Error: Could not set main render target.", ELL_ERROR);
\r
846 ActiveRenderTarget[0] = false;
\r
851 BackBufferSurface->Release();
\r
852 BackBufferSurface = 0;
\r
855 // Reset other render target channels.
\r
857 for (u32 i = 1; i < ActiveRenderTarget.size(); ++i)
\r
859 if (ActiveRenderTarget[i])
\r
861 pID3DDevice->SetRenderTarget(i, 0);
\r
862 ActiveRenderTarget[i] = false;
\r
866 // Set main depth-stencil stencil buffer.
\r
868 if (FAILED(pID3DDevice->SetDepthStencilSurface(DepthStencilSurface)))
\r
870 os::Printer::log("Error: Could not set main depth-stencil buffer.", ELL_ERROR);
\r
873 // Set other settings.
\r
875 CurrentRenderTargetSize = core::dimension2d<u32>(0, 0);
\r
876 Transformation3DChanged = true;
\r
879 CurrentRenderTarget = target;
\r
881 clearBuffers(clearFlag, clearColor, clearDepth, clearStencil);
\r
887 //! sets a viewport
\r
888 void CD3D9Driver::setViewPort(const core::rect<s32>& area)
\r
890 core::rect<s32> vp = area;
\r
891 core::rect<s32> rendert(0,0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height);
\r
892 vp.clipAgainst(rendert);
\r
893 if (vp.getHeight()>0 && vp.getWidth()>0)
\r
895 D3DVIEWPORT9 viewPort;
\r
896 viewPort.X = vp.UpperLeftCorner.X;
\r
897 viewPort.Y = vp.UpperLeftCorner.Y;
\r
898 viewPort.Width = vp.getWidth();
\r
899 viewPort.Height = vp.getHeight();
\r
900 viewPort.MinZ = 0.0f;
\r
901 viewPort.MaxZ = 1.0f;
\r
903 HRESULT hr = pID3DDevice->SetViewport(&viewPort);
\r
905 os::Printer::log("Failed setting the viewport.", ELL_WARNING);
\r
912 //! gets the area of the current viewport
\r
913 const core::rect<s32>& CD3D9Driver::getViewPort() const
\r
919 bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer)
\r
924 const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer;
\r
925 const void* vertices=mb->getVertices();
\r
926 const u32 vertexCount=mb->getVertexCount();
\r
927 const E_VERTEX_TYPE vType=mb->getVertexType();
\r
928 const u32 vertexSize = getVertexPitchFromType(vType);
\r
929 const u32 bufSize = vertexSize * vertexCount;
\r
931 if (!hwBuffer->vertexBuffer || (bufSize > hwBuffer->vertexBufferSize))
\r
933 if (hwBuffer->vertexBuffer)
\r
935 hwBuffer->vertexBuffer->Release();
\r
936 hwBuffer->vertexBuffer=0;
\r
940 // Get the vertex sizes and cvf
\r
944 FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
\r
947 FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2;
\r
950 FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3;
\r
956 DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
\r
957 if (hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
\r
958 flags |= D3DUSAGE_DYNAMIC;
\r
960 if (FAILED(pID3DDevice->CreateVertexBuffer(bufSize, flags, FVF, D3DPOOL_DEFAULT, &hwBuffer->vertexBuffer, NULL)))
\r
962 hwBuffer->vertexBufferSize = bufSize;
\r
964 flags = 0; // SIO2: Reset flags before Lock
\r
965 if (hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
\r
966 flags = D3DLOCK_DISCARD;
\r
968 void* lockedBuffer = 0;
\r
969 hwBuffer->vertexBuffer->Lock(0, bufSize, (void**)&lockedBuffer, flags);
\r
970 memcpy(lockedBuffer, vertices, bufSize);
\r
971 hwBuffer->vertexBuffer->Unlock();
\r
975 void* lockedBuffer = 0;
\r
976 hwBuffer->vertexBuffer->Lock(0, bufSize, (void**)&lockedBuffer, D3DLOCK_DISCARD);
\r
977 memcpy(lockedBuffer, vertices, bufSize);
\r
978 hwBuffer->vertexBuffer->Unlock();
\r
985 bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer)
\r
990 const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer;
\r
991 const u16* indices=mb->getIndices();
\r
992 const u32 indexCount=mb->getIndexCount();
\r
994 D3DFORMAT indexType=D3DFMT_UNKNOWN;
\r
995 switch (mb->getIndexType())
\r
999 indexType=D3DFMT_INDEX16;
\r
1005 indexType=D3DFMT_INDEX32;
\r
1011 const u32 bufSize = indexSize * indexCount;
\r
1012 if (!hwBuffer->indexBuffer || (bufSize > hwBuffer->indexBufferSize))
\r
1014 if (hwBuffer->indexBuffer)
\r
1016 hwBuffer->indexBuffer->Release();
\r
1017 hwBuffer->indexBuffer=0;
\r
1020 DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
\r
1021 if (hwBuffer->Mapped_Index != scene::EHM_STATIC)
\r
1022 flags |= D3DUSAGE_DYNAMIC; // SIO2: Add DYNAMIC flag for dynamic buffer data
\r
1024 if (FAILED(pID3DDevice->CreateIndexBuffer(bufSize, flags, indexType, D3DPOOL_DEFAULT, &hwBuffer->indexBuffer, NULL)))
\r
1027 flags = 0; // SIO2: Reset flags before Lock
\r
1028 if (hwBuffer->Mapped_Index != scene::EHM_STATIC)
\r
1029 flags = D3DLOCK_DISCARD;
\r
1031 void* lockedBuffer = 0;
\r
1032 if (FAILED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&lockedBuffer, flags)))
\r
1035 memcpy(lockedBuffer, indices, bufSize);
\r
1036 hwBuffer->indexBuffer->Unlock();
\r
1038 hwBuffer->indexBufferSize = bufSize;
\r
1042 void* lockedBuffer = 0;
\r
1043 if( SUCCEEDED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&lockedBuffer, D3DLOCK_DISCARD)))
\r
1045 memcpy(lockedBuffer, indices, bufSize);
\r
1046 hwBuffer->indexBuffer->Unlock();
\r
1054 //! updates hardware buffer if needed
\r
1055 bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *hwBuffer)
\r
1060 if (hwBuffer->Mapped_Vertex!=scene::EHM_NEVER)
\r
1062 if (hwBuffer->ChangedID_Vertex != hwBuffer->MeshBuffer->getChangedID_Vertex()
\r
1063 || !((SHWBufferLink_d3d9*)hwBuffer)->vertexBuffer)
\r
1065 hwBuffer->ChangedID_Vertex = hwBuffer->MeshBuffer->getChangedID_Vertex();
\r
1067 if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer))
\r
1072 if (hwBuffer->Mapped_Index!=scene::EHM_NEVER)
\r
1074 if (hwBuffer->ChangedID_Index != hwBuffer->MeshBuffer->getChangedID_Index()
\r
1075 || !((SHWBufferLink_d3d9*)hwBuffer)->indexBuffer)
\r
1077 hwBuffer->ChangedID_Index = hwBuffer->MeshBuffer->getChangedID_Index();
\r
1079 if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer))
\r
1088 //! Create hardware buffer from meshbuffer
\r
1089 CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMeshBuffer* mb)
\r
1091 // Looks like d3d does not support only partial buffering, so refuse
\r
1092 // in any case of NEVER
\r
1093 if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER || mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
\r
1096 SHWBufferLink_d3d9 *hwBuffer=new SHWBufferLink_d3d9(mb);
\r
1099 HWBufferMap.insert(hwBuffer->MeshBuffer, hwBuffer);
\r
1101 hwBuffer->ChangedID_Vertex=hwBuffer->MeshBuffer->getChangedID_Vertex();
\r
1102 hwBuffer->ChangedID_Index=hwBuffer->MeshBuffer->getChangedID_Index();
\r
1103 hwBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex();
\r
1104 hwBuffer->Mapped_Index=mb->getHardwareMappingHint_Index();
\r
1105 hwBuffer->LastUsed=0;
\r
1106 hwBuffer->vertexBuffer=0;
\r
1107 hwBuffer->indexBuffer=0;
\r
1108 hwBuffer->vertexBufferSize=0;
\r
1109 hwBuffer->indexBufferSize=0;
\r
1111 if (!updateHardwareBuffer(hwBuffer))
\r
1113 deleteHardwareBuffer(hwBuffer);
\r
1121 void CD3D9Driver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer)
\r
1126 SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer;
\r
1127 if (HWBuffer->indexBuffer)
\r
1129 HWBuffer->indexBuffer->Release();
\r
1130 HWBuffer->indexBuffer = 0;
\r
1133 if (HWBuffer->vertexBuffer)
\r
1135 HWBuffer->vertexBuffer->Release();
\r
1136 HWBuffer->vertexBuffer = 0;
\r
1139 CNullDriver::deleteHardwareBuffer(_HWBuffer);
\r
1143 //! Draw hardware buffer
\r
1144 void CD3D9Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer)
\r
1149 SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer;
\r
1151 updateHardwareBuffer(HWBuffer); //check if update is needed
\r
1153 HWBuffer->LastUsed=0;//reset count
\r
1155 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
\r
1156 const E_VERTEX_TYPE vType = mb->getVertexType();
\r
1157 const u32 stride = getVertexPitchFromType(vType);
\r
1158 const void* vPtr = mb->getVertices();
\r
1159 const void* iPtr = mb->getIndices();
\r
1160 if (HWBuffer->vertexBuffer)
\r
1162 pID3DDevice->SetStreamSource(0, HWBuffer->vertexBuffer, 0, stride);
\r
1165 if (HWBuffer->indexBuffer)
\r
1167 pID3DDevice->SetIndices(HWBuffer->indexBuffer);
\r
1171 drawVertexPrimitiveList(vPtr, mb->getVertexCount(), iPtr, mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), mb->getIndexType());
\r
1173 if (HWBuffer->vertexBuffer)
\r
1174 pID3DDevice->SetStreamSource(0, 0, 0, 0);
\r
1175 if (HWBuffer->indexBuffer)
\r
1176 pID3DDevice->SetIndices(0);
\r
1180 //! Create occlusion query.
\r
1181 /** Use node for identification and mesh for occlusion test. */
\r
1182 void CD3D9Driver::addOcclusionQuery(scene::ISceneNode* node,
\r
1183 const scene::IMesh* mesh)
\r
1185 if (!queryFeature(EVDF_OCCLUSION_QUERY))
\r
1187 CNullDriver::addOcclusionQuery(node, mesh);
\r
1188 const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1189 if ((index != -1) && (OcclusionQueries[index].PID == 0))
\r
1190 pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, reinterpret_cast<IDirect3DQuery9**>(&OcclusionQueries[index].PID));
\r
1194 //! Remove occlusion query.
\r
1195 void CD3D9Driver::removeOcclusionQuery(scene::ISceneNode* node)
\r
1197 const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1200 if (OcclusionQueries[index].PID != 0)
\r
1201 reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Release();
\r
1202 CNullDriver::removeOcclusionQuery(node);
\r
1207 //! Run occlusion query. Draws mesh stored in query.
\r
1208 /** If the mesh shall not be rendered visible, use
\r
1209 overrideMaterial to disable the color and depth buffer. */
\r
1210 void CD3D9Driver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
\r
1215 const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1218 if (OcclusionQueries[index].PID)
\r
1219 reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN);
\r
1220 CNullDriver::runOcclusionQuery(node,visible);
\r
1221 if (OcclusionQueries[index].PID)
\r
1222 reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_END);
\r
1227 //! Update occlusion query. Retrieves results from GPU.
\r
1228 /** If the query shall not block, set the flag to false.
\r
1229 Update might not occur in this case, though */
\r
1230 void CD3D9Driver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
\r
1232 const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1235 // not yet started
\r
1236 if (OcclusionQueries[index].Run==u32(~0))
\r
1238 bool available = block?true:false;
\r
1241 available=(reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK);
\r
1246 HRESULT hr = reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH);
\r
1247 available = (hr == S_OK);
\r
1250 } while (!available);
\r
1253 OcclusionQueries[index].Result = tmp;
\r
1258 //! Return query result.
\r
1259 /** Return value is the number of visible pixels/fragments.
\r
1260 The value is a safe approximation, i.e. can be larger than the
\r
1261 actual value of pixels. */
\r
1262 u32 CD3D9Driver::getOcclusionQueryResult(scene::ISceneNode* node) const
\r
1264 const s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1266 return OcclusionQueries[index].Result;
\r
1272 //! Create render target.
\r
1273 IRenderTarget* CD3D9Driver::addRenderTarget()
\r
1275 CD3D9RenderTarget* renderTarget = new CD3D9RenderTarget(this);
\r
1276 RenderTargets.push_back(renderTarget);
\r
1278 return renderTarget;
\r
1282 //! draws a vertex primitive list
\r
1283 void CD3D9Driver::drawVertexPrimitiveList(const void* vertices,
\r
1284 u32 vertexCount, const void* indexList, u32 primitiveCount,
\r
1285 E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
\r
1286 E_INDEX_TYPE iType)
\r
1288 if (!checkPrimitiveCount(primitiveCount))
\r
1291 CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType);
\r
1293 if (!vertexCount || !primitiveCount)
\r
1296 draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount,
\r
1297 vType, pType, iType, true);
\r
1301 //! draws a vertex primitive list
\r
1302 void CD3D9Driver::draw2DVertexPrimitiveList(const void* vertices,
\r
1303 u32 vertexCount, const void* indexList, u32 primitiveCount,
\r
1304 E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
\r
1305 E_INDEX_TYPE iType)
\r
1307 if (!checkPrimitiveCount(primitiveCount))
\r
1310 CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType);
\r
1312 if (!vertexCount || !primitiveCount)
\r
1315 draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount,
\r
1316 vType, pType, iType, false);
\r
1320 void CD3D9Driver::draw2D3DVertexPrimitiveList(const void* vertices,
\r
1321 u32 vertexCount, const void* indexList, u32 primitiveCount,
\r
1322 E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
\r
1323 E_INDEX_TYPE iType, bool is3D)
\r
1325 setVertexShader(vType);
\r
1327 const u32 stride = getVertexPitchFromType(vType);
\r
1329 D3DFORMAT indexType=D3DFMT_UNKNOWN;
\r
1334 indexType=D3DFMT_INDEX16;
\r
1339 indexType=D3DFMT_INDEX32;
\r
1346 if (!setRenderStates3DMode())
\r
1351 if (Material.MaterialType==EMT_ONETEXTURE_BLEND)
\r
1353 E_BLEND_FACTOR srcFact;
\r
1354 E_BLEND_FACTOR dstFact;
\r
1355 E_MODULATE_FUNC modulo;
\r
1357 unpack_textureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam);
\r
1358 setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0);
\r
1361 setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL);
\r
1366 case scene::EPT_POINT_SPRITES:
\r
1367 case scene::EPT_POINTS:
\r
1369 f32 tmp=Material.Thickness/getScreenSize().Height;
\r
1370 if (pType==scene::EPT_POINT_SPRITES)
\r
1371 pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
\r
1372 pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
\r
1373 pID3DDevice->SetRenderState(D3DRS_POINTSIZE, F2DW(tmp));
\r
1375 pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, F2DW(tmp));
\r
1376 pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, F2DW(tmp));
\r
1377 pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, F2DW(tmp));
\r
1379 pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, F2DW(tmp));
\r
1383 pID3DDevice->DrawIndexedPrimitive(D3DPT_POINTLIST, 0, 0, vertexCount, 0, primitiveCount);
\r
1387 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount,
\r
1388 primitiveCount, indexList, indexType, vertices, stride);
\r
1391 pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
\r
1392 if (pType==scene::EPT_POINT_SPRITES)
\r
1393 pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
\r
1396 case scene::EPT_LINE_STRIP:
\r
1398 pID3DDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vertexCount, 0, primitiveCount);
\r
1400 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
\r
1401 primitiveCount, indexList, indexType, vertices, stride);
\r
1403 case scene::EPT_LINE_LOOP:
\r
1406 // TODO: Implement proper hardware support for this primitive type.
\r
1407 // (No looping occurs currently because this would require a way to
\r
1408 // draw the hardware buffer with a custom set of indices. We may even
\r
1409 // need to create a new mini index buffer specifically for this
\r
1410 // primitive type.)
\r
1411 pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount);
\r
1415 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
\r
1416 primitiveCount - 1, indexList, indexType, vertices, stride);
\r
1418 u16 tmpIndices[] = {static_cast<u16>(primitiveCount - 1), 0};
\r
1420 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
\r
1421 1, tmpIndices, indexType, vertices, stride);
\r
1424 case scene::EPT_LINES:
\r
1426 pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount);
\r
1428 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
\r
1429 primitiveCount, indexList, indexType, vertices, stride);
\r
1431 case scene::EPT_TRIANGLE_STRIP:
\r
1433 pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vertexCount, 0, primitiveCount);
\r
1435 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, primitiveCount,
\r
1436 indexList, indexType, vertices, stride);
\r
1438 case scene::EPT_TRIANGLE_FAN:
\r
1440 pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vertexCount, 0, primitiveCount);
\r
1442 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, primitiveCount,
\r
1443 indexList, indexType, vertices, stride);
\r
1445 case scene::EPT_TRIANGLES:
\r
1448 pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, primitiveCount);
\r
1452 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount,
\r
1453 primitiveCount, indexList, indexType, vertices, stride);
\r
1460 void CD3D9Driver::draw2DImage(const video::ITexture* texture,
\r
1461 const core::rect<s32>& destRect,
\r
1462 const core::rect<s32>& sourceRect,
\r
1463 const core::rect<s32>* clipRect,
\r
1464 const video::SColor* const colors,
\r
1465 bool useAlphaChannelOfTexture)
\r
1470 const core::dimension2d<u32>& ss = texture->getOriginalSize();
\r
1471 core::rect<f32> tcoords;
\r
1472 tcoords.UpperLeftCorner.X = (f32)sourceRect.UpperLeftCorner.X / (f32)ss.Width;
\r
1473 tcoords.UpperLeftCorner.Y = (f32)sourceRect.UpperLeftCorner.Y / (f32)ss.Height;
\r
1474 tcoords.LowerRightCorner.X = (f32)sourceRect.LowerRightCorner.X / (f32)ss.Width;
\r
1475 tcoords.LowerRightCorner.Y = (f32)sourceRect.LowerRightCorner.Y / (f32)ss.Height;
\r
1477 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
1479 const video::SColor temp[4] =
\r
1487 const video::SColor* const useColor = colors ? colors : temp;
\r
1489 S3DVertex vtx[4]; // clock wise
\r
1490 vtx[0] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f,
\r
1491 0.0f, 0.0f, 0.0f, useColor[0],
\r
1492 tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
\r
1493 vtx[1] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f,
\r
1494 0.0f, 0.0f, 0.0f, useColor[3],
\r
1495 tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
\r
1496 vtx[2] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f,
\r
1497 0.0f, 0.0f, 0.0f, useColor[2],
\r
1498 tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
\r
1499 vtx[3] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f,
\r
1500 0.0f, 0.0f, 0.0f, useColor[1],
\r
1501 tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
\r
1503 s16 indices[6] = {0,1,2,0,2,3};
\r
1505 setActiveTexture(0, texture);
\r
1507 setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 ||
\r
1508 useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255,
\r
1509 true, useAlphaChannelOfTexture);
\r
1511 setVertexShader(EVT_STANDARD);
\r
1515 pID3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
\r
1517 scissor.left = clipRect->UpperLeftCorner.X;
\r
1518 scissor.top = clipRect->UpperLeftCorner.Y;
\r
1519 scissor.right = clipRect->LowerRightCorner.X;
\r
1520 scissor.bottom = clipRect->LowerRightCorner.Y;
\r
1521 pID3DDevice->SetScissorRect(&scissor);
\r
1524 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
\r
1525 D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex));
\r
1528 pID3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
\r
1532 void CD3D9Driver::draw2DImageBatch(const video::ITexture* texture,
\r
1533 const core::array<core::position2d<s32> >& positions,
\r
1534 const core::array<core::rect<s32> >& sourceRects,
\r
1535 const core::rect<s32>* clipRect,
\r
1537 bool useAlphaChannelOfTexture)
\r
1542 if (!setActiveTexture(0, texture))
\r
1545 setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
\r
1547 const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
\r
1549 core::array<S3DVertex> vtx(drawCount * 4);
\r
1550 core::array<u16> indices(drawCount * 6);
\r
1552 for(u32 i = 0;i < drawCount;i++)
\r
1554 core::position2d<s32> targetPos = positions[i];
\r
1555 core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;
\r
1556 // This needs to be signed as it may go negative.
\r
1557 core::dimension2d<s32> sourceSize(sourceRects[i].getSize());
\r
1561 if (targetPos.X < clipRect->UpperLeftCorner.X)
\r
1563 sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
\r
1564 if (sourceSize.Width <= 0)
\r
1567 sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
\r
1568 targetPos.X = clipRect->UpperLeftCorner.X;
\r
1571 if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
\r
1573 sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
\r
1574 if (sourceSize.Width <= 0)
\r
1578 if (targetPos.Y < clipRect->UpperLeftCorner.Y)
\r
1580 sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
1581 if (sourceSize.Height <= 0)
\r
1584 sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
1585 targetPos.Y = clipRect->UpperLeftCorner.Y;
\r
1588 if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
\r
1590 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
\r
1591 if (sourceSize.Height <= 0)
\r
1596 // clip these coordinates
\r
1598 if (targetPos.X<0)
\r
1600 sourceSize.Width += targetPos.X;
\r
1601 if (sourceSize.Width <= 0)
\r
1604 sourcePos.X -= targetPos.X;
\r
1608 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
1610 if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
\r
1612 sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
\r
1613 if (sourceSize.Width <= 0)
\r
1617 if (targetPos.Y<0)
\r
1619 sourceSize.Height += targetPos.Y;
\r
1620 if (sourceSize.Height <= 0)
\r
1623 sourcePos.Y -= targetPos.Y;
\r
1627 if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
\r
1629 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
\r
1630 if (sourceSize.Height <= 0)
\r
1634 // ok, we've clipped everything.
\r
1637 core::rect<f32> tcoords;
\r
1638 tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
\r
1639 tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
\r
1640 tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
\r
1641 tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
\r
1643 const core::rect<s32> poss(targetPos, sourceSize);
\r
1645 vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
\r
1646 0.0f, 0.0f, 0.0f, color,
\r
1647 tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));
\r
1648 vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
\r
1649 0.0f, 0.0f, 0.0f, color,
\r
1650 tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));
\r
1651 vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
\r
1652 0.0f, 0.0f, 0.0f, color,
\r
1653 tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));
\r
1654 vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
\r
1655 0.0f, 0.0f, 0.0f, color,
\r
1656 tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));
\r
1658 const u32 curPos = vtx.size()-4;
\r
1659 indices.push_back(0+curPos);
\r
1660 indices.push_back(1+curPos);
\r
1661 indices.push_back(2+curPos);
\r
1663 indices.push_back(0+curPos);
\r
1664 indices.push_back(2+curPos);
\r
1665 indices.push_back(3+curPos);
\r
1670 setVertexShader(EVT_STANDARD);
\r
1672 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vtx.size(), indices.size() / 3, indices.pointer(),
\r
1673 D3DFMT_INDEX16,vtx.pointer(), sizeof(S3DVertex));
\r
1678 //! draws a 2d image, using a color and the alpha channel of the texture if
\r
1679 //! desired. The image is drawn at pos and clipped against clipRect (if != 0).
\r
1680 void CD3D9Driver::draw2DImage(const video::ITexture* texture,
\r
1681 const core::position2d<s32>& pos,
\r
1682 const core::rect<s32>& sourceRect,
\r
1683 const core::rect<s32>* clipRect, SColor color,
\r
1684 bool useAlphaChannelOfTexture)
\r
1689 if (!sourceRect.isValid())
\r
1692 if (!setActiveTexture(0, texture))
\r
1695 core::position2d<s32> targetPos = pos;
\r
1696 core::position2d<s32> sourcePos = sourceRect.UpperLeftCorner;
\r
1697 // This needs to be signed as it may go negative.
\r
1698 core::dimension2d<s32> sourceSize(sourceRect.getSize());
\r
1702 if (targetPos.X < clipRect->UpperLeftCorner.X)
\r
1704 sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
\r
1705 if (sourceSize.Width <= 0)
\r
1708 sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
\r
1709 targetPos.X = clipRect->UpperLeftCorner.X;
\r
1712 if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
\r
1714 sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
\r
1715 if (sourceSize.Width <= 0)
\r
1719 if (targetPos.Y < clipRect->UpperLeftCorner.Y)
\r
1721 sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
1722 if (sourceSize.Height <= 0)
\r
1725 sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
1726 targetPos.Y = clipRect->UpperLeftCorner.Y;
\r
1729 if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
\r
1731 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
\r
1732 if (sourceSize.Height <= 0)
\r
1737 // clip these coordinates
\r
1739 if (targetPos.X<0)
\r
1741 sourceSize.Width += targetPos.X;
\r
1742 if (sourceSize.Width <= 0)
\r
1745 sourcePos.X -= targetPos.X;
\r
1749 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
1751 if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
\r
1753 sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
\r
1754 if (sourceSize.Width <= 0)
\r
1758 if (targetPos.Y<0)
\r
1760 sourceSize.Height += targetPos.Y;
\r
1761 if (sourceSize.Height <= 0)
\r
1764 sourcePos.Y -= targetPos.Y;
\r
1768 if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
\r
1770 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
\r
1771 if (sourceSize.Height <= 0)
\r
1775 // ok, we've clipped everything.
\r
1778 core::rect<f32> tcoords;
\r
1779 tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
\r
1780 tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
\r
1781 tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
\r
1782 tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
\r
1784 const core::rect<s32> poss(targetPos, sourceSize);
\r
1786 setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
\r
1789 vtx[0] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
\r
1790 0.0f, 0.0f, 0.0f, color,
\r
1791 tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
\r
1792 vtx[1] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
\r
1793 0.0f, 0.0f, 0.0f, color,
\r
1794 tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
\r
1795 vtx[2] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
\r
1796 0.0f, 0.0f, 0.0f, color,
\r
1797 tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
\r
1798 vtx[3] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
\r
1799 0.0f, 0.0f, 0.0f, color,
\r
1800 tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
\r
1802 s16 indices[6] = {0,1,2,0,2,3};
\r
1804 setVertexShader(EVT_STANDARD);
\r
1806 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
\r
1807 D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex));
\r
1811 //!Draws a 2d rectangle with a gradient.
\r
1812 void CD3D9Driver::draw2DRectangle(const core::rect<s32>& position,
\r
1813 SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
\r
1814 const core::rect<s32>* clip)
\r
1816 core::rect<s32> pos(position);
\r
1819 pos.clipAgainst(*clip);
\r
1821 if (!pos.isValid())
\r
1825 vtx[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f,
\r
1826 0.0f, 0.0f, 0.0f, colorLeftUp, 0.0f, 0.0f);
\r
1827 vtx[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f,
\r
1828 0.0f, 0.0f, 0.0f, colorRightUp, 0.0f, 1.0f);
\r
1829 vtx[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f,
\r
1830 0.0f, 0.0f, 0.0f, colorRightDown, 1.0f, 0.0f);
\r
1831 vtx[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f,
\r
1832 0.0f, 0.0f, 0.0f, colorLeftDown, 1.0f, 1.0f);
\r
1834 s16 indices[6] = {0,1,2,0,2,3};
\r
1836 setRenderStates2DMode(
\r
1837 colorLeftUp.getAlpha() < 255 ||
\r
1838 colorRightUp.getAlpha() < 255 ||
\r
1839 colorLeftDown.getAlpha() < 255 ||
\r
1840 colorRightDown.getAlpha() < 255, false, false);
\r
1842 setActiveTexture(0,0);
\r
1844 setVertexShader(EVT_STANDARD);
\r
1846 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
\r
1847 D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex));
\r
1851 //! Draws a 2d line.
\r
1852 void CD3D9Driver::draw2DLine(const core::position2d<s32>& start,
\r
1853 const core::position2d<s32>& end,
\r
1857 drawPixel(start.X, start.Y, color);
\r
1860 // thanks to Vash TheStampede who sent in his implementation
\r
1862 vtx[0] = S3DVertex((f32)start.X+0.375f, (f32)start.Y+0.375f, 0.0f,
\r
1863 0.0f, 0.0f, 0.0f, // normal
\r
1864 color, 0.0f, 0.0f); // texture
\r
1866 vtx[1] = S3DVertex((f32)end.X+0.375f, (f32)end.Y+0.375f, 0.0f,
\r
1868 color, 0.0f, 0.0f);
\r
1870 setRenderStates2DMode(color.getAlpha() < 255, false, false);
\r
1871 setActiveTexture(0,0);
\r
1873 setVertexShader(EVT_STANDARD);
\r
1875 pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1,
\r
1876 &vtx[0], sizeof(S3DVertex) );
\r
1882 void CD3D9Driver::drawPixel(u32 x, u32 y, const SColor & color)
\r
1884 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
1885 if(x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)
\r
1888 setRenderStates2DMode(color.getAlpha() < 255, false, false);
\r
1889 setActiveTexture(0,0);
\r
1891 setVertexShader(EVT_STANDARD);
\r
1893 S3DVertex vertex((f32)x+0.375f, (f32)y+0.375f, 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f);
\r
1895 pID3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vertex, sizeof(vertex));
\r
1899 //! sets right vertex shader
\r
1900 void CD3D9Driver::setVertexShader(E_VERTEX_TYPE newType)
\r
1902 if (newType != LastVertexType)
\r
1904 LastVertexType = newType;
\r
1909 case EVT_STANDARD:
\r
1910 hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1);
\r
1912 case EVT_2TCOORDS:
\r
1913 hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2);
\r
1915 case EVT_TANGENTS:
\r
1916 hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3 |
\r
1917 D3DFVF_TEXCOORDSIZE2(0) | // real texture coord
\r
1918 D3DFVF_TEXCOORDSIZE3(1) | // misuse texture coord 2 for tangent
\r
1919 D3DFVF_TEXCOORDSIZE3(2) // misuse texture coord 3 for binormal
\r
1926 os::Printer::log("Could not set vertex Shader.", ELL_ERROR);
\r
1933 //! sets the needed renderstates
\r
1934 bool CD3D9Driver::setRenderStates3DMode()
\r
1939 if (CurrentRenderMode != ERM_3D)
\r
1941 // switch back the matrices
\r
1942 pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW]));
\r
1943 pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD]));
\r
1944 pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION]));
\r
1946 pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
\r
1947 pID3DDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
\r
1949 ResetRenderStates = true;
\r
1952 if (ResetRenderStates || LastMaterial != Material)
\r
1954 // unset old material
\r
1956 if (CurrentRenderMode == ERM_3D &&
\r
1957 LastMaterial.MaterialType != Material.MaterialType &&
\r
1958 LastMaterial.MaterialType >= 0 && LastMaterial.MaterialType < (s32)MaterialRenderers.size())
\r
1959 MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
\r
1961 // set new material.
\r
1963 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
1964 MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial(
\r
1965 Material, LastMaterial, ResetRenderStates, this);
\r
1968 bool shaderOK = true;
\r
1969 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
1970 shaderOK = MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, LastVertexType);
\r
1972 LastMaterial = Material;
\r
1974 ResetRenderStates = false;
\r
1976 CurrentRenderMode = ERM_3D;
\r
1982 //! Map Irrlicht texture wrap mode to native values
\r
1983 D3DTEXTUREADDRESS CD3D9Driver::getTextureWrapMode(const u8 clamp)
\r
1988 if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
\r
1989 return D3DTADDRESS_WRAP;
\r
1991 case ETC_CLAMP_TO_EDGE:
\r
1992 if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
\r
1993 return D3DTADDRESS_CLAMP;
\r
1995 if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
\r
1996 return D3DTADDRESS_MIRROR;
\r
1997 case ETC_CLAMP_TO_BORDER:
\r
1998 if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
\r
1999 return D3DTADDRESS_BORDER;
\r
2001 return D3DTADDRESS_CLAMP;
\r
2002 case ETC_MIRROR_CLAMP:
\r
2003 case ETC_MIRROR_CLAMP_TO_EDGE:
\r
2004 case ETC_MIRROR_CLAMP_TO_BORDER:
\r
2005 if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
\r
2006 return D3DTADDRESS_MIRRORONCE;
\r
2008 return D3DTADDRESS_CLAMP;
\r
2010 return D3DTADDRESS_WRAP;
\r
2015 //! Can be called by an IMaterialRenderer to make its work easier.
\r
2016 void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
\r
2017 bool resetAllRenderstates)
\r
2019 // This needs only to be updated onresets
\r
2020 if (Params.HandleSRGB && resetAllRenderstates)
\r
2021 pID3DDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE);
\r
2023 if (resetAllRenderstates ||
\r
2024 lastmaterial.AmbientColor != material.AmbientColor ||
\r
2025 lastmaterial.DiffuseColor != material.DiffuseColor ||
\r
2026 lastmaterial.SpecularColor != material.SpecularColor ||
\r
2027 lastmaterial.EmissiveColor != material.EmissiveColor ||
\r
2028 lastmaterial.Shininess != material.Shininess)
\r
2031 mat.Diffuse = colorToD3D(material.DiffuseColor);
\r
2032 mat.Ambient = colorToD3D(material.AmbientColor);
\r
2033 mat.Specular = colorToD3D(material.SpecularColor);
\r
2034 mat.Emissive = colorToD3D(material.EmissiveColor);
\r
2035 mat.Power = material.Shininess;
\r
2036 pID3DDevice->SetMaterial(&mat);
\r
2039 if (lastmaterial.ColorMaterial != material.ColorMaterial)
\r
2041 pID3DDevice->SetRenderState(D3DRS_COLORVERTEX, (material.ColorMaterial != ECM_NONE));
\r
2042 pID3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,
\r
2043 ((material.ColorMaterial == ECM_DIFFUSE)||
\r
2044 (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL);
\r
2045 pID3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,
\r
2046 ((material.ColorMaterial == ECM_AMBIENT)||
\r
2047 (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL);
\r
2048 pID3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE,
\r
2049 (material.ColorMaterial == ECM_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
\r
2050 pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE,
\r
2051 (material.ColorMaterial == ECM_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
\r
2055 if (resetAllRenderstates || lastmaterial.Wireframe != material.Wireframe || lastmaterial.PointCloud != material.PointCloud)
\r
2057 if (material.Wireframe)
\r
2058 pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
\r
2060 if (material.PointCloud)
\r
2061 pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT);
\r
2063 pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
\r
2068 if (resetAllRenderstates || lastmaterial.GouraudShading != material.GouraudShading)
\r
2070 if (material.GouraudShading)
\r
2071 pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
\r
2073 pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
\r
2078 if (resetAllRenderstates || lastmaterial.Lighting != material.Lighting)
\r
2080 if (material.Lighting)
\r
2081 pID3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
\r
2083 pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
\r
2088 if (resetAllRenderstates || lastmaterial.ZBuffer != material.ZBuffer)
\r
2090 switch (material.ZBuffer)
\r
2092 case ECFN_DISABLED:
\r
2093 pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
\r
2095 case ECFN_LESSEQUAL:
\r
2096 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2097 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
\r
2100 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2101 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
\r
2104 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2105 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
\r
2107 case ECFN_NOTEQUAL:
\r
2108 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2109 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL);
\r
2111 case ECFN_GREATEREQUAL:
\r
2112 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2113 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
\r
2115 case ECFN_GREATER:
\r
2116 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2117 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER);
\r
2120 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2121 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
\r
2124 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2125 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NEVER);
\r
2130 if (getWriteZBuffer(material))
\r
2132 pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
\r
2136 pID3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
\r
2139 // back face culling
\r
2141 if (resetAllRenderstates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling))
\r
2143 // if (material.FrontfaceCulling && material.BackfaceCulling)
\r
2144 // pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW|D3DCULL_CCW);
\r
2146 if (material.FrontfaceCulling)
\r
2147 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
\r
2149 if (material.BackfaceCulling)
\r
2150 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
\r
2152 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
\r
2156 if (resetAllRenderstates || lastmaterial.FogEnable != material.FogEnable)
\r
2158 pID3DDevice->SetRenderState(D3DRS_FOGENABLE, material.FogEnable);
\r
2161 // specular highlights
\r
2162 if (resetAllRenderstates || !core::equals(lastmaterial.Shininess,material.Shininess))
\r
2164 const bool enable = (material.Shininess!=0.0f);
\r
2165 pID3DDevice->SetRenderState(D3DRS_SPECULARENABLE, enable);
\r
2166 pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
\r
2170 if (resetAllRenderstates || lastmaterial.NormalizeNormals != material.NormalizeNormals)
\r
2172 pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals);
\r
2176 if (queryFeature(EVDF_COLOR_MASK) &&
\r
2177 (resetAllRenderstates || lastmaterial.ColorMask != material.ColorMask))
\r
2179 const DWORD flag =
\r
2180 ((material.ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) |
\r
2181 ((material.ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) |
\r
2182 ((material.ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) |
\r
2183 ((material.ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0);
\r
2184 pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, flag);
\r
2187 // Blend Operation
\r
2188 if (material.BlendOperation == EBO_NONE)
\r
2189 BridgeCalls->setBlend(false);
\r
2192 BridgeCalls->setBlend(true);
\r
2194 if (queryFeature(EVDF_BLEND_OPERATIONS))
\r
2196 switch (material.BlendOperation)
\r
2199 case EBO_MAX_FACTOR:
\r
2200 case EBO_MAX_ALPHA:
\r
2201 BridgeCalls->setBlendOperation(D3DBLENDOP_MAX);
\r
2204 case EBO_MIN_FACTOR:
\r
2205 case EBO_MIN_ALPHA:
\r
2206 BridgeCalls->setBlendOperation(D3DBLENDOP_MIN);
\r
2208 case EBO_SUBTRACT:
\r
2209 BridgeCalls->setBlendOperation(D3DBLENDOP_SUBTRACT);
\r
2211 case EBO_REVSUBTRACT:
\r
2212 BridgeCalls->setBlendOperation(D3DBLENDOP_REVSUBTRACT);
\r
2215 BridgeCalls->setBlendOperation(D3DBLENDOP_ADD);
\r
2222 if (IR(material.BlendFactor) & 0xFFFFFFFF // TODO: why the & 0xFFFFFFFF?
\r
2223 && material.MaterialType != EMT_ONETEXTURE_BLEND
\r
2226 E_BLEND_FACTOR srcRGBFact = EBF_ZERO;
\r
2227 E_BLEND_FACTOR dstRGBFact = EBF_ZERO;
\r
2228 E_BLEND_FACTOR srcAlphaFact = EBF_ZERO;
\r
2229 E_BLEND_FACTOR dstAlphaFact = EBF_ZERO;
\r
2230 E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;
\r
2231 u32 alphaSource = 0;
\r
2233 unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor);
\r
2235 BridgeCalls->setBlendFuncSeparate(getD3DBlend(srcRGBFact), getD3DBlend(dstRGBFact),
\r
2236 getD3DBlend(srcAlphaFact), getD3DBlend(dstAlphaFact));
\r
2240 if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderstates ||
\r
2241 lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection ||
\r
2242 lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor ||
\r
2243 lastmaterial.PolygonOffsetSlopeScale != material.PolygonOffsetSlopeScale ||
\r
2244 lastmaterial.PolygonOffsetDepthBias != material.PolygonOffsetDepthBias ))
\r
2246 if ( material.PolygonOffsetSlopeScale || material.PolygonOffsetDepthBias )
\r
2248 pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(material.PolygonOffsetSlopeScale));
\r
2249 pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(material.PolygonOffsetDepthBias));
\r
2251 else if (material.PolygonOffsetFactor)
\r
2253 if (material.PolygonOffsetDirection==EPO_BACK)
\r
2255 pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(1.f));
\r
2256 pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW((FLOAT)material.PolygonOffsetFactor));
\r
2260 pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(-1.f));
\r
2261 pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW((FLOAT)-material.PolygonOffsetFactor));
\r
2266 pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
\r
2267 pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
\r
2272 if (resetAllRenderstates || lastmaterial.AntiAliasing != material.AntiAliasing)
\r
2274 if (AlphaToCoverageSupport && (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE))
\r
2276 if (VendorID==0x10DE)//NVidia
\r
2277 pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, MAKEFOURCC('A','T','O','C'));
\r
2278 // SSAA could give better results on NVidia cards
\r
2279 else if (VendorID==0x1002)//ATI
\r
2280 pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1'));
\r
2282 else if (AlphaToCoverageSupport && (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE))
\r
2284 if (VendorID==0x10DE)
\r
2285 pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN);
\r
2286 else if (VendorID==0x1002)
\r
2287 pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0'));
\r
2290 // enable antialiasing
\r
2291 if (Params.AntiAlias)
\r
2293 if (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))
\r
2294 pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
\r
2295 else if (lastmaterial.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))
\r
2296 pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
\r
2297 if (material.AntiAliasing & (EAAM_LINE_SMOOTH))
\r
2298 pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE);
\r
2299 else if (lastmaterial.AntiAliasing & (EAAM_LINE_SMOOTH))
\r
2300 pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE);
\r
2305 if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness)
\r
2307 pID3DDevice->SetRenderState(D3DRS_POINTSIZE, F2DW(material.Thickness));
\r
2310 // texture address mode
\r
2311 for (u32 st=0; st<MaxTextureUnits; ++st)
\r
2313 if (resetAllRenderstates && Params.HandleSRGB)
\r
2314 pID3DDevice->SetSamplerState(st, D3DSAMP_SRGBTEXTURE, TRUE);
\r
2316 if (resetAllRenderstates || lastmaterial.TextureLayer[st].LODBias != material.TextureLayer[st].LODBias)
\r
2318 const float tmp = material.TextureLayer[st].LODBias * 0.125f;
\r
2319 pID3DDevice->SetSamplerState(st, D3DSAMP_MIPMAPLODBIAS, F2DW(tmp));
\r
2322 if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU)
\r
2323 pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
\r
2324 // If separate UV not supported reuse U for V
\r
2325 if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV))
\r
2327 pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
\r
2328 pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSW, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
\r
2332 if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV)
\r
2333 pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV));
\r
2335 if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapW != material.TextureLayer[st].TextureWrapW)
\r
2336 pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSW, getTextureWrapMode(material.TextureLayer[st].TextureWrapW));
\r
2339 // Bilinear, trilinear, and anisotropic filter
\r
2340 if (resetAllRenderstates ||
\r
2341 lastmaterial.TextureLayer[st].BilinearFilter != material.TextureLayer[st].BilinearFilter ||
\r
2342 lastmaterial.TextureLayer[st].TrilinearFilter != material.TextureLayer[st].TrilinearFilter ||
\r
2343 lastmaterial.TextureLayer[st].AnisotropicFilter != material.TextureLayer[st].AnisotropicFilter ||
\r
2344 lastmaterial.UseMipMaps != material.UseMipMaps)
\r
2346 if (material.TextureLayer[st].BilinearFilter || material.TextureLayer[st].TrilinearFilter || material.TextureLayer[st].AnisotropicFilter)
\r
2348 D3DTEXTUREFILTERTYPE tftMag = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) &&
\r
2349 material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR;
\r
2350 D3DTEXTUREFILTERTYPE tftMin = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) &&
\r
2351 material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR;
\r
2352 D3DTEXTUREFILTERTYPE tftMip = material.UseMipMaps? (material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT) : D3DTEXF_NONE;
\r
2354 if (tftMag==D3DTEXF_ANISOTROPIC || tftMin == D3DTEXF_ANISOTROPIC)
\r
2355 pID3DDevice->SetSamplerState(st, D3DSAMP_MAXANISOTROPY, core::min_((DWORD)material.TextureLayer[st].AnisotropicFilter, Caps.MaxAnisotropy));
\r
2356 pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, tftMag);
\r
2357 pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, tftMin);
\r
2358 pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, tftMip);
\r
2362 pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, D3DTEXF_POINT);
\r
2363 pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
\r
2364 pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
\r
2371 //! sets the needed renderstates
\r
2372 void CD3D9Driver::setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible)
\r
2374 if ((CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL &&
\r
2375 CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS) ||
\r
2376 Transformation3DChanged)
\r
2378 // unset last 3d material
\r
2379 if (CurrentRenderMode == ERM_3D &&
\r
2380 static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())
\r
2382 MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial();
\r
2383 ResetRenderStates = true;
\r
2385 // switch back the matrices
\r
2386 pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW]));
\r
2387 pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD]));
\r
2388 pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION]));
\r
2390 Transformation3DChanged = false;
\r
2392 setActiveTexture(0,0);
\r
2393 setActiveTexture(1,0);
\r
2394 setActiveTexture(2,0);
\r
2395 setActiveTexture(3,0);
\r
2397 pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
\r
2399 pID3DDevice->SetFVF(D3DFVF_XYZ);
\r
2400 LastVertexType = (video::E_VERTEX_TYPE)(-1);
\r
2402 pID3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
\r
2403 pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
\r
2404 pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
\r
2405 //pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
\r
2406 //pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
\r
2408 pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
\r
2409 pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x0);
\r
2410 pID3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
\r
2411 pID3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
\r
2413 BridgeCalls->setBlend(true);
\r
2414 BridgeCalls->setBlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE);
\r
2416 pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
\r
2417 pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
\r
2419 //if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY)))
\r
2420 // pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
\r
2421 if ((debugDataVisible & scene::EDS_MESH_WIRE_OVERLAY))
\r
2422 pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
\r
2425 if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS && !zfail)
\r
2427 // USE THE ZPASS METHOD
\r
2428 pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
\r
2429 pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
\r
2430 //pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR); // does not matter, will be set later
\r
2433 if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL && zfail)
\r
2435 // USE THE ZFAIL METHOD
\r
2436 pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
\r
2437 //pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR); // does not matter, will be set later
\r
2438 pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
\r
2441 CurrentRenderMode = zfail ? ERM_SHADOW_VOLUME_ZFAIL : ERM_SHADOW_VOLUME_ZPASS;
\r
2445 //! sets the needed renderstates
\r
2446 void CD3D9Driver::setRenderStatesStencilFillMode(bool alpha)
\r
2448 if (CurrentRenderMode != ERM_STENCIL_FILL || Transformation3DChanged)
\r
2450 core::matrix4 mat;
\r
2451 pID3DDevice->SetTransform(D3DTS_VIEW, &UnitMatrixD3D9);
\r
2452 pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9);
\r
2453 pID3DDevice->SetTransform(D3DTS_PROJECTION, &UnitMatrixD3D9);
\r
2455 pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
\r
2456 pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
\r
2457 pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
\r
2459 pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
\r
2461 pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x1);
\r
2462 pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL);
\r
2463 //pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATEREQUAL);
\r
2464 pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
\r
2465 pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
\r
2466 pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
\r
2467 pID3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
\r
2468 pID3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
\r
2470 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
\r
2472 Transformation3DChanged = false;
\r
2474 pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
\r
2475 pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
\r
2476 pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
\r
2477 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
\r
2478 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
\r
2481 BridgeCalls->setBlend(true);
\r
2482 BridgeCalls->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
\r
2486 BridgeCalls->setBlend(false);
\r
2490 CurrentRenderMode = ERM_STENCIL_FILL;
\r
2494 //! Enable the 2d override material
\r
2495 void CD3D9Driver::enableMaterial2D(bool enable)
\r
2498 CurrentRenderMode = ERM_NONE;
\r
2499 CNullDriver::enableMaterial2D(enable);
\r
2503 //! sets the needed renderstates
\r
2504 void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)
\r
2509 if (CurrentRenderMode != ERM_2D || Transformation3DChanged)
\r
2511 // unset last 3d material
\r
2512 if (CurrentRenderMode == ERM_3D)
\r
2514 if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())
\r
2515 MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
\r
2517 if (!OverrideMaterial2DEnabled)
\r
2519 setBasicRenderStates(InitMaterial2D, LastMaterial, true);
\r
2520 LastMaterial=InitMaterial2D;
\r
2522 // fix everything that is wrongly set by InitMaterial2D default
\r
2523 pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
\r
2525 pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
\r
2528 // this fixes some problems with pixel exact rendering, but also breaks nice texturing
\r
2529 // moreover, it would have to be tested in each call, as the texture flag can change each time
\r
2531 // m.setTranslation(core::vector3df(0.5f,0.5f,0));
\r
2532 pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)m.pointer()));
\r
2534 // adjust the view such that pixel center aligns with texels
\r
2535 // Otherwise, subpixel artifacts will occur
\r
2536 m.setTranslation(core::vector3df(-0.5f,-0.5f,0));
\r
2537 pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer()));
\r
2539 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
2540 m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0);
\r
2541 m.setTranslation(core::vector3df(-1,1,0));
\r
2542 pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer()));
\r
2544 // 2d elements are clipped in software
\r
2545 pID3DDevice->SetRenderState(D3DRS_CLIPPING, FALSE);
\r
2547 Transformation3DChanged = false;
\r
2549 if (OverrideMaterial2DEnabled)
\r
2551 OverrideMaterial2D.Lighting=false;
\r
2552 setBasicRenderStates(OverrideMaterial2D, LastMaterial, false);
\r
2553 LastMaterial = OverrideMaterial2D;
\r
2556 // no alphaChannel without texture
\r
2557 alphaChannel &= texture;
\r
2559 if (alpha || alphaChannel)
\r
2561 BridgeCalls->setBlend(true);
\r
2562 BridgeCalls->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
\r
2565 BridgeCalls->setBlend(false);
\r
2566 pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
\r
2567 pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
\r
2568 pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
\r
2571 setTransform(ETS_TEXTURE_0, core::IdentityMatrix);
\r
2572 // Due to the transformation change, the previous line would call a reset each frame
\r
2573 // but we can safely reset the variable as it was false before
\r
2574 Transformation3DChanged=false;
\r
2578 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
\r
2582 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
\r
2583 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
\r
2587 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
\r
2592 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
\r
2595 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
\r
2599 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
\r
2600 pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
\r
2604 CurrentRenderMode = ERM_2D;
\r
2608 //! deletes all dynamic lights there are
\r
2609 void CD3D9Driver::deleteAllDynamicLights()
\r
2611 for (s32 i=0; i<LastSetLight+1; ++i)
\r
2612 pID3DDevice->LightEnable(i, false);
\r
2614 LastSetLight = -1;
\r
2616 CNullDriver::deleteAllDynamicLights();
\r
2620 //! adds a dynamic light
\r
2621 s32 CD3D9Driver::addDynamicLight(const SLight& dl)
\r
2623 CNullDriver::addDynamicLight(dl);
\r
2630 light.Type = D3DLIGHT_POINT;
\r
2633 light.Type = D3DLIGHT_SPOT;
\r
2635 case ELT_DIRECTIONAL:
\r
2636 light.Type = D3DLIGHT_DIRECTIONAL;
\r
2640 light.Position = *(D3DVECTOR*)((void*)(&dl.Position));
\r
2641 light.Direction = *(D3DVECTOR*)((void*)(&dl.Direction));
\r
2643 light.Range = core::min_(dl.Radius, MaxLightDistance);
\r
2644 light.Falloff = dl.Falloff;
\r
2646 light.Diffuse = *(D3DCOLORVALUE*)((void*)(&dl.DiffuseColor));
\r
2647 light.Specular = *(D3DCOLORVALUE*)((void*)(&dl.SpecularColor));
\r
2648 light.Ambient = *(D3DCOLORVALUE*)((void*)(&dl.AmbientColor));
\r
2650 light.Attenuation0 = dl.Attenuation.X;
\r
2651 light.Attenuation1 = dl.Attenuation.Y;
\r
2652 light.Attenuation2 = dl.Attenuation.Z;
\r
2654 light.Theta = dl.InnerCone * 2.0f * core::DEGTORAD;
\r
2655 light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD;
\r
2659 if(D3D_OK == pID3DDevice->SetLight(LastSetLight, &light))
\r
2661 // I don't care if this succeeds
\r
2662 (void)pID3DDevice->LightEnable(LastSetLight, true);
\r
2663 return LastSetLight;
\r
2669 //! Turns a dynamic light on or off
\r
2670 //! \param lightIndex: the index returned by addDynamicLight
\r
2671 //! \param turnOn: true to turn the light on, false to turn it off
\r
2672 void CD3D9Driver::turnLightOn(s32 lightIndex, bool turnOn)
\r
2674 if(lightIndex < 0 || lightIndex > LastSetLight)
\r
2677 (void)pID3DDevice->LightEnable(lightIndex, turnOn);
\r
2681 //! returns the maximal amount of dynamic lights the device can handle
\r
2682 u32 CD3D9Driver::getMaximalDynamicLightAmount() const
\r
2684 return Caps.MaxActiveLights;
\r
2688 //! Sets the dynamic ambient light color. The default color is
\r
2689 //! (0,0,0,0) which means it is dark.
\r
2690 //! \param color: New color of the ambient light.
\r
2691 void CD3D9Driver::setAmbientLight(const SColorf& color)
\r
2693 CNullDriver::setAmbientLight(color);
\r
2698 D3DCOLOR col = color.toSColor().color;
\r
2699 pID3DDevice->SetRenderState(D3DRS_AMBIENT, col);
\r
2703 //! \return Returns the name of the video driver. Example: In case of the DIRECT3D9
\r
2704 //! driver, it would return "Direct3D9.0".
\r
2705 const wchar_t* CD3D9Driver::getName() const
\r
2707 return L"Direct3D 9.0";
\r
2711 //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
\r
2712 //! this: First, draw all geometry. Then use this method, to draw the shadow
\r
2713 //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow.
\r
2714 void CD3D9Driver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible)
\r
2716 if (!Params.Stencilbuffer)
\r
2719 setRenderStatesStencilShadowMode(zfail, debugDataVisible);
\r
2721 const u32 count = triangles.size();
\r
2729 // Draw front-side of shadow volume in stencil only
\r
2730 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
\r
2731 pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
\r
2732 pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df));
\r
2734 // Now reverse cull order so front sides of shadow volume are written.
\r
2735 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
\r
2736 pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR);
\r
2737 pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df));
\r
2743 // Draw front-side of shadow volume in stencil only
\r
2744 pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
\r
2745 pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR);
\r
2746 pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df));
\r
2748 // Now reverse cull order so front sides of shadow volume are written.
\r
2749 pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);
\r
2750 pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
\r
2751 pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df));
\r
2756 //! Fills the stencil shadow with color. After the shadow volume has been drawn
\r
2757 //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
\r
2758 //! to draw the color of the shadow.
\r
2759 void CD3D9Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge,
\r
2760 video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge)
\r
2762 if (!Params.Stencilbuffer)
\r
2766 vtx[0] = S3DVertex(1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftUpEdge, 0.0f, 0.0f);
\r
2767 vtx[1] = S3DVertex(1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightUpEdge, 0.0f, 1.0f);
\r
2768 vtx[2] = S3DVertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftDownEdge, 1.0f, 0.0f);
\r
2769 vtx[3] = S3DVertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightDownEdge, 1.0f, 1.0f);
\r
2771 s16 indices[6] = {0,1,2,1,3,2};
\r
2773 setRenderStatesStencilFillMode(
\r
2774 leftUpEdge.getAlpha() < 255 ||
\r
2775 rightUpEdge.getAlpha() < 255 ||
\r
2776 leftDownEdge.getAlpha() < 255 ||
\r
2777 rightDownEdge.getAlpha() < 255);
\r
2779 setActiveTexture(0,0);
\r
2781 setVertexShader(EVT_STANDARD);
\r
2783 pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
\r
2784 D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex));
\r
2786 if (clearStencilBuffer)
\r
2787 pID3DDevice->Clear( 0, NULL, D3DCLEAR_STENCIL,0, 1.0, 0);
\r
2791 //! Returns the maximum amount of primitives (mostly vertices) which
\r
2792 //! the device is able to render with one drawIndexedTriangleList
\r
2794 u32 CD3D9Driver::getMaximalPrimitiveCount() const
\r
2796 return Caps.MaxPrimitiveCount;
\r
2800 //! Sets the fog mode.
\r
2801 void CD3D9Driver::setFog(SColor color, E_FOG_TYPE fogType, f32 start,
\r
2802 f32 end, f32 density, bool pixelFog, bool rangeFog)
\r
2804 CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog);
\r
2809 pID3DDevice->SetRenderState(D3DRS_FOGCOLOR, color.color);
\r
2811 pID3DDevice->SetRenderState(
\r
2812 pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE,
\r
2813 (fogType==EFT_FOG_LINEAR)? D3DFOG_LINEAR : (fogType==EFT_FOG_EXP)?D3DFOG_EXP:D3DFOG_EXP2);
\r
2815 if (fogType==EFT_FOG_LINEAR)
\r
2817 pID3DDevice->SetRenderState(D3DRS_FOGSTART, F2DW(start));
\r
2818 pID3DDevice->SetRenderState(D3DRS_FOGEND, F2DW(end));
\r
2821 pID3DDevice->SetRenderState(D3DRS_FOGDENSITY, F2DW(density));
\r
2824 pID3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, rangeFog);
\r
2828 //! Draws a 3d line.
\r
2829 void CD3D9Driver::draw3DLine(const core::vector3df& start,
\r
2830 const core::vector3df& end, SColor color)
\r
2832 setVertexShader(EVT_STANDARD);
\r
2833 setRenderStates3DMode();
\r
2834 video::S3DVertex v[2];
\r
2835 v[0].Color = color;
\r
2836 v[1].Color = color;
\r
2840 pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, v, sizeof(S3DVertex));
\r
2843 void CD3D9Driver::draw3DBox( const core::aabbox3d<f32>& box, SColor color)
\r
2845 core::vector3df edges[8];
\r
2846 box.getEdges(edges);
\r
2848 setVertexShader(EVT_STANDARD);
\r
2849 setRenderStates3DMode();
\r
2851 video::S3DVertex v[24];
\r
2853 for(u32 i = 0; i < 24; i++)
\r
2854 v[i].Color = color;
\r
2856 v[0].Pos = edges[5];
\r
2857 v[1].Pos = edges[1];
\r
2858 v[2].Pos = edges[1];
\r
2859 v[3].Pos = edges[3];
\r
2860 v[4].Pos = edges[3];
\r
2861 v[5].Pos = edges[7];
\r
2862 v[6].Pos = edges[7];
\r
2863 v[7].Pos = edges[5];
\r
2864 v[8].Pos = edges[0];
\r
2865 v[9].Pos = edges[2];
\r
2866 v[10].Pos = edges[2];
\r
2867 v[11].Pos = edges[6];
\r
2868 v[12].Pos = edges[6];
\r
2869 v[13].Pos = edges[4];
\r
2870 v[14].Pos = edges[4];
\r
2871 v[15].Pos = edges[0];
\r
2872 v[16].Pos = edges[1];
\r
2873 v[17].Pos = edges[0];
\r
2874 v[18].Pos = edges[3];
\r
2875 v[19].Pos = edges[2];
\r
2876 v[20].Pos = edges[7];
\r
2877 v[21].Pos = edges[6];
\r
2878 v[22].Pos = edges[5];
\r
2879 v[23].Pos = edges[4];
\r
2881 pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 12, v, sizeof(S3DVertex));
\r
2884 bool CD3D9Driver::retrieveDevice(int numTries, int msSleepBetweenTries)
\r
2886 while ( numTries > 0)
\r
2889 if ( FAILED(hr = pID3DDevice->TestCooperativeLevel()) )
\r
2891 // hr can be: D3DERR_DEVICELOST, D3DERR_DEVICENOTRESET or D3DERR_DRIVERINTERNALERROR
\r
2894 case D3DERR_DEVICENOTRESET:
\r
2897 // when reset fails, just try again, maybe device got lost in between TestCooperativeLevel and reset calls?
\r
2899 case D3DERR_DEVICELOST:
\r
2901 case D3DERR_DRIVERINTERNALERROR:
\r
2905 Sleep(msSleepBetweenTries);
\r
2914 //! resets the device
\r
2915 bool CD3D9Driver::reset()
\r
2917 os::Printer::log("Resetting D3D9 device.", ELL_INFORMATION);
\r
2919 for (u32 i = 0; i<RenderTargets.size(); ++i)
\r
2921 if (RenderTargets[i]->getDriverType() == EDT_DIRECT3D9)
\r
2923 static_cast<CD3D9RenderTarget*>(RenderTargets[i])->releaseSurfaces();
\r
2925 const core::array<ITexture*> texArray = RenderTargets[i]->getTexture();
\r
2927 for (u32 j = 0; j < texArray.size(); ++j)
\r
2929 CD3D9Texture* tex = static_cast<CD3D9Texture*>(texArray[j]);
\r
2932 tex->releaseTexture();
\r
2935 CD3D9Texture* tex = static_cast<CD3D9Texture*>(RenderTargets[i]->getDepthStencil());
\r
2938 tex->releaseTexture();
\r
2941 for (u32 i=0; i<Textures.size(); ++i)
\r
2943 if (Textures[i].Surface->isRenderTarget())
\r
2945 CD3D9Texture* tex = static_cast<CD3D9Texture*>(Textures[i].Surface);
\r
2948 tex->releaseTexture();
\r
2951 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
2953 if (OcclusionQueries[i].PID)
\r
2955 reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[i].PID)->Release();
\r
2956 OcclusionQueries[i].PID=0;
\r
2959 // this does not require a restore in the reset method, it's updated
\r
2960 // automatically in the next render cycle.
\r
2961 removeAllHardwareBuffers();
\r
2963 // reset render target usage information.
\r
2964 for (u32 i = 0; i < ActiveRenderTarget.size(); ++i)
\r
2965 ActiveRenderTarget[i] = false;
\r
2967 if (DepthStencilSurface)
\r
2969 DepthStencilSurface->Release();
\r
2970 DepthStencilSurface = 0;
\r
2973 if (BackBufferSurface)
\r
2975 BackBufferSurface->Release();
\r
2976 BackBufferSurface = 0;
\r
2979 DriverWasReset=true;
\r
2981 HRESULT hr = pID3DDevice->Reset(&present);
\r
2984 if (hr == D3DERR_DEVICELOST)
\r
2986 DeviceLost = true;
\r
2987 os::Printer::log("Resetting failed due to device lost.", ELL_WARNING);
\r
2989 #ifdef D3DERR_DEVICEREMOVED
\r
2990 else if (hr == D3DERR_DEVICEREMOVED)
\r
2992 os::Printer::log("Resetting failed due to device removed.", ELL_WARNING);
\r
2995 else if (hr == D3DERR_DRIVERINTERNALERROR)
\r
2997 os::Printer::log("Resetting failed due to internal error.", ELL_WARNING);
\r
2999 else if (hr == D3DERR_OUTOFVIDEOMEMORY)
\r
3001 os::Printer::log("Resetting failed due to out of memory.", ELL_WARNING);
\r
3003 else if (hr == D3DERR_DEVICENOTRESET)
\r
3005 os::Printer::log("Resetting failed due to not reset.", ELL_WARNING);
\r
3007 else if (hr == D3DERR_INVALIDCALL)
\r
3009 os::Printer::log("Resetting failed due to invalid call", "You need to release some more surfaces.", ELL_WARNING);
\r
3013 os::Printer::log("Resetting failed due to unknown reason.", core::stringc((int)hr).c_str(), ELL_WARNING);
\r
3017 DeviceLost = false;
\r
3019 // reset bridge calls.
\r
3021 BridgeCalls->reset();
\r
3023 // restore screen depthbuffer descriptor
\r
3024 if (!SUCCEEDED(pID3DDevice->GetDepthStencilSurface(&DepthStencilSurface)))
\r
3026 os::Printer::log("Was not able to get main depth buffer.", ELL_ERROR);
\r
3031 for (u32 i=0; i<Textures.size(); ++i)
\r
3033 if (Textures[i].Surface->isRenderTarget())
\r
3034 ((CD3D9Texture*)(Textures[i].Surface))->generateRenderTarget();
\r
3036 for (u32 i = 0; i<RenderTargets.size(); ++i)
\r
3038 if (RenderTargets[i]->getDriverType() == EDT_DIRECT3D9)
\r
3040 const core::array<ITexture*> texArray = RenderTargets[i]->getTexture();
\r
3042 for (u32 j = 0; j < texArray.size(); ++j)
\r
3044 CD3D9Texture* tex = static_cast<CD3D9Texture*>(texArray[j]);
\r
3047 tex->generateRenderTarget();
\r
3050 CD3D9Texture* tex = static_cast<CD3D9Texture*>(RenderTargets[i]->getDepthStencil());
\r
3053 tex->generateRenderTarget();
\r
3055 static_cast<CD3D9RenderTarget*>(RenderTargets[i])->generateSurfaces();
\r
3059 // restore occlusion queries
\r
3060 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
3062 pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, reinterpret_cast<IDirect3DQuery9**>(&OcclusionQueries[i].PID));
\r
3065 ResetRenderStates = true;
\r
3066 LastVertexType = (E_VERTEX_TYPE)-1;
\r
3068 for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
\r
3069 CurrentTexture[i] = 0;
\r
3071 setVertexShader(EVT_STANDARD);
\r
3072 setRenderStates3DMode();
\r
3073 setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
\r
3074 setAmbientLight(getAmbientLight());
\r
3080 void CD3D9Driver::OnResize(const core::dimension2d<u32>& size)
\r
3085 CNullDriver::OnResize(size);
\r
3086 present.BackBufferWidth = size.Width;
\r
3087 present.BackBufferHeight = size.Height;
\r
3091 if ( !retrieveDevice(20, 200) ) // retrying for 3 seconds, I hope that's long enough?
\r
3093 os::Printer::log("Failed to retrieve device in OnResize.", ELL_ERROR);
\r
3099 //! Returns type of video driver
\r
3100 E_DRIVER_TYPE CD3D9Driver::getDriverType() const
\r
3102 return EDT_DIRECT3D9;
\r
3106 //! Returns the transformation set by setTransform
\r
3107 const core::matrix4& CD3D9Driver::getTransform(E_TRANSFORMATION_STATE state) const
\r
3109 return Matrices[state];
\r
3113 //! Get a vertex shader constant index.
\r
3114 s32 CD3D9Driver::getVertexShaderConstantID(const c8* name)
\r
3116 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3118 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3119 return r->getVariableID(true, name);
\r
3125 //! Get a pixel shader constant index.
\r
3126 s32 CD3D9Driver::getPixelShaderConstantID(const c8* name)
\r
3128 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3130 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3131 return r->getVariableID(false, name);
\r
3138 //! Sets a vertex shader constant.
\r
3139 void CD3D9Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
\r
3142 pID3DDevice->SetVertexShaderConstantF(startRegister, data, constantAmount);
\r
3146 //! Sets a pixel shader constant.
\r
3147 void CD3D9Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
\r
3150 pID3DDevice->SetPixelShaderConstantF(startRegister, data, constantAmount);
\r
3154 //! Sets a constant for the vertex shader based on an index.
\r
3155 bool CD3D9Driver::setVertexShaderConstant(s32 index, const f32* floats, int count)
\r
3157 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3159 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3160 return r->setVariable(true, index, floats, count);
\r
3167 //! Int interface for the above.
\r
3168 bool CD3D9Driver::setVertexShaderConstant(s32 index, const s32* ints, int count)
\r
3170 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3172 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3173 return r->setVariable(true, index, ints, count);
\r
3180 //! Uint interface for the above.
\r
3181 bool CD3D9Driver::setVertexShaderConstant(s32 index, const u32* ints, int count)
\r
3183 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3185 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3186 return r->setVariable(true, index, ints, count);
\r
3193 //! Sets a constant for the pixel shader based on an index.
\r
3194 bool CD3D9Driver::setPixelShaderConstant(s32 index, const f32* floats, int count)
\r
3196 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3198 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3199 return r->setVariable(false, index, floats, count);
\r
3206 //! Int interface for the above.
\r
3207 bool CD3D9Driver::setPixelShaderConstant(s32 index, const s32* ints, int count)
\r
3209 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3211 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3212 return r->setVariable(false, index, ints, count);
\r
3219 //! Uint interface for the above.
\r
3220 bool CD3D9Driver::setPixelShaderConstant(s32 index, const u32* ints, int count)
\r
3222 if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size())
\r
3224 CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer;
\r
3225 return r->setVariable(false, index, ints, count);
\r
3233 //! Adds a new material renderer to the VideoDriver, using pixel and/or
\r
3234 //! vertex shaders to render geometry.
\r
3235 s32 CD3D9Driver::addShaderMaterial(const c8* vertexShaderProgram,
\r
3236 const c8* pixelShaderProgram,
\r
3237 IShaderConstantSetCallBack* callback,
\r
3238 E_MATERIAL_TYPE baseMaterial, s32 userData)
\r
3241 CD3D9ShaderMaterialRenderer* r = new CD3D9ShaderMaterialRenderer(
\r
3242 pID3DDevice, this, nr, vertexShaderProgram, pixelShaderProgram,
\r
3243 callback, getMaterialRenderer(baseMaterial), userData);
\r
3250 //! Adds a new material renderer to the VideoDriver, based on a high level shading
\r
3252 s32 CD3D9Driver::addHighLevelShaderMaterial(
\r
3253 const c8* vertexShaderProgram,
\r
3254 const c8* vertexShaderEntryPointName,
\r
3255 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
3256 const c8* pixelShaderProgram,
\r
3257 const c8* pixelShaderEntryPointName,
\r
3258 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
3259 const c8* geometryShaderProgram,
\r
3260 const c8* geometryShaderEntryPointName,
\r
3261 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
3262 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
3264 IShaderConstantSetCallBack* callback,
\r
3265 E_MATERIAL_TYPE baseMaterial, s32 userData)
\r
3269 CD3D9HLSLMaterialRenderer* r = new CD3D9HLSLMaterialRenderer(
\r
3270 pID3DDevice, this, nr,
\r
3271 vertexShaderProgram,
\r
3272 vertexShaderEntryPointName,
\r
3274 pixelShaderProgram,
\r
3275 pixelShaderEntryPointName,
\r
3278 getMaterialRenderer(baseMaterial),
\r
3287 //! Returns a pointer to the IVideoDriver interface. (Implementation for
\r
3288 //! IMaterialRendererServices)
\r
3289 IVideoDriver* CD3D9Driver::getVideoDriver()
\r
3295 //! Creates a render target texture.
\r
3296 ITexture* CD3D9Driver::addRenderTargetTexture(const core::dimension2d<u32>& size,
\r
3297 const io::path& name,
\r
3298 const ECOLOR_FORMAT format)
\r
3300 if ( IImage::isCompressedFormat(format) )
\r
3303 CD3D9Texture* tex = new CD3D9Texture(this, size, name, ETT_2D, format);
\r
3306 if (!tex->Texture)
\r
3318 ITexture* CD3D9Driver::addRenderTargetTextureCubemap(const irr::u32 sideLen,
\r
3319 const io::path& name, const ECOLOR_FORMAT format)
\r
3321 if ( IImage::isCompressedFormat(format) )
\r
3324 CD3D9Texture* tex = new CD3D9Texture(this, core::dimension2d<u32>(sideLen, sideLen), name, ETT_CUBEMAP, format);
\r
3327 if (!tex->CubeTexture)
\r
3339 void CD3D9Driver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
\r
3341 DWORD internalFlag = 0;
\r
3343 if (flag & ECBF_COLOR)
\r
3344 internalFlag |= D3DCLEAR_TARGET;
\r
3346 if (flag & ECBF_DEPTH)
\r
3347 internalFlag |= D3DCLEAR_ZBUFFER;
\r
3349 if (flag & ECBF_STENCIL)
\r
3350 internalFlag |= D3DCLEAR_STENCIL;
\r
3354 HRESULT hr = pID3DDevice->Clear(0, NULL, internalFlag, color.color, depth, stencil);
\r
3357 os::Printer::log("DIRECT3D9 clear failed.", ELL_WARNING);
\r
3362 //! Returns an image created from the last rendered frame.
\r
3363 IImage* CD3D9Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
\r
3365 if (target != video::ERT_FRAME_BUFFER)
\r
3368 if (format==video::ECF_UNKNOWN)
\r
3369 format=getColorFormat();
\r
3371 // TODO: Maybe we could support more formats (floating point and some of those beyond ECF_R8), didn't really try yet
\r
3372 if (IImage::isCompressedFormat(format) || IImage::isDepthFormat(format) || IImage::isFloatingPointFormat(format) || format >= ECF_R8)
\r
3375 // query the screen dimensions of the current adapter
\r
3376 D3DDISPLAYMODE displayMode;
\r
3377 pID3DDevice->GetDisplayMode(0, &displayMode);
\r
3379 // create the image surface to store the front buffer image [always A8R8G8B8]
\r
3381 LPDIRECT3DSURFACE9 lpSurface;
\r
3382 if (FAILED(hr = pID3DDevice->CreateOffscreenPlainSurface(displayMode.Width, displayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &lpSurface, 0)))
\r
3385 // read the front buffer into the image surface
\r
3386 if (FAILED(hr = pID3DDevice->GetFrontBufferData(0, lpSurface)))
\r
3388 lpSurface->Release();
\r
3394 POINT clientPoint;
\r
3395 clientPoint.x = 0;
\r
3396 clientPoint.y = 0;
\r
3398 ClientToScreen((HWND)getExposedVideoData().D3D9.HWnd, &clientPoint);
\r
3400 clientRect.left = clientPoint.x;
\r
3401 clientRect.top = clientPoint.y;
\r
3402 clientRect.right = clientRect.left + ScreenSize.Width;
\r
3403 clientRect.bottom = clientRect.top + ScreenSize.Height;
\r
3405 // window can be off-screen partly, we can't take screenshots from that
\r
3406 clientRect.left = core::max_(clientRect.left, 0l);
\r
3407 clientRect.top = core::max_(clientRect.top, 0l);
\r
3408 clientRect.right = core::min_(clientRect.right, (long)displayMode.Width);
\r
3409 clientRect.bottom = core::min_(clientRect.bottom, (long)displayMode.Height );
\r
3412 // lock our area of the surface
\r
3413 D3DLOCKED_RECT lockedRect;
\r
3414 if (FAILED(lpSurface->LockRect(&lockedRect, &clientRect, D3DLOCK_READONLY)))
\r
3416 lpSurface->Release();
\r
3420 irr::core::dimension2d<u32> shotSize;
\r
3421 shotSize.Width = core::min_( ScreenSize.Width, (u32)(clientRect.right-clientRect.left) );
\r
3422 shotSize.Height = core::min_( ScreenSize.Height, (u32)(clientRect.bottom-clientRect.top) );
\r
3424 // this could throw, but we aren't going to worry about that case very much
\r
3425 IImage* newImage = createImage(format, shotSize);
\r
3429 // d3d pads the image, so we need to copy the correct number of bytes
\r
3430 u32* dP = (u32*)newImage->lock();
\r
3431 u8 * sP = (u8 *)lockedRect.pBits;
\r
3433 // If the display mode format doesn't promise anything about the Alpha value
\r
3434 // and it appears that it's not presenting 255, then we should manually
\r
3435 // set each pixel alpha value to 255.
\r
3436 if (D3DFMT_X8R8G8B8 == displayMode.Format && (0xFF000000 != (*dP & 0xFF000000)))
\r
3438 for (u32 y = 0; y < shotSize.Height; ++y)
\r
3440 for (u32 x = 0; x < shotSize.Width; ++x)
\r
3442 newImage->setPixel(x,y,*((u32*)sP) | 0xFF000000);
\r
3446 sP += lockedRect.Pitch - (4 * shotSize.Width);
\r
3451 for (u32 y = 0; y < shotSize.Height; ++y)
\r
3453 convertColor(sP, video::ECF_A8R8G8B8, shotSize.Width, dP, format);
\r
3454 sP += lockedRect.Pitch;
\r
3455 dP += shotSize.Width;
\r
3459 newImage->unlock();
\r
3462 // we can unlock and release the surface
\r
3463 lpSurface->UnlockRect();
\r
3465 // release the image surface
\r
3466 lpSurface->Release();
\r
3468 // return status of save operation to caller
\r
3473 //! returns color format
\r
3474 ECOLOR_FORMAT CD3D9Driver::getColorFormat() const
\r
3476 return ColorFormat;
\r
3480 //! returns color format
\r
3481 D3DFORMAT CD3D9Driver::getD3DColorFormat() const
\r
3483 return D3DColorFormat;
\r
3487 // Set/unset a clipping plane.
\r
3488 bool CD3D9Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
\r
3490 if (index >= MaxUserClipPlanes)
\r
3493 HRESULT ok = pID3DDevice->SetClipPlane(index, (const float*)&(plane.Normal.X));
\r
3495 enableClipPlane(index, enable);
\r
3500 // Enable/disable a clipping plane.
\r
3501 void CD3D9Driver::enableClipPlane(u32 index, bool enable)
\r
3503 if (index >= MaxUserClipPlanes)
\r
3505 DWORD renderstate;
\r
3506 HRESULT ok = pID3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &renderstate);
\r
3510 renderstate |= (1 << index);
\r
3512 renderstate &= ~(1 << index);
\r
3513 ok = pID3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, renderstate);
\r
3518 D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const
\r
3522 case ECF_A1R5G5B5:
\r
3523 return D3DFMT_A1R5G5B5;
\r
3525 return D3DFMT_R5G6B5;
\r
3527 return D3DFMT_R8G8B8;
\r
3528 case ECF_A8R8G8B8:
\r
3529 return D3DFMT_A8R8G8B8;
\r
3532 return D3DFMT_DXT1;
\r
3534 return D3DFMT_DXT2;
\r
3536 return D3DFMT_DXT3;
\r
3538 return D3DFMT_DXT4;
\r
3540 return D3DFMT_DXT5;
\r
3542 return D3DFMT_R16F;
\r
3544 return D3DFMT_G16R16F;
\r
3545 case ECF_A16B16G16R16F:
\r
3546 return D3DFMT_A16B16G16R16F;
\r
3548 return D3DFMT_R32F;
\r
3550 return D3DFMT_G32R32F;
\r
3551 case ECF_A32B32G32R32F:
\r
3552 return D3DFMT_A32B32G32R32F;
\r
3555 return D3DFMT_A8; // not correct, but somewhat similar
\r
3557 return D3DFMT_A8L8; // not correct, but somewhat similar
\r
3559 return D3DFMT_L16; // not correct, but somewhat similar
\r
3561 return D3DFMT_G16R16; // flipped :-(
\r
3564 return D3DFMT_D16;
\r
3566 return D3DFMT_D24S8;
\r
3568 return D3DFMT_D32;
\r
3570 return D3DFMT_UNKNOWN;
\r
3574 ECOLOR_FORMAT CD3D9Driver::getColorFormatFromD3DFormat(D3DFORMAT format) const
\r
3578 case D3DFMT_X1R5G5B5:
\r
3579 case D3DFMT_A1R5G5B5:
\r
3580 return ECF_A1R5G5B5;
\r
3581 case D3DFMT_A8B8G8R8:
\r
3582 case D3DFMT_A8R8G8B8:
\r
3583 case D3DFMT_X8R8G8B8:
\r
3584 return ECF_A8R8G8B8;
\r
3585 case D3DFMT_R5G6B5:
\r
3586 return ECF_R5G6B5;
\r
3587 case D3DFMT_R8G8B8:
\r
3588 return ECF_R8G8B8;
\r
3590 // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski.
\r
3593 case D3DFMT_G16R16F:
\r
3594 return ECF_G16R16F;
\r
3595 case D3DFMT_A16B16G16R16F:
\r
3596 return ECF_A16B16G16R16F;
\r
3599 case D3DFMT_G32R32F:
\r
3600 return ECF_G32R32F;
\r
3601 case D3DFMT_A32B32G32R32F:
\r
3602 return ECF_A32B32G32R32F;
\r
3604 return (ECOLOR_FORMAT)0;
\r
3609 core::dimension2du CD3D9Driver::getMaxTextureSize() const
\r
3611 return core::dimension2du(Caps.MaxTextureWidth, Caps.MaxTextureHeight);
\r
3614 bool CD3D9Driver::queryTextureFormat(ECOLOR_FORMAT format) const
\r
3616 return getD3DFormatFromColorFormat(format) != D3DFMT_UNKNOWN;
\r
3619 bool CD3D9Driver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
\r
3621 return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation();
\r
3624 u32 CD3D9Driver::getD3DBlend(E_BLEND_FACTOR factor) const
\r
3629 case EBF_ZERO: r = D3DBLEND_ZERO; break;
\r
3630 case EBF_ONE: r = D3DBLEND_ONE; break;
\r
3631 case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
\r
3632 case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
\r
3633 case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
\r
3634 case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
\r
3635 case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
\r
3636 case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
\r
3637 case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
\r
3638 case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
\r
3639 case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
\r
3645 u32 CD3D9Driver::getD3DModulate(E_MODULATE_FUNC func) const
\r
3647 u32 r = D3DTOP_MODULATE;
\r
3650 case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
\r
3651 case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
\r
3652 case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
\r
3658 CD3D9CallBridge* CD3D9Driver::getBridgeCalls() const
\r
3660 return BridgeCalls;
\r
3663 CD3D9CallBridge::CD3D9CallBridge(IDirect3DDevice9* p, CD3D9Driver* driver) : pID3DDevice(p),
\r
3664 BlendOperation(D3DBLENDOP_ADD), BlendSourceRGB(D3DBLEND_ONE), BlendDestinationRGB(D3DBLEND_ZERO),
\r
3665 BlendSourceAlpha(D3DBLEND_ONE), BlendDestinationAlpha(D3DBLEND_ZERO), Blend(false), BlendSeparate(false),
\r
3666 FeatureBlendSeparate(false)
\r
3668 FeatureBlendSeparate = driver->queryFeature(EVDF_BLEND_SEPARATE);
\r
3673 void CD3D9CallBridge::reset()
\r
3675 BlendOperation = D3DBLENDOP_ADD;
\r
3677 BlendSourceRGB = D3DBLEND_ONE;
\r
3678 BlendDestinationRGB = D3DBLEND_ZERO;
\r
3679 BlendSourceAlpha = D3DBLEND_ONE;
\r
3680 BlendDestinationAlpha = D3DBLEND_ZERO;
\r
3683 BlendSeparate = false;
\r
3685 pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
\r
3686 pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
\r
3687 pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
\r
3688 pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
\r
3690 if (FeatureBlendSeparate)
\r
3692 pID3DDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
\r
3693 pID3DDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
\r
3694 pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
\r
3698 void CD3D9CallBridge::setBlendOperation(DWORD mode)
\r
3700 if (BlendOperation != mode)
\r
3702 pID3DDevice->SetRenderState(D3DRS_BLENDOP, mode);
\r
3704 BlendOperation = mode;
\r
3708 void CD3D9CallBridge::setBlendFunc(DWORD source, DWORD destination)
\r
3710 if (BlendSourceRGB != source)
\r
3712 pID3DDevice->SetRenderState(D3DRS_SRCBLEND, source);
\r
3714 BlendSourceRGB = source;
\r
3717 if (BlendDestinationRGB != destination)
\r
3719 pID3DDevice->SetRenderState(D3DRS_DESTBLEND, destination);
\r
3721 BlendDestinationRGB = destination;
\r
3724 if (FeatureBlendSeparate && BlendSeparate)
\r
3726 pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
\r
3728 BlendSeparate = false;
\r
3732 void CD3D9CallBridge::setBlendFuncSeparate(DWORD sourceRGB, DWORD destinationRGB, DWORD sourceAlpha, DWORD destinationAlpha)
\r
3734 if (BlendSourceRGB != sourceRGB)
\r
3736 pID3DDevice->SetRenderState(D3DRS_SRCBLEND, sourceRGB);
\r
3738 BlendSourceRGB = sourceRGB;
\r
3741 if (BlendDestinationRGB != destinationRGB)
\r
3743 pID3DDevice->SetRenderState(D3DRS_DESTBLEND, destinationRGB);
\r
3745 BlendDestinationRGB = destinationRGB;
\r
3748 if (FeatureBlendSeparate)
\r
3750 if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha)
\r
3752 if (BlendSourceAlpha != sourceAlpha)
\r
3754 pID3DDevice->SetRenderState(D3DRS_SRCBLENDALPHA, sourceAlpha);
\r
3756 BlendSourceAlpha = sourceAlpha;
\r
3759 if (BlendDestinationAlpha != destinationAlpha)
\r
3761 pID3DDevice->SetRenderState(D3DRS_DESTBLENDALPHA, destinationAlpha);
\r
3763 BlendDestinationAlpha = destinationAlpha;
\r
3766 if (!BlendSeparate)
\r
3768 pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
\r
3770 BlendSeparate = true;
\r
3773 else if (BlendSeparate)
\r
3775 pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
\r
3777 BlendSeparate = false;
\r
3782 void CD3D9CallBridge::setBlend(bool enable)
\r
3784 if (Blend != enable)
\r
3787 pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
\r
3789 pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
\r
3795 } // end namespace video
\r
3796 } // end namespace irr
\r
3798 #endif // _IRR_COMPILE_WITH_DIRECT3D_9_
\r
3807 #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
\r
3808 //! creates a video driver
\r
3809 IVideoDriver* createDirectX9Driver(const SIrrlichtCreationParameters& params,
\r
3810 io::IFileSystem* io, HWND window)
\r
3812 const bool pureSoftware = false;
\r
3813 CD3D9Driver* dx9 = new CD3D9Driver(params, io);
\r
3814 if (!dx9->initDriver(window, pureSoftware))
\r
3822 #endif // _IRR_COMPILE_WITH_DIRECT3D_9_
\r
3824 } // end namespace video
\r
3825 } // end namespace irr
\r