W3DCustomEdging.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: W3DCustomEdging.cpp ////////////////////////////////////////////////
  24. //-----------------------------------------------------------------------------
  25. //
  26. // Westwood Studios Pacific.
  27. //
  28. // Confidential Information
  29. // Copyright (C) 2001 - All Rights Reserved
  30. //
  31. //-----------------------------------------------------------------------------
  32. //
  33. // Project: RTS3
  34. //
  35. // File name: W3DCustomEdging.cpp
  36. //
  37. // Created: John Ahlquist, May 2001
  38. //
  39. // Desc: Draw buffer to handle all the custom tile edges in a scene.
  40. //
  41. //-----------------------------------------------------------------------------
  42. //-----------------------------------------------------------------------------
  43. // Includes
  44. //-----------------------------------------------------------------------------
  45. #include "W3DDevice/GameClient/W3DCustomEdging.h"
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <assetmgr.h>
  49. #include <texture.h>
  50. #include "common/GlobalData.h"
  51. #include "common/RandomValue.h"
  52. #include "W3DDevice/GameClient/TerrainTex.h"
  53. #include "W3DDevice/GameClient/HeightMap.h"
  54. #include "W3DDevice/GameClient/W3DDynamicLight.h"
  55. #include "WW3D2/Camera.h"
  56. #include "WW3D2/DX8Wrapper.h"
  57. #include "WW3D2/DX8Renderer.h"
  58. #include "WW3D2/Mesh.h"
  59. #include "WW3D2/MeshMdl.h"
  60. //-----------------------------------------------------------------------------
  61. // Private Data
  62. //-----------------------------------------------------------------------------
  63. // A W3D shader that does alpha, texturing, tests zbuffer, doesn't update zbuffer.
  64. #define SC_ALPHA_DETAIL ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
  65. ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  66. ShaderClass::ALPHATEST_ENABLE, ShaderClass::CULL_MODE_DISABLE, \
  67. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  68. static ShaderClass detailAlphaTestShader(SC_ALPHA_DETAIL);
  69. #define SC_NO_ALPHA ( SHADE_CNST(ShaderClass::PASS_ALWAYS, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
  70. ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  71. ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
  72. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  73. static ShaderClass detailShader(SC_NO_ALPHA);
  74. #define SC_DETAIL_BLEND ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
  75. ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  76. ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, ShaderClass::DETAILCOLOR_SCALE, ShaderClass::DETAILALPHA_DISABLE) )
  77. static ShaderClass detailOpaqueShader(SC_DETAIL_BLEND);
  78. /*
  79. #define SC_ALPHA_MIRROR ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
  80. ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  81. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
  82. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  83. static ShaderClass mirrorAlphaShader(SC_ALPHA_DETAIL);
  84. // ShaderClass::PASS_ALWAYS,
  85. #define SC_ALPHA_2D ( SHADE_CNST(PASS_ALWAYS, DEPTH_WRITE_DISABLE, COLOR_WRITE_ENABLE, \
  86. SRCBLEND_SRC_ALPHA, DSTBLEND_ONE_MINUS_SRC_ALPHA, FOG_DISABLE, GRADIENT_DISABLE, \
  87. SECONDARY_GRADIENT_DISABLE, TEXTURING_ENABLE, DETAILCOLOR_DISABLE, DETAILALPHA_DISABLE, \
  88. ALPHATEST_DISABLE, CULL_MODE_ENABLE, DETAILCOLOR_DISABLE, DETAILALPHA_DISABLE) )
  89. ShaderClass ShaderClass::_PresetAlpha2DShader(SC_ALPHA_2D);
  90. */
  91. //-----------------------------------------------------------------------------
  92. // Private Functions
  93. //-----------------------------------------------------------------------------
  94. //=============================================================================
  95. // W3DCustomEdging::loadEdgingsInVertexAndIndexBuffers
  96. //=============================================================================
  97. /** Loads the trees into the vertex buffer for drawing. */
  98. //=============================================================================
  99. void W3DCustomEdging::loadEdgingsInVertexAndIndexBuffers(WorldHeightMap *pMap, Int minX, Int maxX, Int minY, Int maxY)
  100. {
  101. if (!m_indexEdging || !m_vertexEdging || !m_initialized) {
  102. return;
  103. }
  104. if (!m_anythingChanged) {
  105. return;
  106. }
  107. m_anythingChanged = false;
  108. m_curNumEdgingVertices = 0;
  109. m_curNumEdgingIndices = 0;
  110. VertexFormatXYZDUV2 *vb;
  111. UnsignedShort *ib;
  112. // Lock the buffers.
  113. DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexEdging);
  114. DX8VertexBufferClass::WriteLockClass lockVtxBuffer(m_vertexEdging);
  115. vb=(VertexFormatXYZDUV2*)lockVtxBuffer.Get_Vertex_Array();
  116. ib = lockIdxBuffer.Get_Index_Array();
  117. UnsignedShort *curIb = ib;
  118. VertexFormatXYZDUV2 *curVb = vb;
  119. if (minX<0) minX = 0;
  120. if (minY<0) minY = 0;
  121. if (maxX >= pMap->getXExtent()) maxX = pMap->getXExtent()-1;
  122. if (maxY >= pMap->getYExtent()) maxY = pMap->getYExtent()-1;
  123. Int row;
  124. Int column;
  125. try {
  126. for (row=minY; row<maxY-1; row++) {
  127. for (column = minX; column < maxX-1; column++) {
  128. Int cellNdx = column+row*pMap->getXExtent();
  129. Int blend = pMap->m_blendTileNdxes[cellNdx];
  130. if (blend == 0) continue; // no blend.
  131. if (pMap->m_blendedTiles[blend].customBlendEdgeClass<0) continue; // alpha blend.
  132. Int i, j;
  133. Real uOffset;
  134. Real vOffset;
  135. if (pMap->m_blendedTiles[blend].horiz) {
  136. uOffset = 0;
  137. vOffset = 0.25f * (1 + (row&1));
  138. if (pMap->m_blendedTiles[blend].inverted) {
  139. uOffset = 0.75f;
  140. }
  141. } else if (pMap->m_blendedTiles[blend].vert) {
  142. vOffset = 0.75;
  143. uOffset = 0.25f * (1 + (column&1));
  144. if (pMap->m_blendedTiles[blend].inverted) {
  145. vOffset = 0.0f;
  146. }
  147. } else if (pMap->m_blendedTiles[blend].rightDiagonal) {
  148. if (pMap->m_blendedTiles[blend].longDiagonal) {
  149. vOffset = 0.25;
  150. uOffset = 0.5;
  151. if (pMap->m_blendedTiles[blend].inverted) {
  152. uOffset = 0.5f;
  153. vOffset = 0.5f;
  154. }
  155. } else {
  156. vOffset = .75;
  157. uOffset = 0;
  158. if (pMap->m_blendedTiles[blend].inverted) {
  159. uOffset = 0.0f;
  160. vOffset = 0.0f;
  161. }
  162. }
  163. } else if (pMap->m_blendedTiles[blend].leftDiagonal) {
  164. if (pMap->m_blendedTiles[blend].longDiagonal) {
  165. uOffset = 0.25f;
  166. vOffset = 0.25f;
  167. if (pMap->m_blendedTiles[blend].inverted) {
  168. uOffset = 0.25f;
  169. vOffset = 0.5f;
  170. }
  171. } else {
  172. vOffset = 0.75;
  173. uOffset = 0.75f;
  174. if (pMap->m_blendedTiles[blend].inverted) {
  175. uOffset = 0.75f;
  176. vOffset = 0.0f;
  177. }
  178. }
  179. } else {
  180. continue;
  181. }
  182. Region2D range;
  183. pMap->getUVForBlend(pMap->m_blendedTiles[blend].customBlendEdgeClass, &range);
  184. uOffset = range.lo.x + range.width()*uOffset;
  185. vOffset = range.lo.y + range.height()*vOffset;
  186. UnsignedByte alpha[4];
  187. float UA[4], VA[4];
  188. Bool flipForBlend;
  189. pMap->getAlphaUVData(column-pMap->getDrawOrgX(), row-pMap->getDrawOrgY(), UA, VA, alpha, &flipForBlend, false);
  190. Int startVertex = m_curNumEdgingVertices;
  191. for (j=0; j<2; j++) {
  192. for (i=0; i<2; i++) {
  193. if (m_curNumEdgingVertices >= MAX_EDGE_VERTEX) return;
  194. cellNdx = column+i+(row+j)*pMap->getXExtent();
  195. Int diffuse = TheTerrainRenderObject->getStaticDiffuse(column+i, row+j);
  196. curVb->diffuse = 0x80000000 + (diffuse&0x00FFFFFF); // set alpha to 5b.
  197. Real theZ;
  198. theZ = ((float)pMap->getDataPtr()[cellNdx])*MAP_HEIGHT_SCALE;
  199. Real X = (column+i)*MAP_XY_FACTOR;
  200. Real Y = (row+j)*MAP_XY_FACTOR;
  201. curVb->u2 = uOffset + i*0.25f*range.width();
  202. curVb->v2 = vOffset + (1-j)*0.25f*range.height();
  203. Int ndx;
  204. if (j==0) ndx=i;
  205. if (j==1) ndx = 3-i;
  206. curVb->u1 = UA[ndx];
  207. curVb->v1 = VA[ndx];
  208. curVb->x = X;
  209. curVb->y = Y;
  210. curVb->z = theZ;
  211. curVb++;
  212. m_curNumEdgingVertices++;
  213. }
  214. }
  215. Int yOffset = 2;
  216. if (m_curNumEdgingIndices+6 > MAX_EDGE_INDEX) return;
  217. #ifdef FLIP_TRIANGLES // jba - reduces "diamonding" in some cases, not others. Better cliffs, though.
  218. if (flipForBlend) {
  219. *curIb++ = startVertex + 1;
  220. *curIb++ = startVertex + yOffset;
  221. *curIb++ = startVertex ;
  222. *curIb++ = startVertex + 1;
  223. *curIb++ = startVertex + 1+yOffset;
  224. *curIb++ = startVertex + yOffset;
  225. }
  226. else
  227. #endif
  228. {
  229. *curIb++ = startVertex;
  230. *curIb++ = startVertex + 1+yOffset;
  231. *curIb++ = startVertex + yOffset;
  232. *curIb++ = startVertex ;
  233. *curIb++ = startVertex + 1;
  234. *curIb++ = startVertex + 1+yOffset;
  235. }
  236. m_curNumEdgingIndices+=6;
  237. }
  238. }
  239. IndexBufferExceptionFunc();
  240. } catch(...) {
  241. IndexBufferExceptionFunc();
  242. }
  243. m_anythingChanged = false;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Public Functions
  247. //-----------------------------------------------------------------------------
  248. //=============================================================================
  249. // W3DCustomEdging::~W3DCustomEdging
  250. //=============================================================================
  251. /** Destructor. Releases w3d assets. */
  252. //=============================================================================
  253. W3DCustomEdging::~W3DCustomEdging(void)
  254. {
  255. freeEdgingBuffers();
  256. }
  257. //=============================================================================
  258. // W3DCustomEdging::W3DCustomEdging
  259. //=============================================================================
  260. /** Constructor. Sets m_initialized to true if it finds the w3d models it needs
  261. for the trees. */
  262. //=============================================================================
  263. W3DCustomEdging::W3DCustomEdging(void)
  264. {
  265. m_initialized = false;
  266. m_vertexEdging = NULL;
  267. m_indexEdging = NULL;
  268. clearAllEdging();
  269. allocateEdgingBuffers();
  270. m_initialized = true;
  271. }
  272. //=============================================================================
  273. // W3DCustomEdging::freeEdgingBuffers
  274. //=============================================================================
  275. /** Frees the index and vertex buffers. */
  276. //=============================================================================
  277. void W3DCustomEdging::freeEdgingBuffers(void)
  278. {
  279. REF_PTR_RELEASE(m_vertexEdging);
  280. REF_PTR_RELEASE(m_indexEdging);
  281. }
  282. //=============================================================================
  283. // W3DCustomEdging::allocateEdgingBuffers
  284. //=============================================================================
  285. /** Allocates the index and vertex buffers. */
  286. //=============================================================================
  287. void W3DCustomEdging::allocateEdgingBuffers(void)
  288. {
  289. m_vertexEdging=NEW_REF(DX8VertexBufferClass,(DX8_FVF_XYZDUV2,MAX_EDGE_VERTEX+4,DX8VertexBufferClass::USAGE_DYNAMIC));
  290. m_indexEdging=NEW_REF(DX8IndexBufferClass,(2*MAX_EDGE_INDEX+4, DX8IndexBufferClass::USAGE_DYNAMIC));
  291. m_curNumEdgingVertices=0;
  292. m_curNumEdgingIndices=0;
  293. //m_edgeTexture = MSGNEW("TextureClass") TextureClass("EdgingTemplate.tga","EdgingTemplate.tga", TextureClass::MIP_LEVELS_3);
  294. }
  295. //=============================================================================
  296. // W3DCustomEdging::clearAllEdging
  297. //=============================================================================
  298. /** Removes all trees. */
  299. //=============================================================================
  300. void W3DCustomEdging::clearAllEdging(void)
  301. {
  302. m_curNumEdgingVertices=0;
  303. m_curNumEdgingIndices=0;
  304. m_anythingChanged = true;
  305. }
  306. //=============================================================================
  307. // W3DCustomEdging::drawEdging
  308. //=============================================================================
  309. /** Draws the trees. Uses camera to cull. */
  310. //=============================================================================
  311. void W3DCustomEdging::drawEdging(WorldHeightMap *pMap, Int minX, Int maxX, Int minY, Int maxY,
  312. TextureClass * terrainTexture, TextureClass * cloudTexture, TextureClass * noiseTexture)
  313. {
  314. static Bool foo = false;
  315. if (foo) {
  316. return;
  317. }
  318. //m_anythingChanged = true;
  319. loadEdgingsInVertexAndIndexBuffers(pMap, minX, maxX, minY, maxY);
  320. if (m_curNumEdgingIndices == 0) {
  321. return;
  322. }
  323. TextureClass *edgeTex = pMap->getEdgeTerrainTexture();
  324. // Setup the vertex buffer, shader & texture.
  325. DX8Wrapper::Set_Index_Buffer(m_indexEdging,0);
  326. DX8Wrapper::Set_Vertex_Buffer(m_vertexEdging);
  327. DX8Wrapper::Set_Shader(detailAlphaTestShader);
  328. #ifdef _DEBUG
  329. //DX8Wrapper::Set_Shader(detailShader); // shows clipping.
  330. #endif
  331. DX8Wrapper::Set_Texture(0,terrainTexture);
  332. DX8Wrapper::Set_Texture(1,edgeTex);
  333. DX8Wrapper::Apply_Render_State_Changes();
  334. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x7B);
  335. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_LESSEQUAL); //pass pixels who's alpha is not zero
  336. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
  337. DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
  338. DX8Wrapper::Set_Texture(0,edgeTex);
  339. DX8Wrapper::Set_Texture(1, NULL);
  340. // Draw the custom edge.
  341. DX8Wrapper::Apply_Render_State_Changes();
  342. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x84);
  343. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL); //pass pixels who's alpha is not zero
  344. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
  345. DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
  346. #if 0 // Dumps out unmasked data.
  347. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
  348. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, false); //test pixels if transparent(clipped) before rendering.
  349. DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
  350. #endif
  351. DX8Wrapper::Set_Texture(1, NULL);
  352. if (cloudTexture) {
  353. DX8Wrapper::Set_Shader(detailOpaqueShader);
  354. DX8Wrapper::Apply_Render_State_Changes();
  355. DX8Wrapper::Set_Texture(1,edgeTex);
  356. DX8Wrapper::Apply_Render_State_Changes();
  357. DX8Wrapper::Set_Texture(0,cloudTexture);
  358. DX8Wrapper::Apply_Render_State_Changes();
  359. #if 1
  360. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
  361. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  362. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
  363. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE );
  364. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  365. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
  366. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
  367. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
  368. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1 );
  369. #endif
  370. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x80);
  371. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_NOTEQUAL); //pass pixels who's alpha is not zero
  372. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
  373. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  374. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
  375. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
  376. DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
  377. }
  378. if (noiseTexture) {
  379. DX8Wrapper::Set_Texture(1, NULL);
  380. DX8Wrapper::Set_Texture(0,noiseTexture);
  381. DX8Wrapper::Apply_Render_State_Changes();
  382. DX8Wrapper::Set_Texture(1,edgeTex);
  383. DX8Wrapper::Apply_Render_State_Changes();
  384. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x80);
  385. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_NOTEQUAL); //pass pixels who's alpha is not zero
  386. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
  387. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  388. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
  389. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
  390. DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
  391. }
  392. }