00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "KeosD3D9RenderSystem.h"
00022 #include "KeosD3D9Window.h"
00023 #include "KeosD3D9Enum.h"
00024 #include "KeosD3D9Exception.h"
00025 #include "KeosD3D9Buffer.h"
00026 #include "KeosD3D9Declaration.h"
00027 #include "KeosD3D9Texture.h"
00028 #include "KeosLogger.h"
00029 #include "KeosMatrix4.h"
00030 #include "KeosColor.h"
00031 #include "KeosRenderSystemCapabilities.h"
00032 #include "KeosPixelUtils.h"
00033 #include "KeosString.h"
00034 #include "KeosD3D9Shader.h"
00035 #include "KeosLight.h"
00036 #include "Cg/cgD3D9.h"
00037
00038 namespace Keos
00039 {
00040
00041
00042
00043
00044
00045 CD3D9RenderSystem::CD3D9RenderSystem()
00046 {
00047 m_pD3D9 = new CD3D9();
00048
00049 m_nMinVertex = 0;
00050 m_nVertexCount = 0;
00051 m_bDeviceLost = false;
00052
00053
00054 if ( NULL == (m_pD3D9->pD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
00055 D3D9_EXCEPT("Failed to create Direct3D9 object", "CD3D9RenderSystem::CD3D9RenderSystem");
00056
00057
00058 for (int i = 0; i < 6; ++i)
00059 m_Matrices[i].push_back(CMatrix4());
00060
00061 }
00062
00063
00064 CD3D9RenderSystem::~CD3D9RenderSystem()
00065 {
00066 Shutdown();
00067 cgD3D9SetDevice(NULL);
00068 delete m_pD3D9;
00069 }
00070
00071
00072 const String& CD3D9RenderSystem::GetName(void) const
00073 {
00074 static String strName("Direct3D9");
00075 return strName;
00076 }
00077
00078
00079 IRenderWindow* CD3D9RenderSystem::Initialise(bool bAutoCreateWindow, const String& strWindowTitle)
00080 {
00081 ILogger::Log("--> Starting Direct3D9 Subsystem");
00082
00083 ConfigOptionMap::iterator opt = m_Options.find("Video Mode");
00084 if (opt == m_Options.end())
00085 D3D9_EXCEPT("Can't find \"Video Mode\" option", "CD3D9RenderSystem::Initialise");
00086 String val = opt->second.currentValue;
00087 String::size_type pos = val.find('x');
00088 if (pos == String::npos)
00089 D3D9_EXCEPT("Invalid Video Mode provided", "COGLRenderSystem::Initialise");
00090 uint w = CStringConverter::ParseUnsignedInt(val.substr(0, pos));
00091 uint h = CStringConverter::ParseUnsignedInt(val.substr(pos + 1));
00092
00093 opt = m_Options.find("Color Depth");
00094 if (opt == m_Options.end())
00095 D3D9_EXCEPT("Can't find \"Color Depth\" option", "CD3D9RenderSystem::Initialise");
00096 val = opt->second.currentValue;
00097 uint d = CStringConverter::ParseUnsignedInt(val);
00098 if (d == 0)
00099 D3D9_EXCEPT("Invalid Color Depth provided", "CD3D9RenderSystem::Initialise");
00100
00101 opt = m_Options.find("Fullscreen");
00102 if (opt == m_Options.end())
00103 D3D9_EXCEPT("Can't find \"Fullscreen\" option", "CD3D9RenderSystem::Initialise");
00104 val = opt->second.currentValue;
00105 bool f = CStringConverter::ParseBool(val);
00106
00107 IRenderWindow* pAutoWindow = CreateRenderWindow(strWindowTitle, w, h, d, f);
00108
00109 return pAutoWindow;
00110 }
00111
00112
00113 void CD3D9RenderSystem::Reinitialise(void)
00114 {
00115 this->Shutdown();
00116 this->Initialise( true );
00117 }
00118
00119
00120 void CD3D9RenderSystem::Shutdown(void)
00121 {
00122 IRenderSystem::Shutdown();
00123 m_pD3D9->ReleaseDevice();
00124 }
00125
00126
00127 IRenderWindow* CD3D9RenderSystem::CreateRenderWindow(const String &strName, uint nWidth, uint nHeight, uint nColourDepth, bool bFullScreen)
00128 {
00129 ILogger::Log("--> Create Win32 render window");
00130
00131
00132 IRenderWindow* win = new CD3D9Window(m_pD3D9);
00133 win->Create(strName, nWidth, nHeight, nColourDepth, bFullScreen);
00134
00135 AttachRenderTarget( *win );
00136
00137 InitCapabilities();
00138
00139
00140 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, true);
00141 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_LIGHTING, false);
00142 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_ZENABLE, true);
00143 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_FOGENABLE, false);
00144 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false);
00145 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
00146 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
00147 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xFF);
00148 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xFF);
00149 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
00150 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
00151 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
00152 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
00153 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
00154
00155 SetClearColor(CColor::Black);
00156
00157 return win;
00158 }
00159
00160
00161 void CD3D9RenderSystem::InitCapabilities()
00162 {
00163
00164 D3DCAPS9 Caps;
00165 m_pD3D9->pD3DDevice->GetDeviceCaps(&Caps);
00166
00167
00168 if ((Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0)
00169 m_pCapabilities->SetCapability(CAP_HW_MIPMAPPING);
00170
00171
00172 if (CheckFormat(D3DFMT_DXT1, D3DRTYPE_TEXTURE) &&
00173 CheckFormat(D3DFMT_DXT3, D3DRTYPE_TEXTURE) &&
00174 CheckFormat(D3DFMT_DXT5, D3DRTYPE_TEXTURE))
00175 m_pCapabilities->SetCapability(CAP_TEXTURE_COMPRESSION_DXT);
00176
00177
00178 if (!(Caps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
00179 !(Caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
00180 m_pCapabilities->SetCapability(CAP_NON_POWER_OF_2_TEXTURES);
00181
00182
00183 m_pCapabilities->SetNumTextureUnits(Caps.MaxSimultaneousTextures);
00184
00185
00186 SearchVertexShaderCaps(Caps);
00187
00188 SearchPixelShaderCaps(Caps);
00189
00190 m_pCapabilities->Log();
00191
00192
00193 cgD3D9SetDevice(m_pD3D9->pD3DDevice);
00194 if (m_pCapabilities->HasCapability(CAP_VERTEX_PROGRAM))
00195 {
00196 m_VSProfile = cgD3D9GetLatestVertexProfile();
00197 m_VSOptions[0] = cgD3D9GetOptimalOptions(m_VSProfile);
00198 m_VSOptions[1] = NULL;
00199 }
00200 if (m_pCapabilities->HasCapability(CAP_FRAGMENT_PROGRAM))
00201 {
00202 m_PSProfile = cgD3D9GetLatestPixelProfile();
00203 m_PSOptions[0] = cgD3D9GetOptimalOptions(m_PSProfile);
00204 m_PSOptions[1] = NULL;
00205 }
00206 }
00207
00208
00209 void CD3D9RenderSystem::SearchVertexShaderCaps(D3DCAPS9& Caps)
00210 {
00211 ushort nMajor, nMinor;
00212 nMajor = static_cast<ushort>((Caps.VertexShaderVersion & 0x0000FF00) >> 8);
00213 nMinor = static_cast<ushort>(Caps.VertexShaderVersion & 0x000000FF);
00214
00215
00216 switch (nMajor)
00217 {
00218 case 1:
00219 m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00220 m_pCapabilities->SetMaxVertexProgramVersion("vs_1_1");
00221
00222
00223
00224
00225
00226
00227 break;
00228 case 2:
00229 m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00230 if (nMinor > 0)
00231 {
00232 m_pCapabilities->SetMaxVertexProgramVersion("vs_2_x");
00233 }
00234 else
00235 {
00236 m_pCapabilities->SetMaxVertexProgramVersion("vs_2_0");
00237 }
00238
00239
00240
00241
00242
00243
00244 break;
00245 case 3:
00246 m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00247 m_pCapabilities->SetMaxVertexProgramVersion("vs_3_0");
00248
00249
00250
00251
00252
00253
00254 break;
00255 default:
00256 m_pCapabilities->SetMaxVertexProgramVersion("");
00257 break;
00258 }
00259 }
00260
00261
00262 void CD3D9RenderSystem::SearchPixelShaderCaps(D3DCAPS9& Caps)
00263 {
00264 ushort nMajor, nMinor;
00265 nMajor = static_cast<ushort>((Caps.PixelShaderVersion & 0x0000FF00) >> 8);
00266 nMinor = static_cast<ushort>(Caps.PixelShaderVersion & 0x000000FF);
00267
00268 switch (nMajor)
00269 {
00270 case 1:
00271 m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
00272 switch (nMinor)
00273 {
00274 case 1:
00275 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_1");
00276 break;
00277 case 2:
00278 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_2");
00279 break;
00280 case 3:
00281 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_3");
00282 break;
00283 case 4:
00284 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_4");
00285 break;
00286 }
00287
00288
00289
00290
00291
00292
00293 break;
00294 case 2:
00295 m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
00296 if ((Caps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
00297 (Caps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
00298 {
00299 if ((Caps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
00300 (Caps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
00301 (Caps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION))
00302 {
00303
00304 m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_a");
00305 }
00306 else
00307 {
00308 m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_b");
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 }
00318 else
00319 {
00320 m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_0");
00321
00322
00323
00324
00325
00326
00327 }
00328 break;
00329 case 3:
00330 m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
00331 if (nMinor > 0)
00332 {
00333 m_pCapabilities->SetMaxFragmentProgramVersion("ps_3_x");
00334 }
00335 else
00336 {
00337 m_pCapabilities->SetMaxFragmentProgramVersion("ps_3_0");
00338 }
00339
00340
00341
00342
00343
00344
00345 break;
00346 default:
00347 m_pCapabilities->SetMaxFragmentProgramVersion("");
00348 break;
00349 }
00350 }
00351
00352
00353 bool CD3D9RenderSystem::CheckFormat(D3DFORMAT Format, D3DRESOURCETYPE ResourceType, ulong nUsage)
00354 {
00355 Assert(m_pD3D9->pD3D != NULL);
00356
00357 return SUCCEEDED(m_pD3D9->pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
00358 nUsage, ResourceType, Format));
00359 }
00360
00361
00362 void CD3D9RenderSystem::BeginScene() const
00363 {
00364 m_pD3D9->pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, m_ClearColor.ToRGBA(), 1.0f, 0x00);
00365 m_pD3D9->pD3DDevice->BeginScene();
00366 }
00367
00368
00369 void CD3D9RenderSystem::EndScene() const
00370 {
00371 m_pD3D9->pD3DDevice->EndScene();
00372 }
00373
00374
00375 void CD3D9RenderSystem::PrintInfo() const
00376 {
00377 printf("Direct3D9\n");
00378 }
00379
00380
00381 IBufferBase* CD3D9RenderSystem::_CreateVB(ulong nSize, ulong nStride, ulong nFlags) const
00382 {
00383
00384 LPDIRECT3DVERTEXBUFFER9 VertexBuffer;
00385 if (FAILED(m_pD3D9->pD3DDevice->CreateVertexBuffer(nSize * nStride, CD3D9Enum::BufferFlags(nFlags), 0, D3DPOOL_DEFAULT, &VertexBuffer, NULL)))
00386 D3D9_EXCEPT("Error in fonction CreateVertexBuffer", "CD3D9RenderSystem::_CreateVB");
00387
00388 return new CD3D9VertexBuffer(nSize, VertexBuffer);
00389 }
00390
00391
00392 IBufferBase* CD3D9RenderSystem::_CreateIB(ulong nSize, ulong nStride, ulong nFlags) const
00393 {
00394
00395 LPDIRECT3DINDEXBUFFER9 IndexBuffer;
00396 if (FAILED(m_pD3D9->pD3DDevice->CreateIndexBuffer(nSize * nStride, CD3D9Enum::BufferFlags(nFlags), nStride == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &IndexBuffer, NULL)))
00397 D3D9_EXCEPT("Error in fonction CreateIndexBuffer", "CD3D9RenderSystem::_CreateIB");
00398
00399 return new CD3D9IndexBuffer(nSize, IndexBuffer);
00400 }
00401
00402
00403 IDeclaration* CD3D9RenderSystem::CreateDeclaration(const TDeclarationElement* pElements, size_t nCount) const
00404 {
00405 std::vector<D3DVERTEXELEMENT9> DxElements;
00406 std::vector<int> Offset(nCount, 0);
00407
00408
00409 for (const TDeclarationElement* Elt = pElements; Elt < pElements + nCount; ++Elt)
00410 {
00411
00412 D3DVERTEXELEMENT9 CurrentElement;
00413
00414
00415 CurrentElement.Stream = Elt->Stream;
00416 CurrentElement.Offset = Offset[Elt->Stream];
00417 CurrentElement.Method = D3DDECLMETHOD_DEFAULT;
00418
00419
00420 switch (Elt->Usage)
00421 {
00422 case ELT_USAGE_POSITION :
00423 CurrentElement.Usage = D3DDECLUSAGE_POSITION;
00424 CurrentElement.UsageIndex = 0;
00425 break;
00426 case ELT_USAGE_NORMAL :
00427 CurrentElement.Usage = D3DDECLUSAGE_NORMAL;
00428 CurrentElement.UsageIndex = 0;
00429 break;
00430 case ELT_USAGE_DIFFUSE :
00431 CurrentElement.Usage = D3DDECLUSAGE_COLOR;
00432 CurrentElement.UsageIndex = 0;
00433 break;
00434 case ELT_USAGE_TEXCOORD0 :
00435 CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD;
00436 CurrentElement.UsageIndex = 0;
00437 break;
00438 case ELT_USAGE_TEXCOORD1 :
00439 CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD;
00440 CurrentElement.UsageIndex = 1;
00441 break;
00442 case ELT_USAGE_TEXCOORD2 :
00443 CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD;
00444 CurrentElement.UsageIndex = 2;
00445 break;
00446 case ELT_USAGE_TEXCOORD3 :
00447 CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD;
00448 CurrentElement.UsageIndex = 3;
00449 break;
00450 }
00451
00452
00453 switch (Elt->DataType)
00454 {
00455 case ELT_TYPE_FLOAT1 :
00456 CurrentElement.Type = D3DDECLTYPE_FLOAT1;
00457 Offset[Elt->Stream] += 4;
00458 break;
00459 case ELT_TYPE_FLOAT2 :
00460 CurrentElement.Type = D3DDECLTYPE_FLOAT2;
00461 Offset[Elt->Stream] += 8;
00462 break;
00463 case ELT_TYPE_FLOAT3 :
00464 CurrentElement.Type = D3DDECLTYPE_FLOAT3;
00465 Offset[Elt->Stream] += 12;
00466 break;
00467 case ELT_TYPE_FLOAT4 :
00468 CurrentElement.Type = D3DDECLTYPE_FLOAT4;
00469 Offset[Elt->Stream] += 16;
00470 break;
00471 case ELT_TYPE_COLOR :
00472 CurrentElement.Type = D3DDECLTYPE_D3DCOLOR;
00473 Offset[Elt->Stream] += 4;
00474 break;
00475 }
00476
00477
00478 DxElements.push_back(CurrentElement);
00479 }
00480
00481
00482 D3DVERTEXELEMENT9 EndElement = D3DDECL_END();
00483 DxElements.push_back(EndElement);
00484
00485
00486 LPDIRECT3DVERTEXDECLARATION9 Declaration = NULL;
00487 if (FAILED(m_pD3D9->pD3DDevice->CreateVertexDeclaration(&DxElements[0], &Declaration)))
00488 D3D9_EXCEPT("Error in fonction CreateVertexDeclaration", "CD3D9RenderSystem::CreateDeclaration");
00489
00490 return new CD3D9Declaration(Declaration);
00491 }
00492
00493
00494 void CD3D9RenderSystem::_SetVB(uint nStream, const IBufferBase* pBuffer, ulong nStride, ulong nMinVertex, ulong nMaxVertex)
00495 {
00496
00497 const CD3D9VertexBuffer* VertexBuffer = static_cast<const CD3D9VertexBuffer*>(pBuffer);
00498
00499
00500 m_pD3D9->pD3DDevice->SetStreamSource(nStream, VertexBuffer ? VertexBuffer->GetBuffer() : NULL, 0, nStride);
00501
00502
00503 m_nMinVertex = nMinVertex;
00504 m_nVertexCount = nMaxVertex - nMinVertex + 1;
00505 }
00506
00507
00508 void CD3D9RenderSystem::_SetIB(const IBufferBase* pBuffer, ulong nStride)
00509 {
00510
00511 const CD3D9IndexBuffer* IndexBuffer = static_cast<const CD3D9IndexBuffer*>(pBuffer);
00512
00513
00514 m_pD3D9->pD3DDevice->SetIndices(IndexBuffer ? IndexBuffer->GetBuffer() : NULL);
00515 }
00516
00517
00518 void CD3D9RenderSystem::SetDeclaration(const IDeclaration* pDeclaration)
00519 {
00520
00521 const CD3D9Declaration* DxDeclaration = static_cast<const CD3D9Declaration*>(pDeclaration);
00522
00523
00524 m_pD3D9->pD3DDevice->SetVertexDeclaration(DxDeclaration ? DxDeclaration->GetDeclaration() : NULL);
00525 }
00526
00527
00528 void CD3D9RenderSystem::DrawPrimitives(TPrimitiveType Type, ulong nFirstVertex, ulong nCount) const
00529 {
00530 m_pD3D9->pD3DDevice->DrawPrimitive(CD3D9Enum::Get(Type), nFirstVertex, nCount);
00531 }
00532
00533
00534 void CD3D9RenderSystem::DrawIndexedPrimitives(TPrimitiveType Type, ulong nFirstIndex, ulong nCount) const
00535 {
00536 m_pD3D9->pD3DDevice->DrawIndexedPrimitive(CD3D9Enum::Get(Type), 0, m_nMinVertex, m_nVertexCount, nFirstIndex, nCount);
00537 }
00538
00539
00540 void CD3D9RenderSystem::PushMatrix(TMatrixType Type)
00541 {
00542 m_Matrices[Type].push_back(m_Matrices[Type].back());
00543 }
00544
00545
00546 void CD3D9RenderSystem::PopMatrix(TMatrixType Type)
00547 {
00548 m_Matrices[Type].pop_back();
00549
00550 m_pD3D9->pD3DDevice->SetTransform(CD3D9Enum::Get(Type), (D3DMATRIX*)&m_Matrices[Type].back());
00551 }
00552
00553
00554 void CD3D9RenderSystem::LoadMatrix(TMatrixType Type, const CMatrix4& Matrix)
00555 {
00556 m_Matrices[Type].back() = Matrix;
00557
00558 m_pD3D9->pD3DDevice->SetTransform(CD3D9Enum::Get(Type), (D3DMATRIX*)&Matrix);
00559 }
00560
00561
00562 void CD3D9RenderSystem::LoadMatrixMult(TMatrixType Type, const CMatrix4& Matrix)
00563 {
00564 m_Matrices[Type].back() = Matrix * m_Matrices[Type].back();
00565
00566 m_pD3D9->pD3DDevice->SetTransform(CD3D9Enum::Get(Type), (D3DMATRIX*)&m_Matrices[Type].back());
00567 }
00568
00569
00570 void CD3D9RenderSystem::GetMatrix(TMatrixType Type, CMatrix4& Matrix) const
00571 {
00572 Matrix = m_Matrices[Type].back();
00573 }
00574
00575
00576 ulong CD3D9RenderSystem::ConvertColor(const CColor& Color) const
00577 {
00578 return Color.ToARGB();
00579 }
00580
00581
00582 ITextureBase* CD3D9RenderSystem::CreateTexture(const TVector2I& Size, TPixelFormat Format, ulong nFlags) const
00583 {
00584
00585 bool bHasMipmaps = (nFlags & TEX_NOMIPMAP) != 0;
00586 bool bAutoMipmaps = GetCapabilities()->HasCapability(CAP_HW_MIPMAPPING) &&
00587 m_pD3D9->pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
00588 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE,
00589 CD3D9Enum::Get(Format)) == D3D_OK;
00590
00591
00592 ulong nUsage = bAutoMipmaps ? D3DUSAGE_AUTOGENMIPMAP : 0;
00593
00594
00595 LPDIRECT3DTEXTURE9 Texture = NULL;
00596 if (FAILED(D3DXCreateTexture(m_pD3D9->pD3DDevice, Size.x, Size.y, 0, nUsage, CD3D9Enum::Get(Format), D3DPOOL_MANAGED, &Texture)))
00597 D3D9_EXCEPT("Error in fonction D3DXCreateTexture", "CD3D9RenderSystem::CreateTexture");
00598
00599 return new CD3D9Texture(Size, Format, bHasMipmaps, bAutoMipmaps, Texture);
00600 }
00601
00602
00603 void CD3D9RenderSystem::SetTexture(uint nUnit, const ITextureBase* pTexture) const
00604 {
00605 const CD3D9Texture* DxTexture = static_cast<const CD3D9Texture*>(pTexture);
00606 m_pD3D9->pD3DDevice->SetTexture(nUnit, DxTexture ? DxTexture->GetD3D9Texture() : NULL);
00607 }
00608
00609
00610 void CD3D9RenderSystem::SetupAlphaBlending(TBlend Src, TBlend Dest) const
00611 {
00612 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_SRCBLEND, CD3D9Enum::Get(Src));
00613 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_DESTBLEND, CD3D9Enum::Get(Dest));
00614 }
00615
00616
00617 void CD3D9RenderSystem::SetupTextureUnit(uint nUnit, TTextureOp Op, TTextureArg Arg1, TTextureArg Arg2, const CColor& Constant) const
00618 {
00619
00620 if (Op < TXO_ALPHA_FIRSTARG)
00621 {
00622 m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_COLOROP, CD3D9Enum::Get(Op));
00623 m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_COLORARG1, CD3D9Enum::Get(Arg1));
00624 m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_COLORARG2, CD3D9Enum::Get(Arg2));
00625 }
00626 else
00627 {
00628 m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_ALPHAOP, CD3D9Enum::Get(Op));
00629 m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_ALPHAARG1, CD3D9Enum::Get(Arg1));
00630 m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_ALPHAARG2, CD3D9Enum::Get(Arg2));
00631 }
00632
00633
00634 if ((Arg1 == TXA_CONSTANT) || (Arg2 == TXA_CONSTANT))
00635 {
00636 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR, ConvertColor(Constant));
00637 }
00638 }
00639
00640
00641 void CD3D9RenderSystem::Enable(TRenderParameter Param, bool bValue) const
00642 {
00643 m_pD3D9->pD3DDevice->SetRenderState(CD3D9Enum::Get(Param), bValue);
00644 }
00645
00646
00647 IShaderBase* CD3D9RenderSystem::CreateShader(CGprogram Program, TShaderType Type) const
00648 {
00649 return new CD3D9Shader(Program, Type);
00650 }
00651
00652
00653 void CD3D9RenderSystem::SetVertexShader(const IShaderBase* pShader)
00654 {
00655 const CD3D9Shader* pDxShader = static_cast<const CD3D9Shader*>(pShader);
00656
00657 if (pDxShader)
00658 {
00659 if (pDxShader->GetType() != SHADER_VERTEX)
00660 D3D9_EXCEPT("Incorrect shader type (Pixel Shader)", "CD3D9RenderSystem::SetVertexShader");
00661
00662 cgD3D9BindProgram(pDxShader->GetProgram());
00663 }
00664 else
00665 {
00666 m_pD3D9->pD3DDevice->SetVertexShader(NULL);
00667 }
00668 }
00669
00670
00671 void CD3D9RenderSystem::SetPixelShader(const IShaderBase* pShader)
00672 {
00673 const CD3D9Shader* pDxShader = static_cast<const CD3D9Shader*>(pShader);
00674
00675 if (pDxShader)
00676 {
00677 if (pDxShader->GetType() != SHADER_PIXEL)
00678 D3D9_EXCEPT("Incorrect shader type (Vertex Shader)", "CD3D9RenderSystem::SetPixelShader");
00679
00680 cgD3D9BindProgram(pDxShader->GetProgram());
00681 }
00682 else
00683 {
00684 m_pD3D9->pD3DDevice->SetPixelShader(NULL);
00685 }
00686 }
00687
00688
00689 void CD3D9RenderSystem::RestoreLostDevice(void)
00690 {
00691
00692 HRESULT hr = m_pD3D9->pD3DDevice->Reset(
00693 ((CD3D9Window*)m_pRenderWindow)->GetPresentationParameters());
00694
00695 if (hr == D3DERR_DEVICELOST)
00696 {
00697
00698 return;
00699 }
00700 else if (FAILED(hr))
00701 {
00702 D3D9_EXCEPT("Cannot reset device !", "CD3D9RenderSystem::RestoreLostDevice");
00703 }
00704
00705 m_bDeviceLost = false;
00706 }
00707
00708
00709 bool CD3D9RenderSystem::IsDeviceLost(void)
00710 {
00711 return m_bDeviceLost;
00712 }
00713
00714
00715 void CD3D9RenderSystem::_NotifyDeviceLost(void)
00716 {
00717 m_bDeviceLost = true;
00718 }
00719
00720
00721 void CD3D9RenderSystem::SetClearColor(const CColor& Color)
00722 {
00723 m_ClearColor = Color;
00724 }
00725
00726
00727 void CD3D9RenderSystem::SetLight(uint nIndex, CLight* pLight)
00728 {
00729 HRESULT hr;
00730
00731 D3DLIGHT9 d3dLight;
00732 ZeroMemory( &d3dLight, sizeof(d3dLight) );
00733
00734 if (!pLight)
00735 {
00736 if ( FAILED( hr = m_pD3D9->pD3DDevice->LightEnable( nIndex, FALSE) ) )
00737 D3D9_EXCEPT("Unable to disable light", "CD3D9RenderSystem::SetLight");
00738 }
00739 else
00740 {
00741 switch ( pLight->GetType() )
00742 {
00743 case CLight::LT_POINT:
00744 d3dLight.Type = D3DLIGHT_POINT;
00745 break;
00746
00747 case CLight::LT_DIRECTIONAL:
00748 d3dLight.Type = D3DLIGHT_DIRECTIONAL;
00749 break;
00750
00751 case CLight::LT_SPOT:
00752 d3dLight.Type = D3DLIGHT_SPOT;
00753 d3dLight.Falloff = pLight->GetSpotFalloff();
00754 d3dLight.Theta = pLight->GetSpotInnerAngle().valueRadians();
00755 ;
00756 d3dLight.Phi = pLight->GetSpotOuterAngle().valueRadians();
00757 ;
00758 break;
00759 }
00760
00761 CColor Col;
00762 float f4vals[4];
00763
00764 Col = pLight->GetDiffuseColor();
00765 Col.ToFloat(f4vals);
00766 d3dLight.Diffuse = D3DXCOLOR( f4vals[0], f4vals[1], f4vals[2], f4vals[3] );
00767
00768 Col = pLight->GetSpecularColor();
00769 Col.ToFloat(f4vals);
00770 d3dLight.Specular = D3DXCOLOR( f4vals[0], f4vals[1], f4vals[2], f4vals[3] );
00771
00772 TVector3F Vec;
00773 if ( pLight->GetType() != CLight::LT_DIRECTIONAL )
00774 {
00775 Vec = pLight->GetPosition();
00776 d3dLight.Position = D3DXVECTOR3( Vec.x, Vec.y, Vec.z );
00777 }
00778 if ( pLight->GetType() != CLight::LT_POINT )
00779 {
00780 Vec = pLight->GetDirection();
00781 d3dLight.Direction = D3DXVECTOR3( Vec.x, Vec.y, Vec.z );
00782 }
00783
00784 d3dLight.Range = pLight->GetAttenuationRange();
00785 d3dLight.Attenuation0 = pLight->GetAttenuationConstant();
00786 d3dLight.Attenuation1 = pLight->GetAttenuationLinear();
00787 d3dLight.Attenuation2 = pLight->GetAttenuationQuadric();
00788
00789 if ( FAILED( hr = m_pD3D9->pD3DDevice->SetLight( nIndex, &d3dLight ) ) )
00790 D3D9_EXCEPT("Unable to set light details", "CD3D9RenderSystem::SetLight");
00791
00792 if ( FAILED( hr = m_pD3D9->pD3DDevice->LightEnable( nIndex, TRUE ) ) )
00793 D3D9_EXCEPT("Unable to enable light", "CD3D9RenderSystem::SetLight");
00794 }
00795 }
00796
00797
00798 void CD3D9RenderSystem::SetFillMode(TFillMode Mode)
00799 {
00800 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_FILLMODE, CD3D9Enum::Get(Mode));
00801 }
00802
00803 }