TerrainTex.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  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: TerrainTex.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: TerrainTex.cpp
  36. //
  37. // Created: John Ahlquist, April 2001
  38. //
  39. // Desc: TextureClass overrides to perform custom texturing for the terrain.
  40. //
  41. //-----------------------------------------------------------------------------
  42. //-----------------------------------------------------------------------------
  43. // Includes
  44. //-----------------------------------------------------------------------------
  45. #include <stdlib.h>
  46. #include "W3DDevice/GameClient/TerrainTex.h"
  47. #include "W3DDevice/GameClient/WorldHeightMap.h"
  48. #include "W3DDevice/GameClient/TileData.h"
  49. #include "common/GlobalData.h"
  50. #include "WW3D2/dx8wrapper.h"
  51. #include "d3dx8tex.h"
  52. /******************************************************************************
  53. TerrainTextureClass
  54. ******************************************************************************/
  55. //-----------------------------------------------------------------------------
  56. // Public Functions
  57. //-----------------------------------------------------------------------------
  58. //=============================================================================
  59. // TerrainTextureClass::TerrainTextureClass
  60. //=============================================================================
  61. /** Constructor. Calls parent constructor to create a 16 bit per pixel D3D
  62. texture of the desired height and mip level. */
  63. //=============================================================================
  64. TerrainTextureClass::TerrainTextureClass(int height) :
  65. TextureClass(TEXTURE_WIDTH, height,
  66. WW3D_FORMAT_A1R5G5B5, MIP_LEVELS_3 )
  67. {
  68. }
  69. //=============================================================================
  70. // TerrainTextureClass::TerrainTextureClass
  71. //=============================================================================
  72. /** Constructor. Calls parent constructor to create a 16 bit per pixel D3D
  73. texture of the desired height and mip level. */
  74. //=============================================================================
  75. TerrainTextureClass::TerrainTextureClass(int height, int width) :
  76. TextureClass(width, height,
  77. WW3D_FORMAT_A1R5G5B5, MIP_LEVELS_ALL )
  78. {
  79. }
  80. //=============================================================================
  81. // TerrainTextureClass::update
  82. //=============================================================================
  83. /** Sets the tile bitmap data into the texture. The tiles are placed with 4
  84. pixel borders around them, so that when the tiles are scaled and bilinearly
  85. interpolated, you don't get seams between the tiles. */
  86. //=============================================================================
  87. int TerrainTextureClass::update(WorldHeightMap *htMap)
  88. {
  89. // D3DTexture is our texture;
  90. IDirect3DSurface8 *surface_level;
  91. D3DSURFACE_DESC surface_desc;
  92. D3DLOCKED_RECT locked_rect;
  93. DX8_ErrorCode(Peek_D3D_Texture()->GetSurfaceLevel(0, &surface_level));
  94. DX8_ErrorCode(surface_level->GetDesc(&surface_desc));
  95. if (surface_desc.Width < TEXTURE_WIDTH) {
  96. return 0;
  97. }
  98. DX8_ErrorCode(surface_level->LockRect(&locked_rect, NULL, 0));
  99. Int tilePixelExtent = TILE_PIXEL_EXTENT;
  100. Int tilesPerRow = surface_desc.Width/(2*TILE_PIXEL_EXTENT+TILE_OFFSET);
  101. tilesPerRow *= 2;
  102. // Int numRows = surface_desc.Height/(tilePixelExtent+TILE_OFFSET);
  103. #ifdef _DEBUG
  104. //DEBUG_ASSERTCRASH(tilesPerRow*numRows >= htMap->m_numBitmapTiles, ("Too many tiles."));
  105. DEBUG_ASSERTCRASH((Int)surface_desc.Width >= tilePixelExtent*tilesPerRow, ("Bitmap too small."));
  106. #endif
  107. if (surface_desc.Format == D3DFMT_A1R5G5B5) {
  108. #if 0
  109. UnsignedInt cellX, cellY;
  110. for (cellX = 0; cellX < surface_desc.Width; cellX++) {
  111. for (cellY = 0; cellY < surface_desc.Height; cellY++) {
  112. UnsignedByte *pBGR = ((UnsignedByte *)locked_rect.pBits)+(cellY*surface_desc.Width+cellX)*2;
  113. *((Short*)pBGR) = (((255-2*cellY)>>3)<<10) + ((4*cellX)>>4);
  114. }
  115. }
  116. #endif
  117. Int tileNdx;
  118. Int pixelBytes = 2;
  119. for (tileNdx=0; tileNdx < htMap->m_numBitmapTiles; tileNdx++) {
  120. TileData *pTile = htMap->getSourceTile(tileNdx);
  121. if (!pTile) continue;
  122. ICoord2D position = pTile->m_tileLocationInTexture;
  123. if (position.x<=0) continue; // all real tile offsets start at 2. jba.
  124. Int i,j;
  125. for (j=0; j<tilePixelExtent; j++) {
  126. UnsignedByte *pBGR = pTile->getRGBDataForWidth(tilePixelExtent);
  127. pBGR += (tilePixelExtent-1-j)*TILE_BYTES_PER_PIXEL*tilePixelExtent; // invert to match.
  128. Int row = position.y+j;
  129. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  130. (row)*surface_desc.Width*pixelBytes;
  131. Int column = position.x;
  132. pBGRX += column*pixelBytes;
  133. for (i=0; i<tilePixelExtent; i++) {
  134. *((Short*)pBGRX) = 0x8000 + ((pBGR[2]>>3)<<10) + ((pBGR[1]>>3)<<5) + (pBGR[0]>>3);
  135. pBGRX +=pixelBytes;
  136. pBGR +=TILE_BYTES_PER_PIXEL;
  137. }
  138. }
  139. }
  140. // Now draw the 4 pixel border around each tile class.
  141. Int texClass;
  142. for (texClass=0; texClass<htMap->m_numTextureClasses; texClass++) {
  143. Int width = htMap->m_textureClasses[texClass].width;
  144. ICoord2D origin = htMap->m_textureClasses[texClass].positionInTexture;
  145. if (origin.x<=0) continue;
  146. width *= TILE_PIXEL_EXTENT;
  147. // Duplicate 4 columns of pixels before and after.
  148. Int j;
  149. for (j=0; j<width; j++) {
  150. Int row = origin.y+j;
  151. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  152. (row)*surface_desc.Width*pixelBytes;
  153. Int column = origin.x;
  154. pBGRX += column*pixelBytes;
  155. // copy before
  156. memcpy(pBGRX-(4)*pixelBytes, pBGRX+(width-4)*pixelBytes, 4*pixelBytes);
  157. // copy after
  158. memcpy(pBGRX+(width*pixelBytes), pBGRX, 4*pixelBytes);
  159. }
  160. // Duplicate 4 rows of pixels before and after.
  161. for (j=0; j<4; j++) {
  162. // copy before.
  163. Int row = origin.y-j-1;
  164. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  165. (row)*surface_desc.Width*pixelBytes;
  166. UnsignedByte *target = pBGRX+(origin.x-4)*pixelBytes;
  167. memcpy(target, target+width*surface_desc.Width*pixelBytes, (width+8)*pixelBytes);
  168. // copy after.
  169. row = origin.y+j;
  170. pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  171. (row)*surface_desc.Width*pixelBytes;
  172. target = pBGRX+(origin.x-4)*pixelBytes;
  173. memcpy(target+width*surface_desc.Width*pixelBytes, target, (width+8)*pixelBytes);
  174. }
  175. }
  176. }
  177. surface_level->UnlockRect();
  178. surface_level->Release();
  179. DX8_ErrorCode(D3DXFilterTexture(Peek_D3D_Texture(), NULL, 0, D3DX_FILTER_BOX));
  180. if (TheWritableGlobalData->m_textureReductionFactor) {
  181. Peek_D3D_Texture()->SetLOD(TheWritableGlobalData->m_textureReductionFactor);
  182. }
  183. return(surface_desc.Height);
  184. }
  185. #if 0 // old version.
  186. //=============================================================================
  187. // TerrainTextureClass::update
  188. //=============================================================================
  189. /** Sets the tile bitmap data into the texture. The tiles are placed with 4
  190. pixel borders around them, so that when the tiles are scaled and bilinearly
  191. interpolated, you don't get seams between the tiles. */
  192. //=============================================================================
  193. int TerrainTextureClass::update(WorldHeightMap *htMap)
  194. {
  195. // D3DTexture is our texture;
  196. IDirect3DSurface8 *surface_level;
  197. D3DSURFACE_DESC surface_desc;
  198. D3DLOCKED_RECT locked_rect;
  199. DX8_ErrorCode(D3DTexture->GetSurfaceLevel(0, &surface_level));
  200. DX8_ErrorCode(surface_level->GetDesc(&surface_desc));
  201. if (surface_desc.Width < TEXTURE_WIDTH) {
  202. surface_level->Release();
  203. if (surface_desc.Width == 256) {
  204. return update256(htMap);
  205. }
  206. return false;
  207. }
  208. DX8_ErrorCode(surface_level->LockRect(&locked_rect, NULL, 0));
  209. Int tilePixelExtent = TILE_PIXEL_EXTENT;
  210. Int tilesPerRow = surface_desc.Width/(2*TILE_PIXEL_EXTENT+TILE_OFFSET);
  211. tilesPerRow *= 2;
  212. Int numRows = surface_desc.Height/(tilePixelExtent+TILE_OFFSET);
  213. #ifdef _DEBUG
  214. assert(tilesPerRow*numRows >= htMap->m_numBitmapTiles);
  215. assert((Int)surface_desc.Width >= tilePixelExtent*tilesPerRow);
  216. #endif
  217. if (surface_desc.Format == D3DFMT_A1R5G5B5) {
  218. Int cellX, cellY;
  219. #if 0
  220. for (cellX = 0; cellX < surface_desc.Width; cellX++) {
  221. for (cellY = 0; cellY < surface_desc.Height; cellY++) {
  222. UnsignedByte *pBGR = ((UnsignedByte *)locked_rect.pBits)+(cellY*surface_desc.Width+cellX)*2;
  223. *((Short*)pBGR) = (((255-2*cellY)>>3)<<10) + ((4*cellX)>>4);
  224. }
  225. }
  226. #endif
  227. Int pixelBytes = 2;
  228. for (cellY = 0; cellY < numRows; cellY++) {
  229. for (cellX = 0; cellX < tilesPerRow; cellX++) {
  230. Int tileNdx = cellX/2 + (tilesPerRow/2)*(cellY/2);
  231. tileNdx *=4;
  232. if (cellX&1) tileNdx++;
  233. if (!(cellY&1)) tileNdx += 2;
  234. #define ADD_EXTRA_TILES 1
  235. #if ADD_EXTRA_TILES // Fills in an extra 2 columns and 1 row of tiles if there is room.
  236. if (!htMap->getSourceTile(tileNdx) && htMap->getSourceTile(tileNdx-4)) {
  237. tileNdx -= 4;
  238. }
  239. if (!htMap->getSourceTile(tileNdx) && htMap->getSourceTile(tileNdx-8)) {
  240. tileNdx -= 8;
  241. }
  242. if (!htMap->getSourceTile(tileNdx) && htMap->getSourceTile(tileNdx-2*tilesPerRow)) {
  243. tileNdx -= 2*tilesPerRow;
  244. }
  245. #endif
  246. if (htMap->getSourceTile(tileNdx)) {
  247. Int i,j;
  248. for (j=0; j<tilePixelExtent; j++) {
  249. UnsignedByte *pBGR = htMap->getSourceTile(tileNdx)->getRGBDataForWidth(tilePixelExtent);
  250. pBGR += (tilePixelExtent-1-j)*TILE_BYTES_PER_PIXEL*tilePixelExtent; // invert to match.
  251. Int row = cellY*tilePixelExtent+j;
  252. row += TILE_OFFSET/2;
  253. row += TILE_OFFSET*(cellY/2);
  254. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  255. (row)*surface_desc.Width*pixelBytes;
  256. Int column = cellX*tilePixelExtent;
  257. column += TILE_OFFSET*(cellX/2);
  258. pBGRX += column*pixelBytes;
  259. pBGRX += (TILE_OFFSET/2)*pixelBytes;
  260. for (i=0; i<tilePixelExtent; i++) {
  261. *((Short*)pBGRX) = 0x8000 + ((pBGR[2]>>3)<<10) + ((pBGR[1]>>3)<<5) + (pBGR[0]>>3);
  262. pBGRX +=pixelBytes;
  263. pBGR +=TILE_BYTES_PER_PIXEL;
  264. }
  265. }
  266. }
  267. }
  268. }
  269. for (cellY = 0; cellY < numRows; cellY++) {
  270. for (cellX = 0; cellX < tilesPerRow; cellX++) {
  271. // Duplicate 4 rows of pixels before and after.
  272. Int j;
  273. for (j=0; j<tilePixelExtent; j++) {
  274. Int row = cellY*tilePixelExtent+j;
  275. row += TILE_OFFSET/2;
  276. row += TILE_OFFSET*(cellY/2);
  277. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  278. (row)*surface_desc.Width*pixelBytes;
  279. Int column = cellX*tilePixelExtent;
  280. column += TILE_OFFSET*(cellX/2);
  281. pBGRX += column*pixelBytes;
  282. if (cellX&1) {
  283. Int bytesToCopy = 4*pixelBytes;
  284. if (cellX == tilesPerRow-1) {
  285. // last cell, so fill to the end of the texture.
  286. Int usedWidth = tilesPerRow*tilePixelExtent + TILE_OFFSET*(tilesPerRow/2);
  287. usedWidth *= pixelBytes;
  288. bytesToCopy += surface_desc.Width*pixelBytes - usedWidth;
  289. }
  290. // Copy after.
  291. pBGRX -= tilePixelExtent*pixelBytes;
  292. pBGRX += (TILE_OFFSET/2)*pixelBytes;
  293. memcpy(pBGRX+(2*tilePixelExtent*pixelBytes), pBGRX, bytesToCopy);
  294. } else {
  295. // copy before
  296. memcpy(pBGRX, pBGRX+(2*tilePixelExtent)*pixelBytes, 4*pixelBytes);
  297. }
  298. }
  299. }
  300. }
  301. for (cellY = 0; cellY < numRows; cellY++) {
  302. Int rowBytes = surface_desc.Width*pixelBytes;
  303. Int row = cellY*tilePixelExtent;
  304. row += TILE_OFFSET/2;
  305. row += TILE_OFFSET*(cellY/2);
  306. if ( (cellY&1) == 0) {
  307. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  308. (row)*rowBytes;
  309. row += 2*tilePixelExtent;
  310. UnsignedByte *pBase = ((UnsignedByte*)locked_rect.pBits) +
  311. (row)*rowBytes;
  312. memcpy(pBGRX-4*rowBytes, pBase-4*rowBytes, 4*rowBytes);
  313. } else {
  314. UnsignedByte *pBase = ((UnsignedByte*)locked_rect.pBits) +
  315. (row-tilePixelExtent)*rowBytes;
  316. row += tilePixelExtent;
  317. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  318. (row)*rowBytes;
  319. memcpy(pBGRX, pBase, 4*rowBytes);
  320. }
  321. }
  322. }
  323. surface_level->UnlockRect();
  324. surface_level->Release();
  325. DX8_ErrorCode(D3DXFilterTexture(D3DTexture, NULL, 0, D3DX_FILTER_BOX));
  326. return(surface_desc.Height);
  327. }
  328. #endif
  329. //=============================================================================
  330. // TerrainTextureClass::setLOD
  331. //=============================================================================
  332. /** Sets the lod of the texture to be loaded into the video card. */
  333. //=============================================================================
  334. void TerrainTextureClass::setLOD(Int LOD)
  335. {
  336. if (Peek_D3D_Texture()) Peek_D3D_Texture()->SetLOD(LOD);
  337. }
  338. //=============================================================================
  339. // TerrainTextureClass::update
  340. //=============================================================================
  341. /** Sets the tile bitmap data into the texture. The tiles are placed with 4
  342. pixel borders around them, so that when the tiles are scaled and bilinearly
  343. interpolated, you don't get seams between the tiles. */
  344. //=============================================================================
  345. Bool TerrainTextureClass::updateFlat(WorldHeightMap *htMap, Int xCell, Int yCell, Int cellWidth, Int pixelsPerCell)
  346. {
  347. // D3DTexture is our texture;
  348. IDirect3DSurface8 *surface_level;
  349. D3DSURFACE_DESC surface_desc;
  350. D3DLOCKED_RECT locked_rect;
  351. DX8_ErrorCode(Peek_D3D_Texture()->GetSurfaceLevel(0, &surface_level));
  352. DX8_ErrorCode(surface_level->GetDesc(&surface_desc));
  353. DEBUG_ASSERTCRASH((Int)surface_desc.Width == cellWidth*pixelsPerCell, ("Bitmap too small."));
  354. DEBUG_ASSERTCRASH((Int)surface_desc.Height == cellWidth*pixelsPerCell, ("Bitmap too small."));
  355. if (surface_desc.Width != cellWidth*pixelsPerCell) {
  356. return false;
  357. }
  358. DX8_ErrorCode(surface_level->LockRect(&locked_rect, NULL, 0));
  359. if (surface_desc.Format == D3DFMT_A1R5G5B5) {
  360. Int pixelBytes = 2;
  361. Int cellX, cellY;
  362. #if 0
  363. UnsignedInt X, Y;
  364. for (X = 0; X < surface_desc.Width; X++) {
  365. for (Y = 0; Y < surface_desc.Height; Y++) {
  366. UnsignedByte *pBGR = ((UnsignedByte *)locked_rect.pBits)+(Y*surface_desc.Width+X)*pixelBytes;
  367. *((Short*)pBGR) = (((255-2*Y)>>3)<<10) + ((2*X)>>4);
  368. }
  369. }
  370. #endif
  371. for (cellX = 0; cellX < cellWidth; cellX++) {
  372. for (cellY = 0; cellY < cellWidth; cellY++) {
  373. UnsignedByte *pBGRX_data = ((UnsignedByte*)locked_rect.pBits);
  374. UnsignedByte *pBGR = htMap->getPointerToTileData(xCell+cellX, yCell+cellY, pixelsPerCell);
  375. if (pBGR == NULL) continue; // past end of defined terrain. [3/24/2003]
  376. Int k, l;
  377. for (k=pixelsPerCell-1; k>=0; k--) {
  378. UnsignedByte *pBGRX = pBGRX_data + (pixelsPerCell*(cellWidth-cellY-1)+k)*surface_desc.Width*pixelBytes +
  379. cellX*pixelsPerCell*pixelBytes;
  380. for (l=0; l<pixelsPerCell; l++) {
  381. *((Short*)pBGRX) = 0x8000 + ((pBGR[2]>>3)<<10) + ((pBGR[1]>>3)<<5) + (pBGR[0]>>3);
  382. pBGRX +=pixelBytes;
  383. pBGR +=TILE_BYTES_PER_PIXEL;
  384. }
  385. }
  386. }
  387. }
  388. }
  389. surface_level->UnlockRect();
  390. surface_level->Release();
  391. DX8_ErrorCode(D3DXFilterTexture(Peek_D3D_Texture(), NULL, 0, D3DX_FILTER_BOX));
  392. return(surface_desc.Height);
  393. }
  394. //=============================================================================
  395. // TerrainTextureClass::Apply
  396. //=============================================================================
  397. /** Sets the texture as the current D3D texture, and does some custom setup
  398. (standard D3D setup, but beyond the scope of W3D). */
  399. //=============================================================================
  400. void TerrainTextureClass::Apply(unsigned int stage)
  401. {
  402. // Do the base apply.
  403. TextureClass::Apply(stage);
  404. #if 0 // obsolete [4/1/2003]
  405. if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
  406. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  407. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  408. } else {
  409. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_POINT);
  410. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  411. }
  412. if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
  413. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  414. } else {
  415. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  416. }
  417. // Now setup the texture pipeline.
  418. if (stage==0) {
  419. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  420. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  421. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  422. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  423. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  424. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  425. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  426. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  427. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
  428. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
  429. }
  430. #endif
  431. }
  432. /******************************************************************************
  433. AlphaTerrainTextureClass
  434. ******************************************************************************/
  435. //-----------------------------------------------------------------------------
  436. // Public Functions
  437. //-----------------------------------------------------------------------------
  438. //=============================================================================
  439. // AlphaTerrainTextureClass::AlphaTerrainTextureClass
  440. //=============================================================================
  441. /** Constructor. Calls parent constructor to creat a throw away 8x8 texture,
  442. then uses the base texture's D3D texture. This way the base tiles pass, drawn
  443. using TerrainTextureClass shares the same texture with the blended edges pass,
  444. saving lots of texture memory, and preventing seams between blended tiles. */
  445. //=============================================================================
  446. AlphaTerrainTextureClass::AlphaTerrainTextureClass( TextureClass *pBaseTex ):
  447. TextureClass(8, 8,
  448. WW3D_FORMAT_A1R5G5B5, MIP_LEVELS_1 )
  449. {
  450. // Attach the base texture's d3d texture.
  451. IDirect3DTexture8 * d3d_tex = pBaseTex->Peek_D3D_Texture();
  452. Set_D3D_Base_Texture(d3d_tex);
  453. }
  454. //=============================================================================
  455. // AlphaTerrainTextureClass::Apply
  456. //=============================================================================
  457. /** Sets the texture as the current D3D texture, and does some custom setup.
  458. This may be applied in either single pass, as the second texture in the pipe,
  459. or multipass. If stage==0, we are doing multipass and we set up the pipe
  460. for a single texture. If stage==1, then we are doing a single pass, and we
  461. set up the pipe so that we blend onto the base texture in stage 0.
  462. (standard D3D setup, but beyond the scope of W3D). */
  463. //=============================================================================
  464. void AlphaTerrainTextureClass::Apply(unsigned int stage)
  465. {
  466. // Do the base apply.
  467. TextureClass::Apply(stage);
  468. // Set the bilinear or trilinear filtering.
  469. if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
  470. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  471. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  472. } else {
  473. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_POINT);
  474. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  475. }
  476. if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
  477. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  478. } else {
  479. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  480. }
  481. // Since we are using multiple distinct tiles, the textures doesn't wrap, so clamp it.
  482. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  483. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  484. // Now setup the texture pipeline.
  485. if (stage==0) {
  486. // Modulate the diffuse color with the texture as lighting comes from diffuse.
  487. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  488. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  489. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  490. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  491. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 1 );
  492. // Blend the result using the alpha. (came from diffuse mod texture)
  493. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  494. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
  495. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
  496. // Disable stage 2.
  497. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  498. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  499. } else if (stage==1) {
  500. if (TheGlobalData && !TheGlobalData->m_multiPassTerrain)
  501. {
  502. ///@todo: Remove 8-Stage Nvidia hack after drivers are fixed.
  503. //This method is a backdoor specific to Nvidia based cards. It will fail on
  504. //other hardware. Allows single pass blend of 2 textures and post modulate diffuse.
  505. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  506. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0);
  507. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  508. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  509. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  510. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  511. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  512. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_ADD);
  513. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1);
  514. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE);
  515. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  516. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_ADD);
  517. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TFACTOR | D3DTA_COMPLEMENT);
  518. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
  519. DX8Wrapper::Set_DX8_Texture(2, NULL);
  520. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLOROP, D3DTOP_MODULATE);
  521. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXCOORDINDEX, 2);
  522. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  523. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  524. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  525. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  526. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
  527. DX8Wrapper::Set_DX8_Texture(3, NULL);
  528. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  529. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXCOORDINDEX, 3);
  530. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLORARG1, D3DTA_DIFFUSE | 0 | D3DTA_ALPHAREPLICATE);
  531. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  532. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  533. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  534. DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
  535. DX8Wrapper::Set_DX8_Texture(4, NULL);
  536. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLOROP, D3DTOP_MODULATE);
  537. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_TEXCOORDINDEX, 4);
  538. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLORARG1, D3DTA_CURRENT);
  539. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  540. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  541. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
  542. DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  543. DX8Wrapper::Set_DX8_Texture(5, NULL);
  544. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_COLOROP, D3DTOP_ADD);
  545. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_TEXCOORDINDEX, 5);
  546. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  547. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  548. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_ALPHAOP, D3DTOP_ADD);
  549. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_ALPHAARG1, D3DTA_TFACTOR | D3DTA_COMPLEMENT);
  550. DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
  551. DX8Wrapper::Set_DX8_Texture(6, NULL);
  552. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_COLOROP, D3DTOP_MODULATE);
  553. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_TEXCOORDINDEX, 6);
  554. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  555. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_COLORARG2, D3DTA_TFACTOR);
  556. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  557. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  558. DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
  559. DX8Wrapper::Set_DX8_Texture(7, NULL);
  560. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  561. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_TEXCOORDINDEX, 7);
  562. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  563. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_COLORARG2, D3DTA_TFACTOR);
  564. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  565. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  566. DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
  567. }
  568. else
  569. {
  570. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  571. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  572. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  573. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  574. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  575. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
  576. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  577. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  578. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  579. }
  580. }
  581. }
  582. /******************************************************************************
  583. LightMapTerrainTextureClass
  584. ******************************************************************************/
  585. //-----------------------------------------------------------------------------
  586. // Public Functions
  587. //-----------------------------------------------------------------------------
  588. //=============================================================================
  589. // LightMapTerrainTextureClass::LightMapTerrainTextureClass
  590. //=============================================================================
  591. /** Constructor. Calls parent constructor to load the .tga texture. */
  592. //=============================================================================
  593. LightMapTerrainTextureClass::LightMapTerrainTextureClass(AsciiString name, MipCountType mipLevelCount) :
  594. TextureClass(name.isEmpty()?"TSNoiseUrb.tga":name.str(),name.isEmpty()?"TSNoiseUrb.tga":name.str(), mipLevelCount )
  595. {
  596. Get_Filter().Set_Min_Filter(TextureFilterClass::FILTER_TYPE_BEST);
  597. Get_Filter().Set_Mag_Filter(TextureFilterClass::FILTER_TYPE_BEST);
  598. Get_Filter().Set_U_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_REPEAT);
  599. Get_Filter().Set_V_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_REPEAT);
  600. }
  601. #define STRETCH_FACTOR ((float)(1/(63.0*MAP_XY_FACTOR/2))) /* covers 63/2 tiles */
  602. //=============================================================================
  603. // LightMapTerrainTextureClass::Apply
  604. //=============================================================================
  605. /** Sets the texture as the current D3D texture, and does some custom setup.
  606. The LightMapTerrainTextureClass may be applied by itself, or with the
  607. CloudMapTerrainTextureClass. This may be applied in either single pass,
  608. as the second texture in the pipe,
  609. or multipass. If stage==0, we are doing multipass and we set up the pipe
  610. for a single texture. If stage==1, then we are doing a single pass, and we
  611. set up the pipe so that we blend onto the cloud map texture in stage 0.
  612. Also, texture is mapped using the x/y coordinates of the map, saving us
  613. yet another set of uv coordinates.
  614. (standard D3D setup, but beyond the scope of W3D). */
  615. //=============================================================================
  616. void LightMapTerrainTextureClass::Apply(unsigned int stage)
  617. {
  618. TextureClass::Apply(stage);
  619. #if 0 // obsolete [4/1/2003]
  620. // Do the base apply.
  621. /* previous setup */
  622. if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
  623. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  624. } else {
  625. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  626. }
  627. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_POINT);
  628. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  629. // Disable 3rd stage just in case.
  630. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
  631. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  632. // Now setup the texture pipeline.
  633. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  634. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLORARG2, D3DTA_CURRENT );
  635. if (stage == 0) {
  636. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  637. //Disable second stage
  638. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  639. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  640. } else {
  641. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLOROP, D3DTOP_MODULATE );
  642. }
  643. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  644. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
  645. // Two output coordinates are used.
  646. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  647. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  648. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  649. Matrix4x4 curView;
  650. DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
  651. D3DXMATRIX inv;
  652. float det;
  653. D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
  654. D3DXMATRIX scale;
  655. D3DXMatrixScaling(&scale, STRETCH_FACTOR, STRETCH_FACTOR,1);
  656. inv *=scale;
  657. if (stage==0) {
  658. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, *((Matrix4x4*)&inv));
  659. } if (stage==1) {
  660. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, *((Matrix4x4*)&inv));
  661. }
  662. if (stage==0) {
  663. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  664. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
  665. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
  666. }
  667. #endif
  668. }
  669. /******************************************************************************
  670. AlphaEdgeTextureClass
  671. ******************************************************************************/
  672. //-----------------------------------------------------------------------------
  673. // Public Functions
  674. //-----------------------------------------------------------------------------
  675. /**
  676. * AlphaEdgeTextureClass - Generates the alpha edge blending for terrain.
  677. *
  678. */
  679. AlphaEdgeTextureClass::AlphaEdgeTextureClass( int height, MipCountType mipLevelCount) :
  680. // TextureClass("EdgingTemplate.tga","EdgingTemplate.tga", mipLevelCount )
  681. TextureClass(TEXTURE_WIDTH, height, WW3D_FORMAT_A8R8G8B8, mipLevelCount )
  682. {
  683. }
  684. int AlphaEdgeTextureClass::update256(WorldHeightMap *htMap)
  685. {
  686. return 1;
  687. }
  688. int AlphaEdgeTextureClass::update(WorldHeightMap *htMap)
  689. {
  690. // D3DTexture is our texture;
  691. IDirect3DSurface8 *surface_level;
  692. D3DSURFACE_DESC surface_desc;
  693. D3DLOCKED_RECT locked_rect;
  694. DX8_ErrorCode(Peek_D3D_Texture()->GetSurfaceLevel(0, &surface_level));
  695. DX8_ErrorCode(surface_level->LockRect(&locked_rect, NULL, 0));
  696. DX8_ErrorCode(surface_level->GetDesc(&surface_desc));
  697. Int tilePixelExtent = TILE_PIXEL_EXTENT; // blend tiles are 1/4 tiles.
  698. // Int tilesPerRow = surface_desc.Width / (tilePixelExtent+8);
  699. // Int numRows = surface_desc.Height/(tilePixelExtent+8);
  700. if (surface_desc.Format == D3DFMT_A8R8G8B8) {
  701. #if 1
  702. #if 1
  703. Int cellX, cellY;
  704. for (cellX = 0; (UnsignedInt)cellX < surface_desc.Width; cellX++) {
  705. for (cellY = 0; cellY < surface_desc.Height; cellY++) {
  706. UnsignedByte *pBGR = ((UnsignedByte *)locked_rect.pBits)+(cellY*surface_desc.Width+cellX)*4;
  707. pBGR[2] = 255-cellY/2;
  708. pBGR[0] = cellX/2;
  709. pBGR[3] = cellX/2; // alpha.
  710. pBGR[3] = 128; // alpha.
  711. }
  712. }
  713. #endif
  714. #if 1
  715. Int tileNdx;
  716. Int pixelBytes = 4;
  717. for (tileNdx=0; tileNdx < htMap->m_numEdgeTiles; tileNdx++) {
  718. TileData *pTile = htMap->getEdgeTile(tileNdx);
  719. if (!pTile) continue;
  720. ICoord2D position = pTile->m_tileLocationInTexture;
  721. if (position.x<=0) continue; // all real edge offsets start at 4. jba.
  722. Int i,j;
  723. Int column = position.x;
  724. for (j=0; j<tilePixelExtent; j++) {
  725. Int row = position.y+j;
  726. UnsignedByte *pBGR = htMap->getEdgeTile(tileNdx)->getRGBDataForWidth(tilePixelExtent);
  727. pBGR += (tilePixelExtent-1-j)*TILE_BYTES_PER_PIXEL*tilePixelExtent; // invert to match.
  728. UnsignedByte *pBGRX = ((UnsignedByte*)locked_rect.pBits) +
  729. (row)*surface_desc.Width*pixelBytes;
  730. pBGRX += column*pixelBytes;
  731. for (i=0; i<tilePixelExtent; i++) {
  732. pBGRX[0] = pBGR[0]; //r
  733. pBGRX[1] = pBGR[1]; //g
  734. pBGRX[2] = pBGR[2]; //b
  735. if (pBGR[0]==0 && pBGR[1]==0 && pBGR[2]==0) {
  736. pBGRX[3] = 0x80;
  737. } else if (pBGR[0]==0xff && pBGR[1]==0xff && pBGR[2]==0xff) {
  738. pBGRX[3] = 0x00;
  739. } else {
  740. pBGRX[3] = 0xff;
  741. }
  742. pBGRX += pixelBytes;
  743. pBGR += TILE_BYTES_PER_PIXEL;
  744. }
  745. }
  746. }
  747. #endif
  748. #endif
  749. }
  750. surface_level->UnlockRect();
  751. surface_level->Release();
  752. DX8_ErrorCode(D3DXFilterTexture(Peek_D3D_Texture(), NULL, 0, D3DX_FILTER_BOX));
  753. return(surface_desc.Height);
  754. }
  755. void AlphaEdgeTextureClass::Apply(unsigned int stage)
  756. {
  757. // Do the base apply.
  758. TextureClass::Apply(stage);
  759. #if 0 // obsolete [4/1/2003]
  760. if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
  761. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  762. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  763. } else {
  764. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_POINT);
  765. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  766. }
  767. if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
  768. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  769. } else {
  770. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  771. }
  772. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  773. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  774. // Now setup the texture pipeline.
  775. if (stage==0) {
  776. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  777. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  778. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  779. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  780. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  781. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 1 );
  782. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  783. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
  784. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
  785. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  786. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  787. } else if (stage==1) {
  788. // Drawing texture through the mask.
  789. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
  790. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  791. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
  792. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE );
  793. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  794. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
  795. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
  796. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
  797. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1 );
  798. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  799. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_ONE);
  800. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
  801. }
  802. #endif
  803. }
  804. /******************************************************************************
  805. CloudMapTerrainTextureClass
  806. ******************************************************************************/
  807. //-----------------------------------------------------------------------------
  808. // Public Functions
  809. //-----------------------------------------------------------------------------
  810. //=============================================================================
  811. // CloudMapTerrainTextureClass::CloudMapTerrainTextureClass
  812. //=============================================================================
  813. /** Constructor. Calls parent constructor to load the .tga texture, and sets
  814. up the "sliding" parameters for the clouds to slide over the terrain. */
  815. //=============================================================================
  816. //@todo - Allow adjustment of the cloud slide rate, and lose the hard coded "cloudmap.tga"
  817. CloudMapTerrainTextureClass::CloudMapTerrainTextureClass(MipCountType mipLevelCount) :
  818. TextureClass("TSCloudMed.tga","TSCloudMed.tga", mipLevelCount )
  819. {
  820. Get_Filter().Set_Mip_Mapping( TextureFilterClass::FILTER_TYPE_FAST );
  821. m_xSlidePerSecond = -0.02f;
  822. m_ySlidePerSecond = 1.50f * m_xSlidePerSecond;
  823. m_curTick = 0;
  824. m_xOffset = 0;
  825. m_yOffset = 0;
  826. }
  827. //=============================================================================
  828. // CloudMapTerrainTextureClass::Apply
  829. //=============================================================================
  830. /** Sets the texture as the current D3D texture, and does some custom setup.
  831. The CloudMapTerrainTextureClass may be applied by itself, or with the
  832. LightMapTerrainTexture. This may be applied in either single pass,
  833. as the first texture in the pipe with LightMapTerrainTextureClass as the
  834. second stage of the pape, or multipass. We setup for stage 0, assuming that
  835. we are the only texture, as LightMapTerrainTexture will adjust for multitexture
  836. if it is applied to stage 1.
  837. Also, texture is mapped using the x/y coordinates of the map, saving us
  838. yet another set of uv coordinates.
  839. (standard D3D setup, but beyond the scope of W3D). */
  840. //=============================================================================
  841. void CloudMapTerrainTextureClass::Apply(unsigned int stage)
  842. {
  843. // Do the base apply.
  844. TextureClass::Apply(stage);
  845. return;
  846. #if 0 // obsolete
  847. /* previous setup */
  848. if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
  849. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  850. } else {
  851. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  852. }
  853. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  854. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  855. // Now setup the texture pipeline.
  856. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
  857. // Two output coordinates are used.
  858. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  859. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  860. DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  861. Matrix4x4 curView;
  862. DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
  863. D3DXMATRIX inv;
  864. float det;
  865. D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
  866. D3DXMATRIX scale;
  867. D3DXMatrixScaling(&scale, STRETCH_FACTOR, STRETCH_FACTOR,1);
  868. inv *=scale;
  869. D3DXMATRIX offset;
  870. Int delta = m_curTick;
  871. m_curTick = ::GetTickCount();
  872. delta = m_curTick-delta;
  873. m_xOffset += m_xSlidePerSecond*delta/1000;
  874. m_yOffset += m_ySlidePerSecond*delta/1000;
  875. if (m_xOffset > 1) m_xOffset -= 1;
  876. if (m_yOffset > 1) m_yOffset -= 1;
  877. if (m_xOffset < -1) m_xOffset += 1;
  878. if (m_yOffset < -1) m_yOffset += 1;
  879. D3DXMatrixTranslation(&offset, m_xOffset, m_yOffset,0);
  880. inv *= offset;
  881. if (stage==0) {
  882. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  883. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  884. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
  885. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  886. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, *((Matrix4x4*)&inv));
  887. // Disable 3rd stage just in case.
  888. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
  889. DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  890. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  891. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  892. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  893. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
  894. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
  895. } else if (stage==1) {
  896. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  897. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  898. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
  899. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
  900. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  901. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, *((Matrix4x4*)&inv));
  902. }
  903. #endif
  904. }
  905. //=============================================================================
  906. // CloudMapTerrainTextureClass::restore
  907. //=============================================================================
  908. /** Cleans up any custom settings to the texturing pipeline that may not be
  909. understood by w3d. */
  910. //=============================================================================
  911. void CloudMapTerrainTextureClass::restore(void)
  912. {
  913. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  914. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  915. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  916. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  917. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  918. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  919. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
  920. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  921. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  922. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  923. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
  924. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  925. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  926. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  927. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 0 );
  928. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  929. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
  930. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
  931. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
  932. if (TheGlobalData && !TheGlobalData->m_multiPassTerrain)
  933. {
  934. ///@todo: Remove 8-Stage Nvidia hack after drivers are fixed.
  935. //This method is a backdoor specific to Nvidia based cards. It will fail on
  936. //other hardware. Allows single pass blend of 2 textures and post modulate diffuse.
  937. Int i;
  938. for (i=0; i<8; i++) {
  939. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_COLOROP, D3DTOP_DISABLE);
  940. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_TEXCOORDINDEX, i);
  941. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  942. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  943. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  944. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  945. DX8Wrapper::Set_DX8_Texture_Stage_State( i, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  946. DX8Wrapper::Set_DX8_Texture(i, NULL);
  947. }
  948. }
  949. }
  950. /******************************************************************************
  951. ScorchTextureClass
  952. ******************************************************************************/
  953. //-----------------------------------------------------------------------------
  954. // Public Functions
  955. //-----------------------------------------------------------------------------
  956. //=============================================================================
  957. // ScorchTextureClass::ScorchTextureClass
  958. //=============================================================================
  959. /** Constructor. Calls parent constructor to load the .tga texture. */
  960. //=============================================================================
  961. /// @todo - get "EXScorch01.tga" from not hard coded location.
  962. ScorchTextureClass::ScorchTextureClass(MipCountType mipLevelCount) :
  963. TextureClass("EXScorch01.tga","EXScorch01.tga", mipLevelCount )
  964. // Hack to disable texture reduction.
  965. // TextureClass("EXScorch01.tga","EXScorch01.tga", mipLevelCount,WW3D_FORMAT_UNKNOWN,true,false)
  966. {
  967. }
  968. //=============================================================================
  969. // ScorchTextureClass::Apply
  970. //=============================================================================
  971. /** Sets the texture as the current D3D texture, and does some custom setup.
  972. The ScorchTextureClass is applied by iteself, as it's mesh is a subset of the
  973. terrain mesh.
  974. (standard D3D setup, but beyond the scope of W3D). */
  975. //=============================================================================
  976. void ScorchTextureClass::Apply(unsigned int stage)
  977. {
  978. // Do the base apply.
  979. TextureClass::Apply(stage);
  980. // Setup bilinear or trilinear filtering as specified in global data.
  981. if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
  982. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  983. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  984. } else {
  985. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MINFILTER, D3DTEXF_POINT);
  986. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  987. }
  988. if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
  989. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  990. } else {
  991. DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
  992. }
  993. DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  994. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  995. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  996. // Now setup the texture pipeline.
  997. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  998. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  999. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  1000. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  1001. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1002. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
  1003. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
  1004. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
  1005. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1006. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1007. }