KeosD3D9RenderSystem.cpp

Go to the documentation of this file.
00001 /*
00002  * This source file is part of KEOS (Free 3D Engine)
00003  * For the latest info, see http://www.keosengine.org/
00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
00005  *
00006  * This program is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free Software
00008  * Foundation; either version 2 of the License, or (at your option) any later
00009  * version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00018  * http://www.gnu.org/copyleft/lesser.txt.
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   // CD3D9RenderSystem implementation
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     // Create our Direct3D object
00054     if ( NULL == (m_pD3D9->pD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
00055       D3D9_EXCEPT("Failed to create Direct3D9 object", "CD3D9RenderSystem::CD3D9RenderSystem");
00056 
00057     // Create Matrices
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     // Create the window
00132     IRenderWindow* win = new CD3D9Window(m_pD3D9);
00133     win->Create(strName, nWidth, nHeight, nColourDepth, bFullScreen);
00134 
00135     AttachRenderTarget( *win );
00136 
00137     InitCapabilities();
00138 
00139     // Direct3D default states
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     // Get caps
00164     D3DCAPS9 Caps;
00165     m_pD3D9->pD3DDevice->GetDeviceCaps(&Caps);
00166 
00167     // Check for hardware mipmapping support
00168     if ((Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0)
00169       m_pCapabilities->SetCapability(CAP_HW_MIPMAPPING);
00170 
00171     // Check for texture dxt compression
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     // Check for non-power-of-2 texture support
00178     if (!(Caps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
00179         !(Caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
00180       m_pCapabilities->SetCapability(CAP_NON_POWER_OF_2_TEXTURES);
00181 
00182     // Set number of texture units
00183     m_pCapabilities->SetNumTextureUnits(Caps.MaxSimultaneousTextures);
00184 
00185     // Check for Vertex Shaders support and set version number
00186     SearchVertexShaderCaps(Caps);
00187     // Check for Pixel Shaders support and set version number
00188     SearchPixelShaderCaps(Caps);
00189 
00190     m_pCapabilities->Log();
00191 
00192     // Setup Cg D3D Runtime
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     // Populate max version & params
00216     switch (nMajor)
00217     {
00218       case 1:
00219         m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00220         m_pCapabilities->SetMaxVertexProgramVersion("vs_1_1");
00221         // No boolean params allowed
00222         //m_pCapabilities->SetVertexProgramConstantBoolCount(0);
00223         // No integer params allowed
00224         //m_pCapabilities->SetVertexProgramConstantIntCount(0);
00225         // float params, always 4D
00226         //m_pCapabilities->SetVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
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         // 16 boolean params allowed
00239         //m_pCapabilities->SetVertexProgramConstantBoolCount(16);
00240         // 16 integer params allowed, 4D
00241         //m_pCapabilities->SetVertexProgramConstantIntCount(16);
00242         // float params, always 4D
00243         //m_pCapabilities->SetVertexProgramConstantFloatCount(Caps.MaxVertexShaderConst);
00244         break;
00245       case 3:
00246         m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
00247         m_pCapabilities->SetMaxVertexProgramVersion("vs_3_0");
00248         // 16 boolean params allowed
00249         //m_pCapabilities->SetVertexProgramConstantBoolCount(16);
00250         // 16 integer params allowed, 4D
00251         //m_pCapabilities->SetVertexProgramConstantIntCount(16);
00252         // float params, always 4D
00253         //m_pCapabilities->SetVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
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         // no boolean params allowed
00288         //m_pCapabilities->SetFragmentProgramConstantBoolCount(0);
00289         // no integer params allowed
00290         //m_pCapabilities->SetFragmentProgramConstantIntCount(0);
00291         // float params, always 4D
00292         //m_pCapabilities->SetFragmentProgramConstantFloatCount(8);
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             // ps_2_a is more powerful than ps_2_b? odd
00304             m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_a");
00305           }
00306           else
00307           {
00308             m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_b");
00309           }
00310 
00311           // 16 boolean params allowed
00312           //m_pCapabilities->SetFragmentProgramConstantBoolCount(16);
00313           // 16 integer params allowed, 4D
00314           //m_pCapabilities->SetFragmentProgramConstantIntCount(16);
00315           // float params, always 4D
00316           //m_pCapabilities->SetFragmentProgramConstantFloatCount(224);
00317         }
00318         else
00319         {
00320           m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_0");
00321           // no boolean params allowed
00322           //m_pCapabilities->SetFragmentProgramConstantBoolCount(0);
00323           // no integer params allowed
00324           //m_pCapabilities->SetFragmentProgramConstantIntCount(0);
00325           // float params, always 4D
00326           //m_pCapabilities->SetFragmentProgramConstantFloatCount(32);
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         // 16 boolean params allowed
00340         //m_pCapabilities->SetFragmentProgramConstantBoolCount(16);
00341         // 16 integer params allowed, 4D
00342         //m_pCapabilities->SetFragmentProgramConstantIntCount(16);
00343         // float params, always 4D
00344         //m_pCapabilities->SetFragmentProgramConstantFloatCount(224);
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     // Create buffer
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     // Create buffer
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     // Convert declaration elements in Dx9 elements
00409     for (const TDeclarationElement* Elt = pElements; Elt < pElements + nCount; ++Elt)
00410     {
00411       // Build temp element
00412       D3DVERTEXELEMENT9 CurrentElement;
00413 
00414       // Stream, offset and method
00415       CurrentElement.Stream = Elt->Stream;
00416       CurrentElement.Offset = Offset[Elt->Stream];
00417       CurrentElement.Method = D3DDECLMETHOD_DEFAULT;
00418 
00419       // Usage
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       // Offset
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       // Add the current element
00478       DxElements.push_back(CurrentElement);
00479     }
00480 
00481     // Add the element which is the end of the array
00482     D3DVERTEXELEMENT9 EndElement = D3DDECL_END();
00483     DxElements.push_back(EndElement);
00484 
00485     // Create declaration
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     // Get the Dx buffer
00497     const CD3D9VertexBuffer* VertexBuffer = static_cast<const CD3D9VertexBuffer*>(pBuffer);
00498 
00499     // Send to the API
00500     m_pD3D9->pD3DDevice->SetStreamSource(nStream, VertexBuffer ? VertexBuffer->GetBuffer() : NULL, 0, nStride);
00501 
00502     // Save MinVertex and VertexCount
00503     m_nMinVertex   = nMinVertex;
00504     m_nVertexCount = nMaxVertex - nMinVertex + 1;
00505   }
00506 
00507   //-----------------------------------------------------------------------
00508   void CD3D9RenderSystem::_SetIB(const IBufferBase* pBuffer, ulong nStride)
00509   {
00510     // Get the Dx buffer
00511     const CD3D9IndexBuffer* IndexBuffer = static_cast<const CD3D9IndexBuffer*>(pBuffer);
00512 
00513     // Send to the API
00514     m_pD3D9->pD3DDevice->SetIndices(IndexBuffer ? IndexBuffer->GetBuffer() : NULL);
00515   }
00516 
00517   //-----------------------------------------------------------------------
00518   void CD3D9RenderSystem::SetDeclaration(const IDeclaration* pDeclaration)
00519   {
00520     // Get the Dx buffer
00521     const CD3D9Declaration* DxDeclaration = static_cast<const CD3D9Declaration*>(pDeclaration);
00522 
00523     // Send to the API
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     // Detect mipmapping options
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     // Adjust Usage
00592     ulong nUsage = bAutoMipmaps ? D3DUSAGE_AUTOGENMIPMAP : 0;
00593 
00594     // Create Dx9 texture
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     // Operator and arguments
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     // Constant
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     // Reset the device, using the primary window presentation params
00692     HRESULT hr = m_pD3D9->pD3DDevice->Reset(
00693                    ((CD3D9Window*)m_pRenderWindow)->GetPresentationParameters());
00694 
00695     if (hr == D3DERR_DEVICELOST)
00696     {
00697       // Don't continue
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 } // namespace Keos

Generated on Fri Mar 9 14:29:03 2007 for Keos by  doxygen 1.5.1-p1