shdrenderer.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/shdrenderer.cpp $*
  25. *
  26. * Org Author:: Jani_p
  27. * *
  28. * $Author:: Kenny_m
  29. *
  30. * $Modtime:: 7/29/02 1:50p $*
  31. * *
  32. * $Revision:: 3 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * 6/02/02 5:59p KM Added render info and light environment support $*
  37. * 7/29/02 1:50p KM Added VB and IB usage flags for software vertex shaders
  38. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  39. #include "shdrenderer.h"
  40. #include "shdforcelinks.h"
  41. #include "shdmesh.h"
  42. #include "shdsubmesh.h"
  43. #include "shddef.h"
  44. #include "shddefmanager.h"
  45. #include "shdclassids.h"
  46. #include "wwdebug.h"
  47. #include "dx8vertexbuffer.h"
  48. #include "dx8indexbuffer.h"
  49. #include "dx8wrapper.h"
  50. #include "rinfo.h"
  51. #include "camera.h"
  52. #include "texture.h"
  53. #include "ww3dformat.h"
  54. #include "wwprofile.h"
  55. #include "sortingrenderer.h"
  56. #include "meshmatdesc.h"
  57. static DynamicVectorClass<Vector3> _TempVertexBuffer;
  58. static DynamicVectorClass<Vector3> _TempNormalBuffer;
  59. ShdRendererClass* ShdRendererClass::ShdRenderer=NULL;
  60. ShdRendererClass::ShdRendererClass()
  61. {
  62. }
  63. ShdRendererClass::~ShdRendererClass()
  64. {
  65. }
  66. /////////////////////////////////////////////////////////////////////////////////////
  67. // Initialize the rendering system. This is the place to create different versions
  68. // (such as DX8, DX9, OGL) of the rendering system, if needed.
  69. /////////////////////////////////////////////////////////////////////////////////////
  70. void ShdRendererClass::Init()
  71. {
  72. SHD_Force_Links();
  73. WWASSERT(!ShdRenderer);
  74. ShdRenderer=new ShdDX8RendererClass();
  75. Init_Shaders();
  76. }
  77. void ShdRendererClass::Init_Shaders()
  78. {
  79. ShdDefClass* def;
  80. for (int i=SHDDEF_CLASSID_DUMMY+1; i<SHDDEF_CLASSID_LAST; i++)
  81. {
  82. def=ShdDefManagerClass::Create_ShdDefClass_Instance(i);
  83. if (def != NULL) {
  84. def->Init();
  85. REF_PTR_RELEASE(def);
  86. }
  87. }
  88. }
  89. /////////////////////////////////////////////////////////////////////////////////////
  90. // Release the renderer system. At this point, all the meshes must have been
  91. // unregistered.
  92. /////////////////////////////////////////////////////////////////////////////////////
  93. void ShdRendererClass::Shutdown()
  94. {
  95. Shutdown_Shaders();
  96. WWASSERT(ShdRenderer);
  97. delete ShdRenderer;
  98. ShdRenderer=0;
  99. }
  100. void ShdRendererClass::Shutdown_Shaders()
  101. {
  102. ShdDefClass* def;
  103. for (int i=SHDDEF_CLASSID_DUMMY+1; i<SHDDEF_CLASSID_LAST; i++)
  104. {
  105. def=ShdDefManagerClass::Create_ShdDefClass_Instance(i);
  106. if (def) {
  107. def->Shutdown();
  108. REF_PTR_RELEASE(def);
  109. }
  110. }
  111. }
  112. /////////////////////////////////////////////////////////////////////////////////////
  113. // DirectX8 renderer utility class declaration
  114. /////////////////////////////////////////////////////////////////////////////////////
  115. RendererListContainerClass::RendererListContainerClass(int pass) : Pass(pass)
  116. {
  117. }
  118. RendererListContainerClass::~RendererListContainerClass()
  119. {
  120. Unregister_All();
  121. }
  122. void RendererListContainerClass::Register_Renderer(ShdRendererNodeClass* node)
  123. {
  124. WWASSERT(node);
  125. node->Add_Ref();
  126. node->Set_Renderer_List_Container(this,Pass);
  127. LinkedNodes.Add_Tail(node);
  128. }
  129. void RendererListContainerClass::Unregister_All()
  130. {
  131. while (!LinkedNodes.Is_Empty()) {
  132. ShdRendererNodeClass* node=LinkedNodes.Remove_Head();
  133. // REF_PTR_RELEASE(node);
  134. delete node;
  135. }
  136. }
  137. void RendererListContainerClass::Flush()
  138. {
  139. ShdRendererNodeClass* prev_node=NULL;
  140. while (!VisibleNodes.Is_Empty())
  141. {
  142. ShdRendererNodeClass* node=VisibleNodes.Remove_Head();
  143. node->Apply_Shared_Shader_Settings(prev_node,Pass);
  144. node->Flush(Pass);
  145. prev_node=node;
  146. }
  147. }
  148. class ShdDX8RendererClass::MeshContainerClass : public RefCountClass
  149. {
  150. public:
  151. MeshContainerClass();
  152. virtual ~MeshContainerClass();
  153. ShdRendererNodeClass* Register_Mesh(ShdMeshClass* mesh,ShdSubMeshClass* sub_mesh);
  154. // void Add_Visible_Node(ShdRendererNodeClass* node,int pass);
  155. void Flush();
  156. private:
  157. // ShdRendererNodeList VisibleNodeList[SHD_MAX_PASSES];
  158. RendererListContainerList RendererListContainers[SHD_MAX_PASSES];
  159. };
  160. /**
  161. ** ShdDX8RendererNode
  162. */
  163. class ShdDX8RendererNodeClass : public ShdRendererNodeClass
  164. {
  165. public:
  166. ShdDX8RendererNodeClass(ShdDX8RendererClass::MeshContainerClass* container, ShdMeshClass* mesh,ShdSubMeshClass* sub_mesh);
  167. virtual ~ShdDX8RendererNodeClass();
  168. virtual void Render(RenderInfoClass& rinfo);
  169. virtual void Flush(int pass);
  170. virtual void Apply_Shared_Shader_Settings(ShdRendererNodeClass* prev,int pass);
  171. virtual bool Greater_Than(const ShdRendererNodeClass&, int pass) const;
  172. virtual bool Similar_Enough(const ShdRendererNodeClass&, int pass) const;
  173. private:
  174. ShdDX8RendererClass::MeshContainerClass* Container;
  175. ShdMeshClass* Mesh;
  176. ShdSubMeshClass* SubMesh;
  177. VertexBufferClass** VertexBuffers;
  178. IndexBufferClass* IndexBuffer;
  179. LightEnvironmentClass LightEnvironment; // todo KJM optimize for output lights
  180. RenderInfoClass* RenderInfo;
  181. };
  182. /////////////////////////////////////////////////////////////////////////////////////
  183. // DirectX8 renderer implementation
  184. /////////////////////////////////////////////////////////////////////////////////////
  185. ShdDX8RendererClass::ShdDX8RendererClass()
  186. {
  187. MeshCategories=new MeshContainerClass*[SHDDEF_CLASSID_LAST];
  188. for (int i=0;i<SHDDEF_CLASSID_LAST;++i)
  189. {
  190. MeshCategories[i]=0;
  191. }
  192. }
  193. ShdDX8RendererClass::~ShdDX8RendererClass()
  194. {
  195. for (int i=0;i<SHDDEF_CLASSID_LAST;++i)
  196. {
  197. if (MeshCategories[i])
  198. {
  199. REF_PTR_RELEASE(MeshCategories[i]);
  200. delete MeshCategories[i];
  201. MeshCategories[i]=0;
  202. }
  203. }
  204. delete[] MeshCategories;
  205. MeshCategories=0;
  206. }
  207. bool ShdDX8RendererNodeClass::Greater_Than(const ShdRendererNodeClass& s, int pass) const
  208. {
  209. // Danger! Assuming ShdDX8RendererNodeClass!
  210. const ShdDX8RendererNodeClass* src=static_cast<const ShdDX8RendererNodeClass*>(&s);
  211. WWASSERT(SubMesh && src->SubMesh);
  212. return SubMesh->Peek_Shader()->Greater_Than(*src->SubMesh->Peek_Shader(),pass);
  213. }
  214. bool ShdDX8RendererNodeClass::Similar_Enough(const ShdRendererNodeClass& s, int pass) const
  215. {
  216. // Danger! Assuming ShdDX8RendererNodeClass!
  217. const ShdDX8RendererNodeClass* src=static_cast<const ShdDX8RendererNodeClass*>(&s);
  218. WWASSERT(SubMesh && src->SubMesh);
  219. return SubMesh->Peek_Shader()->Similar_Enough(*src->SubMesh->Peek_Shader(),pass);
  220. }
  221. /////////////////////////////////////////////////////////////////////////////////////
  222. // Register mesh to the rendering system
  223. /////////////////////////////////////////////////////////////////////////////////////
  224. ShdRendererNodeClass* ShdDX8RendererClass::Register_Mesh
  225. (
  226. ShdMeshClass* mesh,
  227. ShdSubMeshClass* sub_mesh
  228. )
  229. {
  230. ShdInterfaceClass* shd=sub_mesh->Peek_Shader();
  231. const ShdDefClass* def=shd->Peek_Definition();
  232. uint32 class_id=def->Get_Class_ID();
  233. WWASSERT(class_id<SHDDEF_CLASSID_LAST);
  234. if (!MeshCategories[class_id])
  235. {
  236. MeshCategories[class_id]=new MeshContainerClass();
  237. }
  238. return MeshCategories[class_id]->Register_Mesh(mesh,sub_mesh);
  239. }
  240. /////////////////////////////////////////////////////////////////////////////////////
  241. // Flush the list of visible meshes
  242. /////////////////////////////////////////////////////////////////////////////////////
  243. void ShdDX8RendererClass::Flush()
  244. {
  245. WWPROFILE("ShdDX8RendererClass::Flush");
  246. DX8Wrapper::Apply_Render_State_Changes();
  247. DX8Wrapper::Invalidate_Cached_Render_States();
  248. DX8Wrapper::Apply_Default_State();
  249. SNAPSHOT_SAY(("ShdDX8RendererClass::Flush()\n"));
  250. for (int i=0;i<SHDDEF_CLASSID_LAST;++i)
  251. {
  252. if (MeshCategories[i])
  253. {
  254. MeshCategories[i]->Flush();
  255. }
  256. }
  257. DX8Wrapper::Invalidate_Cached_Render_States();
  258. DX8Wrapper::Apply_Default_State();
  259. }
  260. /////////////////////////////////////////////////////////////////////////////////////
  261. // MeshContiner is used for each shader type. Meshes are assigned to a container
  262. // when they're first rendered and they link themselves to container's visible list
  263. // each frame they're visible.
  264. /////////////////////////////////////////////////////////////////////////////////////
  265. ShdDX8RendererClass::MeshContainerClass::MeshContainerClass()
  266. {
  267. }
  268. ShdDX8RendererClass::MeshContainerClass::~MeshContainerClass()
  269. {
  270. for (int pass=0; pass<SHD_MAX_PASSES; pass++)
  271. {
  272. while (!RendererListContainers[pass].Is_Empty()) {
  273. RendererListContainerClass* cont=RendererListContainers[pass].Remove_Head();
  274. cont->Unregister_All();
  275. REF_PTR_RELEASE(cont);
  276. }
  277. }
  278. }
  279. /////////////////////////////////////////////////////////////////////////////////////
  280. // RendererNodeClass acts as a link between ShdMeshClass, ShdSubMeshClass and the
  281. // rendering system.
  282. /////////////////////////////////////////////////////////////////////////////////////
  283. ShdRendererNodeClass* ShdDX8RendererClass::MeshContainerClass::Register_Mesh
  284. (
  285. ShdMeshClass* mesh,
  286. ShdSubMeshClass* sub_mesh
  287. )
  288. {
  289. ShdDX8RendererNodeClass* node=new ShdDX8RendererNodeClass(this,mesh,sub_mesh);
  290. ShdInterfaceClass* shdi=sub_mesh->Peek_Shader();
  291. WWASSERT(shdi);
  292. for (int pass=0; pass<shdi->Get_Pass_Count(); pass++)
  293. {
  294. RendererListContainerIterator ite(&RendererListContainers[pass]);
  295. ite.Last();
  296. while (!ite.Is_Done()) {
  297. RendererListContainerClass* cont=ite.Peek_Obj();
  298. if (cont) {
  299. ShdRendererNodeListIterator ite2(&cont->Peek_Linked_Nodes());
  300. ite2.First();
  301. // Container should delete itself when the last node is removed, so we must
  302. // never have an empty node.
  303. WWASSERT(!ite2.Is_Done());
  304. ShdRendererNodeClass* obj=ite2.Peek_Obj();
  305. if (obj) {
  306. if (node->Greater_Than(*obj,pass)) {
  307. // If similar enough, add to the same renderer container, otherwise create a new one
  308. if (node->Similar_Enough(*obj,pass)) {
  309. cont->Register_Renderer(node);
  310. }
  311. else {
  312. RendererListContainerClass* new_cont=new RendererListContainerClass(pass);
  313. new_cont->Register_Renderer(node);
  314. RendererListContainers[pass].Add_After(new_cont,new_cont);
  315. }
  316. break;
  317. }
  318. }
  319. }
  320. ite.Prev();
  321. }
  322. if (ite.Is_Done()) {
  323. RendererListContainerClass* new_cont=new RendererListContainerClass(pass);
  324. new_cont->Register_Renderer(node);
  325. RendererListContainers[pass].Add(new_cont);
  326. }
  327. }
  328. return node;
  329. }
  330. /////////////////////////////////////////////////////////////////////////////////////
  331. // Render all visible nodes and clear the visible list.
  332. /////////////////////////////////////////////////////////////////////////////////////
  333. void ShdDX8RendererClass::MeshContainerClass::Flush()
  334. {
  335. SNAPSHOT_SAY(("ShdDX8RendererClass::MeshContainerClass::Flush()\n"));
  336. for (int pass=0; pass<SHD_MAX_PASSES; pass++)
  337. {
  338. RendererListContainerIterator ite(&RendererListContainers[pass]);
  339. ite.First();
  340. while (!ite.Is_Done()) {
  341. RendererListContainerClass* cont=ite.Peek_Obj();
  342. cont->Flush();
  343. ite.Next();
  344. }
  345. }
  346. }
  347. /***********************************************************************************************
  348. * ShdDX8RendererNodeClass::ShdDX8RendererNodeClass --
  349. * Init the mesh for rendering... this node is used for all subsequent rendering of
  350. * the particular mesh.
  351. * INPUT: *
  352. * *
  353. * OUTPUT: *
  354. * *
  355. * WARNINGS: *
  356. * *
  357. * HISTORY: *
  358. * 4/20/2002 jp : Created
  359. * 5/26/2002 kjm : Updated stream handling for per-pixel shaders *
  360. * 6/02/2002 kjm : Added light environment handling
  361. * 7/29/2002 kjm : Added VB and IB usage flags for software vertex shaders
  362. *=============================================================================================*/
  363. ShdDX8RendererNodeClass::ShdDX8RendererNodeClass
  364. (
  365. ShdDX8RendererClass::MeshContainerClass* container,
  366. ShdMeshClass* mesh,
  367. ShdSubMeshClass* sub_mesh
  368. )
  369. : Container(container),
  370. Mesh(NULL),
  371. SubMesh(NULL),
  372. VertexBuffers(NULL),
  373. IndexBuffer(NULL)
  374. {
  375. REF_PTR_SET(Container,container);
  376. REF_PTR_SET(Mesh,mesh);
  377. REF_PTR_SET(SubMesh,sub_mesh);
  378. // create usage depending on associated shader's processing behaviour KM
  379. DX8IndexBufferClass::UsageType ib_usage=DX8IndexBufferClass::USAGE_DEFAULT;
  380. if (!SubMesh->Peek_Shader()->Use_HW_Vertex_Processing())
  381. {
  382. ib_usage=DX8IndexBufferClass::USAGE_SOFTWAREPROCESSING;
  383. }
  384. int count=SubMesh->Get_Visible_Polygon_Count();
  385. if (!count) count=SubMesh->Get_Polygon_Count();
  386. unsigned index_count=count*3;
  387. if (SubMesh->Is_Sorting()) {
  388. IndexBuffer=new SortingIndexBufferClass(index_count);
  389. }
  390. else {
  391. IndexBuffer=new DX8IndexBufferClass(index_count,ib_usage);
  392. }
  393. IndexBufferClass::WriteLockClass ilock(IndexBuffer);
  394. const TriIndex* indices=SubMesh->Get_Polygon_Array();
  395. int i;
  396. int j=0;
  397. for (i=SubMesh->Get_First_Visible_Polygon();i<count+SubMesh->Get_First_Visible_Polygon();++i)
  398. {
  399. ilock.Get_Index_Array()[j++]=indices[i][0];
  400. ilock.Get_Index_Array()[j++]=indices[i][1];
  401. ilock.Get_Index_Array()[j++]=indices[i][2];
  402. }
  403. // Don't use static vertex buffers if skin
  404. if (SubMesh->Get_Flag(MeshGeometryClass::SKIN)) {
  405. return;
  406. }
  407. // Compose the vertex and index buffers
  408. VertexStreamStruct vss;
  409. vss.Locations=SubMesh->Get_Vertex_Array();
  410. vss.Normals=SubMesh->Get_Vertex_Normal_Array();
  411. for (unsigned stage=0;stage<MAX_TEXTURE_STAGES;++stage)
  412. {
  413. vss.UV[stage]=SubMesh->Get_UV_Array(stage);
  414. }
  415. vss.DiffuseInt=SubMesh->Get_Diffuse_Array();
  416. vss.S=SubMesh->Get_Tangent_Basis_S_Array();
  417. vss.T=SubMesh->Get_Tangent_Basis_T_Array();
  418. vss.SxT=SubMesh->Get_Tangent_Basis_SxT_Array();
  419. unsigned vertex_count=SubMesh->Get_Vertex_Count();
  420. unsigned stream_count=SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();
  421. WWASSERT(stream_count>0);
  422. // create usage depending on associated shader's processing behaviour KM
  423. DX8VertexBufferClass::UsageType vb_usage=DX8VertexBufferClass::USAGE_DEFAULT;
  424. if (!SubMesh->Peek_Shader()->Use_HW_Vertex_Processing())
  425. {
  426. vb_usage=DX8VertexBufferClass::USAGE_SOFTWAREPROCESSING;
  427. }
  428. VertexBuffers=new VertexBufferClass*[stream_count];
  429. unsigned n;
  430. for (n=0;n<stream_count;++n)
  431. {
  432. unsigned vertex_size=SubMesh->Peek_Shader()->Get_Vertex_Size(n);
  433. if (SubMesh->Is_Sorting()) {
  434. VertexBuffers[n]=
  435. new SortingVertexBufferClass(vertex_count);
  436. }
  437. else {
  438. VertexBuffers[n]=
  439. new DX8VertexBufferClass
  440. (
  441. 0,
  442. vertex_count,
  443. vb_usage,
  444. vertex_size
  445. );
  446. }
  447. VertexBufferClass::WriteLockClass vlock(VertexBuffers[n]);
  448. SubMesh->Peek_Shader()->Copy_Vertex_Stream
  449. (
  450. n,
  451. vlock.Get_Vertex_Array(),
  452. vss,
  453. SubMesh->Get_Vertex_Count()
  454. );
  455. }
  456. }
  457. ShdDX8RendererNodeClass::~ShdDX8RendererNodeClass()
  458. {
  459. unsigned stream_count=SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();
  460. unsigned n;
  461. for (n=0;n<stream_count;++n)
  462. {
  463. REF_PTR_RELEASE(VertexBuffers[n]);
  464. }
  465. delete[] VertexBuffers;
  466. VertexBuffers=NULL;
  467. REF_PTR_RELEASE(IndexBuffer);
  468. REF_PTR_RELEASE(Mesh);
  469. REF_PTR_RELEASE(SubMesh);
  470. REF_PTR_RELEASE(Container);
  471. }
  472. /***********************************************************************************************
  473. * ShdDX8RendererNodeClass::Render -- Render node
  474. *
  475. * INPUT: *
  476. * *
  477. * OUTPUT: *
  478. * *
  479. * WARNINGS: *
  480. * *
  481. * HISTORY: *
  482. * 4/20/2002 jp : Created
  483. * 6/02/2002 kjm : Added light environment handling
  484. *=============================================================================================*/
  485. void ShdDX8RendererNodeClass::Render(RenderInfoClass& rinfo)
  486. {
  487. RenderInfo=&rinfo;
  488. if (rinfo.light_environment)
  489. {
  490. memcpy(&LightEnvironment,rinfo.light_environment,sizeof(LightEnvironmentClass));
  491. }
  492. else {
  493. LightEnvironment.Reset(Vector3(0.0f,0.0f,0.0f),Vector3(0.0f,0.0f,0.0f));
  494. }
  495. Connect();
  496. }
  497. bool enable_rnd=true;
  498. void ShdDX8RendererNodeClass::Flush(int cur_pass)
  499. {
  500. WWASSERT(RenderInfo);
  501. // pass selection for this instance
  502. if (!SubMesh->Peek_Shader()->Pass_Selection(Mesh,RenderInfo,cur_pass))
  503. {
  504. return;
  505. }
  506. SNAPSHOT_SAY(("ShdDX8RendererNodeClass::Flush(%d) - %s\n",cur_pass,SubMesh->Get_Name()));
  507. // BEGIN OF SKIN CODE
  508. if (SubMesh->Get_Flag(MeshGeometryClass::SKIN)) {
  509. DX8Wrapper::Set_Vertex_Buffer(NULL); // Free up the reference to the current vertex buffer
  510. // (in case it is the dynamic, which may have to be resized)
  511. unsigned vertex_count=SubMesh->Get_Vertex_Count();
  512. unsigned stream_count=SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();
  513. WWASSERT(stream_count>0);
  514. // For now there are restrictions in vertex buffer format with skinning
  515. FVFInfoClass fi(dynamic_fvf_type);
  516. WWASSERT(SubMesh->Peek_Shader()->Get_Vertex_Size(0)==fi.Get_FVF_Size());
  517. DynamicVBAccessClass vb(
  518. SubMesh->Is_Sorting() ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8,
  519. dynamic_fvf_type,
  520. vertex_count);
  521. SNAPSHOT_SAY(("DynamicVBAccess - %s - %d vertices\n",SubMesh->Is_Sorting() ? "sorting" : "non-sorting",vertex_count));
  522. if (_TempVertexBuffer.Length() < (int)vertex_count) _TempVertexBuffer.Resize(vertex_count);
  523. if (_TempNormalBuffer.Length() < (int)vertex_count) _TempNormalBuffer.Resize(vertex_count);
  524. Vector3* loc=&(_TempVertexBuffer[0]);
  525. Vector3* norm=&(_TempNormalBuffer[0]);
  526. WWASSERT(Mesh->Get_Container());
  527. SubMesh->Get_Deformed_Vertices(loc,norm,Mesh->Get_Container()->Get_HTree());
  528. // Compose the vertex and index buffers
  529. VertexStreamStruct vss;
  530. vss.Locations=loc;
  531. vss.Normals=norm;
  532. for (unsigned stage=0;stage<MAX_TEXTURE_STAGES;++stage)
  533. {
  534. vss.UV[stage]=SubMesh->Get_UV_Array(stage);
  535. }
  536. vss.DiffuseInt=SubMesh->Get_Diffuse_Array();
  537. vss.S=SubMesh->Get_Tangent_Basis_S_Array();
  538. vss.T=SubMesh->Get_Tangent_Basis_T_Array();
  539. vss.SxT=SubMesh->Get_Tangent_Basis_SxT_Array();
  540. WWASSERT(stream_count==1);
  541. {
  542. DynamicVBAccessClass::WriteLockClass vlock(&vb);
  543. SubMesh->Peek_Shader()->Copy_Vertex_Stream
  544. (
  545. 0,//stream
  546. vlock.Get_Formatted_Vertex_Array(),
  547. vss,
  548. SubMesh->Get_Vertex_Count()
  549. );
  550. }
  551. DX8Wrapper::Set_Vertex_Buffer(vb);//stream 0
  552. DX8Wrapper::Set_Index_Buffer(IndexBuffer,0);
  553. DX8Wrapper::Set_Transform(D3DTS_WORLD,Matrix3D(true));//Mesh->Get_Transform());
  554. DX8Wrapper::Set_Light_Environment(&LightEnvironment);
  555. SubMesh->Peek_Shader()->Apply_Instance(cur_pass, *RenderInfo);
  556. if (SubMesh->Is_Sorting()) {
  557. SortingRendererClass::Insert_Triangles
  558. (
  559. 0,
  560. SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
  561. 0,
  562. SubMesh->Get_Vertex_Count()
  563. );
  564. }
  565. else {
  566. DX8Wrapper::Draw_Triangles
  567. (
  568. 0,
  569. SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
  570. 0,
  571. SubMesh->Get_Vertex_Count()
  572. );
  573. }
  574. return;
  575. }
  576. // END OF SKIN CODE
  577. for (unsigned n=0;n<SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();++n)
  578. {
  579. DX8Wrapper::Set_Vertex_Buffer(VertexBuffers[n],n);
  580. }
  581. DX8Wrapper::Set_Index_Buffer(IndexBuffer,0);
  582. DX8Wrapper::Set_Transform(D3DTS_WORLD,Mesh->Get_Transform());
  583. DX8Wrapper::Set_Light_Environment(&LightEnvironment);
  584. SubMesh->Peek_Shader()->Apply_Instance(cur_pass, *RenderInfo);
  585. if (SubMesh->Is_Sorting()) {
  586. SortingRendererClass::Insert_Triangles
  587. (
  588. 0,
  589. SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
  590. 0,
  591. SubMesh->Get_Vertex_Count()
  592. );
  593. }
  594. else {
  595. DX8Wrapper::Draw_Triangles
  596. (
  597. 0,
  598. SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
  599. 0,
  600. SubMesh->Get_Vertex_Count()
  601. );
  602. }
  603. }
  604. void ShdDX8RendererNodeClass::Apply_Shared_Shader_Settings(ShdRendererNodeClass* prev_node, int pass)
  605. {
  606. // If the previously set shader is not the same type as this, we need to set
  607. // all render states to default state.
  608. if (prev_node) {
  609. ShdDX8RendererNodeClass* prev_dx8_node=static_cast<ShdDX8RendererNodeClass*>(prev_node); // Illegal to pass another type!
  610. ShdInterfaceClass* shd=prev_dx8_node->SubMesh->Peek_Shader();
  611. if (shd->Get_Class_ID()!=SubMesh->Peek_Shader()->Get_Class_ID()) {
  612. DX8Wrapper::Apply_Default_State();
  613. }
  614. }
  615. SubMesh->Peek_Shader()->Apply_Shared(pass, *RenderInfo);
  616. }