render2d.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /*
  2. ** Command & Conquer Generals(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/render2d.cpp $*
  25. * *
  26. * $Author:: Jani_p $Modtime:: 1/24/01 3:54p $*
  27. * *
  28. * $Revision:: 38 $*
  29. * *
  30. *---------------------------------------------------------------------------------------------*
  31. * Functions: *
  32. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  33. #include "render2d.h"
  34. #include "mutex.h"
  35. #include "ww3d.h"
  36. #include "refcount.h"
  37. #include "font3d.h"
  38. #include "rect.h"
  39. #include "texture.h"
  40. #include "matrix4.h"
  41. #include "matrix3d.h"
  42. #include "dx8wrapper.h"
  43. #include "dx8indexbuffer.h"
  44. #include "dx8vertexbuffer.h"
  45. #include "sortingrenderer.h"
  46. #include "vertmaterial.h"
  47. #include "dx8fvf.h"
  48. #include "dx8caps.h"
  49. #include "wwprofile.h"
  50. #include "wwmemlog.h"
  51. #include "assetmgr.h"
  52. RectClass Render2DClass::ScreenResolution( 0,0,0,0 );
  53. /*
  54. ** Render2DClass
  55. */
  56. Render2DClass::Render2DClass( TextureClass* tex ) :
  57. CoordinateScale( 1, 1 ),
  58. CoordinateOffset( 0, 0 ),
  59. Texture(0),
  60. ZValue(0),
  61. IsHidden( false ),
  62. IsGrayScale (false)
  63. {
  64. Set_Texture( tex );
  65. Shader = Get_Default_Shader();
  66. return ;
  67. }
  68. Render2DClass::~Render2DClass()
  69. {
  70. REF_PTR_RELEASE(Texture);
  71. }
  72. ShaderClass
  73. Render2DClass::Get_Default_Shader( void )
  74. {
  75. ShaderClass shader;
  76. shader.Set_Depth_Mask( ShaderClass::DEPTH_WRITE_DISABLE );
  77. shader.Set_Depth_Compare( ShaderClass::PASS_ALWAYS );
  78. shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA );
  79. shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_SRC_ALPHA );
  80. shader.Set_Fog_Func( ShaderClass::FOG_DISABLE );
  81. shader.Set_Primary_Gradient( ShaderClass::GRADIENT_MODULATE );
  82. shader.Set_Texturing( ShaderClass::TEXTURING_ENABLE );
  83. return shader;
  84. }
  85. void Render2DClass::Reset(void)
  86. {
  87. Vertices.Delete_All( false );
  88. UVCoordinates.Delete_All( false );
  89. Colors.Delete_All( false );
  90. Indices.Delete_All( false );
  91. Update_Bias(); // Keep the bias updated
  92. }
  93. void Render2DClass::Set_Texture(TextureClass* tex)
  94. {
  95. REF_PTR_SET(Texture,tex);
  96. }
  97. void Render2DClass::Set_Texture( const char * filename)
  98. {
  99. TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture( filename, TextureClass::MIP_LEVELS_1 );
  100. Set_Texture( tex );
  101. if ( tex != NULL ) {
  102. SET_REF_OWNER( tex );
  103. tex->Release_Ref();
  104. }
  105. }
  106. /**added for generals to draw disabled button states - MW*/
  107. void Render2DClass::Enable_Grayscale(bool b)
  108. {
  109. IsGrayScale = b;
  110. }
  111. void Render2DClass::Enable_Alpha(bool b)
  112. {
  113. IsGrayScale = false;
  114. if (b) {
  115. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA );
  116. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_SRC_ALPHA );
  117. }
  118. else {
  119. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_ONE);
  120. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ZERO );
  121. }
  122. }
  123. void Render2DClass::Enable_Additive(bool b)
  124. {
  125. IsGrayScale = false;
  126. if (b) {
  127. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ONE );
  128. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_ONE );
  129. }
  130. else {
  131. Shader.Set_Src_Blend_Func( ShaderClass::SRCBLEND_ONE);
  132. Shader.Set_Dst_Blend_Func( ShaderClass::DSTBLEND_ZERO );
  133. }
  134. }
  135. void Render2DClass::Enable_Texturing(bool b)
  136. {
  137. if (b) {
  138. Shader.Set_Texturing( ShaderClass::TEXTURING_ENABLE );
  139. }
  140. else {
  141. Shader.Set_Texturing( ShaderClass::TEXTURING_DISABLE );
  142. }
  143. }
  144. void Render2DClass::Set_Coordinate_Range( const RectClass & range )
  145. {
  146. // default range is (-1,1)-(1,-1)
  147. CoordinateScale.X = 2 / range.Width();
  148. CoordinateScale.Y = -2 / range.Height();
  149. CoordinateOffset.X = -(CoordinateScale.X * range.Left) - 1;
  150. CoordinateOffset.Y = -(CoordinateScale.Y * range.Top) + 1;
  151. Update_Bias();
  152. }
  153. void Render2DClass::Update_Bias( void )
  154. {
  155. BiasedCoordinateOffset = CoordinateOffset;
  156. if ( WW3D::Is_Screen_UV_Biased() ) { // Global bais setting
  157. Vector2 bais_add( -0.5f ,-0.5f ); // offset by -0.5,-0.5 in pixels
  158. // Convert from pixels to (-1,1)-(1,-1) units
  159. bais_add.X = bais_add.X / (Get_Screen_Resolution().Width() * 0.5f);
  160. bais_add.Y = bais_add.Y / (Get_Screen_Resolution().Height() * -0.5f);
  161. BiasedCoordinateOffset += bais_add;
  162. }
  163. }
  164. #if 0
  165. Vector2 Render2DClass::Convert_Vert( const Vector2 & v )
  166. {
  167. Vector2 out;
  168. // Convert to (-1,1)-(1,-1)
  169. out.X = v.X * CoordinateScale.X + CoordinateOffset.X;
  170. out.Y = v.Y * CoordinateScale.Y + CoordinateOffset.Y;
  171. // Convert to pixels
  172. out.X = (out.X + 1.0f) * (Get_Screen_Resolution().Width() * 0.5f);
  173. out.Y = (out.Y - 1.0f) * (Get_Screen_Resolution().Height() * -0.5f);
  174. // Round to nearest pixel
  175. out.X = WWMath::Floor( out.X + 0.5f );
  176. out.Y = WWMath::Floor( out.Y + 0.5f );
  177. // Bias
  178. if ( WW3D::Is_Screen_UV_Biased() ) { // Global bais setting
  179. out.X -= 0.5f;
  180. out.Y -= 0.5f;
  181. }
  182. // Convert back to (-1,1)-(1,-1)
  183. out.X = out.X / (Get_Screen_Resolution().Width() * 0.5f) - 1.0f;
  184. out.Y = out.Y / (Get_Screen_Resolution().Height() * -0.5f) + 1.0f;
  185. return out;
  186. }
  187. #else
  188. /*
  189. ** Convert Vert must convert from the convention defined by Set_Coordinate_Range
  190. ** into the convention (-1,1)-(1,-1), which is needed by the renderer.
  191. // NOPE ** In addition, it rounds all coordinates off to the nearest pixel
  192. ** Also, it offsets the coordinates as need for Screen_UV_Bias
  193. */
  194. void Render2DClass::Convert_Vert( Vector2 & vert_out, const Vector2 & vert_in )
  195. {
  196. // Convert to (-1,1)-(1,-1)
  197. vert_out.X = vert_in.X * CoordinateScale.X + BiasedCoordinateOffset.X;
  198. vert_out.Y = vert_in.Y * CoordinateScale.Y + BiasedCoordinateOffset.Y;
  199. }
  200. void Render2DClass::Convert_Vert( Vector2 & vert_out, float x_in, float y_in )
  201. {
  202. // Convert to (-1,1)-(1,-1)
  203. vert_out.X = x_in * CoordinateScale.X + BiasedCoordinateOffset.X;
  204. vert_out.Y = y_in * CoordinateScale.Y + BiasedCoordinateOffset.Y;
  205. }
  206. #endif
  207. void Render2DClass::Move( const Vector2 & move ) // Move all verts
  208. {
  209. Vector2 scaled_move;
  210. scaled_move.X = move.X * CoordinateScale.X;
  211. scaled_move.Y = move.Y * CoordinateScale.Y;
  212. for ( int i = 0; i < Vertices.Count(); i++ ) {
  213. Vertices[i] += scaled_move;
  214. }
  215. }
  216. /*
  217. ** Internal Add Quad Elements
  218. ** Caller must mutex lock
  219. */
  220. void Render2DClass::Internal_Add_Quad_Vertices( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3 )
  221. {
  222. Vector2 * verts = Vertices.Add_Multiple( 4 );
  223. Convert_Vert( *verts++, v0 );
  224. Convert_Vert( *verts++, v1 );
  225. Convert_Vert( *verts++, v2 );
  226. Convert_Vert( *verts , v3 );
  227. }
  228. void Render2DClass::Internal_Add_Quad_Vertices( const RectClass & screen )
  229. {
  230. Vector2 * verts = Vertices.Add_Multiple( 4 );
  231. Convert_Vert( *verts++, screen.Left, screen.Top );
  232. Convert_Vert( *verts++, screen.Left, screen.Bottom );
  233. Convert_Vert( *verts++, screen.Right, screen.Top );
  234. Convert_Vert( *verts, screen.Right, screen.Bottom );
  235. }
  236. void Render2DClass::Internal_Add_Quad_UVs( const RectClass & uv )
  237. {
  238. Vector2 * uvs = UVCoordinates.Add_Multiple( 4 );
  239. uvs->X = uv.Left; uvs->Y = uv.Top; uvs++;
  240. uvs->X = uv.Left; uvs->Y = uv.Bottom; uvs++;
  241. uvs->X = uv.Right; uvs->Y = uv.Top; uvs++;
  242. uvs->X = uv.Right; uvs->Y = uv.Bottom;
  243. }
  244. void Render2DClass::Internal_Add_Quad_Colors( unsigned long color )
  245. {
  246. unsigned long * colors = Colors.Add_Multiple( 4 );
  247. *colors++ = color;
  248. *colors++ = color;
  249. *colors++ = color;
  250. *colors = color;
  251. }
  252. void Render2DClass::Internal_Add_Quad_VColors( unsigned long color1, unsigned long color2 )
  253. {
  254. unsigned long * colors = Colors.Add_Multiple( 4 );
  255. *colors++ = color1;
  256. *colors++ = color2;
  257. *colors++ = color1;
  258. *colors = color2;
  259. }
  260. void Render2DClass::Internal_Add_Quad_HColors( unsigned long color1, unsigned long color2 )
  261. {
  262. unsigned long * colors = Colors.Add_Multiple( 4 );
  263. *colors++ = color1;
  264. *colors++ = color1;
  265. *colors++ = color2;
  266. *colors = color2;
  267. }
  268. void Render2DClass::Internal_Add_Quad_Indicies( int start_vert_index, bool backfaced )
  269. {
  270. unsigned short * indices = Indices.Add_Multiple( 6 );
  271. if (backfaced ^ (CoordinateScale.X * CoordinateScale.Y > 0)) {
  272. *indices++ = start_vert_index + 1;
  273. *indices++ = start_vert_index + 0;
  274. *indices++ = start_vert_index + 2;
  275. *indices++ = start_vert_index + 1;
  276. *indices++ = start_vert_index + 2;
  277. *indices = start_vert_index + 3;
  278. } else {
  279. *indices++ = start_vert_index + 0;
  280. *indices++ = start_vert_index + 1;
  281. *indices++ = start_vert_index + 2;
  282. *indices++ = start_vert_index + 2;
  283. *indices++ = start_vert_index + 1;
  284. *indices = start_vert_index + 3;
  285. }
  286. }
  287. void Render2DClass::Add_Quad( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, const RectClass & uv, unsigned long color )
  288. {
  289. Internal_Add_Quad_Indicies( Vertices.Count() );
  290. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  291. Internal_Add_Quad_UVs( uv );
  292. Internal_Add_Quad_Colors( color );
  293. }
  294. void Render2DClass::Add_Quad_Backfaced( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, const RectClass & uv, unsigned long color )
  295. {
  296. Internal_Add_Quad_Indicies( Vertices.Count(), true );
  297. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  298. Internal_Add_Quad_UVs( uv );
  299. Internal_Add_Quad_Colors( color );
  300. }
  301. void Render2DClass::Add_Quad_VGradient( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, const RectClass & uv, unsigned long top_color, unsigned long bottom_color )
  302. {
  303. Internal_Add_Quad_Indicies( Vertices.Count() );
  304. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  305. Internal_Add_Quad_UVs( uv );
  306. Internal_Add_Quad_VColors( top_color, bottom_color );
  307. }
  308. void Render2DClass::Add_Quad_HGradient( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, const RectClass & uv, unsigned long left_color, unsigned long right_color )
  309. {
  310. Internal_Add_Quad_Indicies( Vertices.Count() );
  311. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  312. Internal_Add_Quad_UVs( uv );
  313. Internal_Add_Quad_HColors( left_color, right_color );
  314. }
  315. void Render2DClass::Add_Quad_VGradient( const RectClass & screen, unsigned long top_color, unsigned long bottom_color )
  316. {
  317. Internal_Add_Quad_Indicies( Vertices.Count() );
  318. Internal_Add_Quad_Vertices( screen );
  319. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  320. Internal_Add_Quad_VColors( top_color, bottom_color );
  321. }
  322. void Render2DClass::Add_Quad_HGradient( const RectClass & screen, unsigned long left_color, unsigned long right_color )
  323. {
  324. Internal_Add_Quad_Indicies( Vertices.Count() );
  325. Internal_Add_Quad_Vertices( screen );
  326. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  327. Internal_Add_Quad_HColors( left_color, right_color );
  328. }
  329. void Render2DClass::Add_Quad( const RectClass & screen, const RectClass & uv, unsigned long color )
  330. {
  331. Internal_Add_Quad_Indicies( Vertices.Count() );
  332. Internal_Add_Quad_Vertices( screen );
  333. Internal_Add_Quad_UVs( uv );
  334. Internal_Add_Quad_Colors( color );
  335. }
  336. void Render2DClass::Add_Quad( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & v3, unsigned long color )
  337. {
  338. Internal_Add_Quad_Indicies( Vertices.Count() );
  339. Internal_Add_Quad_Vertices( v0, v1, v2, v3 );
  340. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  341. Internal_Add_Quad_Colors( color );
  342. }
  343. void Render2DClass::Add_Quad( const RectClass & screen, unsigned long color )
  344. {
  345. Internal_Add_Quad_Indicies( Vertices.Count() );
  346. Internal_Add_Quad_Vertices( screen );
  347. Internal_Add_Quad_UVs( RectClass( 0,0,1,1 ) );
  348. Internal_Add_Quad_Colors( color );
  349. }
  350. /*
  351. ** Add Tri
  352. */
  353. void Render2DClass::Add_Tri( const Vector2 & v0, const Vector2 & v1, const Vector2 & v2, const Vector2 & uv0, const Vector2 & uv1, const Vector2 & uv2, unsigned long color )
  354. {
  355. int old_vert_count = Vertices.Count();
  356. int new_vert_count = old_vert_count + 3;
  357. int new_index_count = Indices.Count() + 3;
  358. // Add the verticies (translated to new coordinates)
  359. #if 0
  360. Vertices.Add( Convert_Vert( v0 ), new_vert_count );
  361. Vertices.Add( Convert_Vert( v1 ), new_vert_count );
  362. Vertices.Add( Convert_Vert( v2 ), new_vert_count );
  363. #else
  364. Vector2 * verts = Vertices.Add_Multiple( 3 );
  365. Convert_Vert( *verts++, v0 );
  366. Convert_Vert( *verts++, v1 );
  367. Convert_Vert( *verts , v2 );
  368. #endif
  369. // Add the uv coordinates
  370. UVCoordinates.Add( uv0, new_vert_count );
  371. UVCoordinates.Add( uv1, new_vert_count );
  372. UVCoordinates.Add( uv2, new_vert_count );
  373. // Add the colors
  374. Colors.Add( color, new_vert_count );
  375. Colors.Add( color, new_vert_count );
  376. Colors.Add( color, new_vert_count );
  377. // Add the faces
  378. Indices.Add( old_vert_count + 0, new_index_count );
  379. Indices.Add( old_vert_count + 1, new_index_count );
  380. Indices.Add( old_vert_count + 2, new_index_count );
  381. }
  382. void Render2DClass::Add_Line( const Vector2 & a, const Vector2 & b, float width, unsigned long color )
  383. {
  384. Add_Line( a, b, width, RectClass( 0,0,1,1 ), color );
  385. }
  386. void Render2DClass::Add_Line( const Vector2 & a, const Vector2 & b, float width, const RectClass & uv, unsigned long color )
  387. {
  388. Vector2 corner_offset = a - b; // get line relative to b
  389. float temp = corner_offset.X; // Rotate 90
  390. corner_offset.X = corner_offset.Y;
  391. corner_offset.Y = -temp;
  392. corner_offset.Normalize(); // scale to length width/2
  393. corner_offset *= width / 2;
  394. Add_Quad( a - corner_offset, a + corner_offset, b - corner_offset, b + corner_offset, uv, color );
  395. //Add_Quad_HGradient(RectClass( a.X -corner_offset.X ,a.Y,b.X,b.Y ), color, color2);
  396. //Add_Quad_HGradient( const RectClass & screen, unsigned long left_color, unsigned long right_color );
  397. }
  398. void Render2DClass::Add_Line( const Vector2 & a, const Vector2 & b, float width, unsigned long color, unsigned long color2 )
  399. {
  400. Add_Line( a, b, width, RectClass( 0,0,1,1 ), color, color2 );
  401. }
  402. void Render2DClass::Add_Line( const Vector2 & a, const Vector2 & b, float width, const RectClass & uv, unsigned long color , unsigned long color2)
  403. {
  404. Vector2 corner_offset = a - b; // get line relative to b
  405. float temp = corner_offset.X; // Rotate 90
  406. corner_offset.X = corner_offset.Y;
  407. corner_offset.Y = -temp;
  408. corner_offset.Normalize(); // scale to length width/2
  409. corner_offset *= width / 2;
  410. Add_Quad_HGradient( a - corner_offset, a + corner_offset, b - corner_offset, b + corner_offset, uv, color,color2);
  411. //Add_Quad_HGradient(RectClass( a.X -corner_offset.X ,a.Y,b.X,b.Y ), color, color2);
  412. }
  413. void Render2DClass::Add_Rect( const RectClass & rect, float border_width, uint32 border_color, uint32 fill_color )
  414. {
  415. //
  416. // First add the outline
  417. //
  418. if( border_width > 0 )
  419. Add_Outline( rect, border_width, border_color );
  420. //
  421. // Next, fill the contents
  422. //
  423. RectClass fill_rect = rect;
  424. if( border_width > 0 )
  425. {
  426. fill_rect.Left += border_width + 1;
  427. fill_rect.Top += border_width + 1;
  428. fill_rect.Right -= border_width - 1;
  429. fill_rect.Bottom -= border_width - 1;
  430. }
  431. Add_Quad (fill_rect, fill_color);
  432. return ;
  433. }
  434. void Render2DClass::Add_Outline( const RectClass & rect, float width, unsigned long color )
  435. {
  436. Add_Outline( rect, width, RectClass( 0,0,1,1 ), color );
  437. }
  438. void Render2DClass::Add_Outline( const RectClass & rect, float width, const RectClass & uv, unsigned long color )
  439. {
  440. //
  441. // Pretty straight forward, simply add the four side of the rectangle as lines.
  442. //
  443. /** @todo colin, I had to tweak these to get precise line drawing, as we want
  444. the UV bias on, but it just isn't lining up */
  445. Add_Line (Vector2 (rect.Left + 1, rect.Bottom), Vector2 (rect.Left + 1, rect.Top + 1), width, color);
  446. Add_Line (Vector2 (rect.Left, rect.Top + 1), Vector2 (rect.Right - 1, rect.Top + 1), width, color);
  447. Add_Line (Vector2 (rect.Right, rect.Top), Vector2 (rect.Right, rect.Bottom - 1), width, color);
  448. Add_Line (Vector2 (rect.Right, rect.Bottom), Vector2 (rect.Left + 1, rect.Bottom), width, color);
  449. }
  450. void Render2DClass::Render(void)
  451. {
  452. if ( !Indices.Count() || IsHidden) {
  453. return;
  454. }
  455. // save the view and projection matrices since we're nuking them
  456. Matrix4 view,proj;
  457. Matrix4 identity(true);
  458. DX8Wrapper::Get_Transform(D3DTS_VIEW,view);
  459. DX8Wrapper::Get_Transform(D3DTS_PROJECTION,proj);
  460. //
  461. // Configure the viewport for entire screen
  462. //
  463. D3DVIEWPORT8 vp = { 0 };
  464. vp.X = (DWORD)ScreenResolution.Left;
  465. vp.Y = (DWORD)ScreenResolution.Top;
  466. vp.Width = (DWORD)ScreenResolution.Width ();
  467. vp.Height = (DWORD)ScreenResolution.Height ();
  468. vp.MinZ = 0;
  469. vp.MaxZ = 1;
  470. DX8Wrapper::Set_Viewport(&vp);
  471. DX8Wrapper::Set_Texture(0,Texture);
  472. VertexMaterialClass *vm=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  473. DX8Wrapper::Set_Material(vm);
  474. REF_PTR_RELEASE(vm);
  475. DX8Wrapper::Set_World_Identity();
  476. DX8Wrapper::Set_View_Identity();
  477. DX8Wrapper::Set_Transform(D3DTS_PROJECTION,identity);
  478. DynamicVBAccessClass vb(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,Vertices.Count());
  479. {
  480. DynamicVBAccessClass::WriteLockClass Lock(&vb);
  481. const FVFInfoClass &fi=vb.FVF_Info();
  482. unsigned char *vb=(unsigned char*)Lock.Get_Formatted_Vertex_Array();
  483. int i;
  484. for (i=0; i<Vertices.Count(); i++)
  485. {
  486. Vector3 temp(Vertices[i].X,Vertices[i].Y,ZValue);
  487. *(Vector3*)(vb+fi.Get_Location_Offset())=temp;
  488. *(unsigned int*)(vb+fi.Get_Diffuse_Offset())=Colors[i];
  489. *(Vector2*)(vb+fi.Get_Tex_Offset(0))=UVCoordinates[i];
  490. vb+=fi.Get_FVF_Size();
  491. }
  492. }
  493. DynamicIBAccessClass ib(BUFFER_TYPE_DYNAMIC_DX8,Indices.Count());
  494. {
  495. DynamicIBAccessClass::WriteLockClass Lock(&ib);
  496. unsigned short *mem=Lock.Get_Index_Array();
  497. for (int i=0; i<Indices.Count(); i++)
  498. mem[i]=Indices[i];
  499. }
  500. DX8Wrapper::Set_Vertex_Buffer(vb);
  501. DX8Wrapper::Set_Index_Buffer(ib,0);
  502. if (IsGrayScale)
  503. { //special case added to draw grayscale non-alpha blended images.
  504. DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
  505. DX8Wrapper::Apply_Render_State_Changes(); //force update of all regular W3D states.
  506. if (DX8Caps::Support_DOT3())
  507. { //Override W3D states with customizations for grayscale
  508. DX8Wrapper::Set_DX8_Render_State(D3DRS_TEXTUREFACTOR, 0x80A5CA8E);
  509. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG0, D3DTA_TFACTOR | D3DTA_ALPHAREPLICATE);
  510. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  511. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR | D3DTA_ALPHAREPLICATE);
  512. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD);
  513. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
  514. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
  515. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
  516. }
  517. else
  518. { //doesn't have DOT3 blend mode so fake it another way.
  519. DX8Wrapper::Set_DX8_Render_State(D3DRS_TEXTUREFACTOR, 0x60606060);
  520. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  521. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
  522. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  523. }
  524. }
  525. else
  526. DX8Wrapper::Set_Shader(Shader);
  527. DX8Wrapper::Draw_Triangles(0,Indices.Count()/3,0,Vertices.Count());
  528. // SphereClass sphere(Vector3(0.0f,0.0f,0.0f),0.0f);
  529. // SortingRendererClass::Insert_Triangles(sphere,0,Indices.Count()/3,0,Vertices.Count());
  530. DX8Wrapper::Set_Transform(D3DTS_VIEW,view);
  531. DX8Wrapper::Set_Transform(D3DTS_PROJECTION,proj);
  532. if (IsGrayScale)
  533. ShaderClass::Invalidate(); //force both stages to be reset.
  534. }
  535. /*
  536. ** Render2DTextClass
  537. */
  538. Render2DTextClass::Render2DTextClass(Font3DInstanceClass *font) :
  539. Location(0.0f,0.0f),
  540. Cursor(0.0f,0.0f),
  541. Font(NULL),
  542. WrapWidth(0),
  543. ClipRect(0, 0, 0, 0),
  544. IsClippedEnabled(false)
  545. {
  546. Set_Coordinate_Range( RectClass( -320, -240, 320, 240 ) );
  547. Set_Font( font );
  548. Reset();
  549. }
  550. Render2DTextClass::~Render2DTextClass()
  551. {
  552. REF_PTR_RELEASE(Font);
  553. }
  554. void Render2DTextClass::Reset(void)
  555. {
  556. Render2DClass::Reset();
  557. Cursor = Location;
  558. WrapWidth = 0;
  559. DrawExtents = RectClass( 0,0,0,0 );
  560. TotalExtents = RectClass( 0,0,0,0 );
  561. ClipRect.Set (0, 0, 0, 0);
  562. IsClippedEnabled = false;
  563. }
  564. void Render2DTextClass::Set_Font( Font3DInstanceClass *font )
  565. {
  566. REF_PTR_SET(Font,font);
  567. if ( Font != NULL ) {
  568. Set_Texture( Font->Peek_Texture() );
  569. #define BLOCK_CHAR 0
  570. BlockUV = Font->Char_UV( BLOCK_CHAR );
  571. // Inset it a bit to be sure we have no edge problems
  572. BlockUV.Inflate( Vector2(-BlockUV.Width()/4, -BlockUV.Height()/4) );
  573. }
  574. }
  575. /*
  576. **
  577. */
  578. void Render2DTextClass::Draw_Char( WCHAR ch, unsigned long color )
  579. {
  580. float char_spacing = Font->Char_Spacing( ch );
  581. float char_height = Font->Char_Height();
  582. //
  583. // Check to see if this character is clipped
  584. //
  585. bool is_clipped = false;
  586. if ( IsClippedEnabled &&
  587. (Cursor.X < ClipRect.Left ||
  588. Cursor.X + char_spacing > ClipRect.Right ||
  589. Cursor.Y < ClipRect.Top ||
  590. Cursor.Y + char_height > ClipRect.Bottom))
  591. {
  592. is_clipped = true;
  593. }
  594. if ( ch != (WCHAR)' ' && !is_clipped ) {
  595. RectClass screen( Cursor.X, Cursor.Y, Cursor.X + Font->Char_Width(ch), Cursor.Y + char_height );
  596. Internal_Add_Quad_Indicies( Vertices.Count() );
  597. Internal_Add_Quad_Vertices( screen );
  598. Internal_Add_Quad_UVs( Font->Char_UV( ch ) );
  599. Internal_Add_Quad_Colors( color );
  600. DrawExtents += screen;
  601. TotalExtents += screen;
  602. }
  603. Cursor.X += char_spacing;
  604. }
  605. void Render2DTextClass::Draw_Text( const char * text, unsigned long color )
  606. {
  607. WWMEMLOG(MEM_GEOMETRY);
  608. WideStringClass wide(0,true);
  609. wide.Convert_From( text );
  610. Draw_Text( wide, color );
  611. }
  612. void Render2DTextClass::Draw_Text( const WCHAR * text, unsigned long color )
  613. {
  614. WWMEMLOG(MEM_GEOMETRY);
  615. // Reset the Extents
  616. DrawExtents = RectClass( Location, Location );
  617. if ( TotalExtents.Width() == 0 ) {
  618. TotalExtents = RectClass( Location, Location );
  619. }
  620. while (*text) {
  621. WCHAR ch = *text++;
  622. // Check to see if we need to move to a newline or not
  623. bool wrap = ( ch == (WCHAR)'\n' );
  624. // if the current char is a space, and the next word length puts us past our Width, wrap
  625. if ( ch == (WCHAR)' ' && WrapWidth > 0 ) {
  626. const WCHAR * word = text;
  627. float word_width = Font->Char_Spacing(ch);
  628. while ( (*word != (WCHAR)0) && (*word > (WCHAR)' ') ) {
  629. word_width += Font->Char_Spacing(*word++);
  630. }
  631. wrap = ( (Cursor.X + word_width) >= (Location.X + WrapWidth) );
  632. }
  633. if ( wrap ) {
  634. Cursor.Y += Font->Char_Height();
  635. Cursor.X = Location.X;
  636. } else {
  637. // Draw char at cursor, update cursor and extents
  638. Draw_Char( ch, color );
  639. }
  640. }
  641. }
  642. void Render2DTextClass::Draw_Block( const RectClass & screen, unsigned long color )
  643. {
  644. Internal_Add_Quad_Indicies( Vertices.Count() );
  645. Internal_Add_Quad_Vertices( screen );
  646. Internal_Add_Quad_UVs( BlockUV );
  647. Internal_Add_Quad_Colors( color );
  648. TotalExtents += screen;
  649. }
  650. Vector2 Render2DTextClass::Get_Text_Extents( const WCHAR * text )
  651. {
  652. Vector2 extent (0, Font->Char_Height());
  653. while (*text) {
  654. WCHAR ch = *text++;
  655. if ( ch != (WCHAR)'\n' ) {
  656. extent.X += Font->Char_Spacing( ch );
  657. }
  658. }
  659. return extent;
  660. }