| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DCustomEdging.cpp ////////////////////////////////////////////////
- //-----------------------------------------------------------------------------
- //
- // Westwood Studios Pacific.
- //
- // Confidential Information
- // Copyright (C) 2001 - All Rights Reserved
- //
- //-----------------------------------------------------------------------------
- //
- // Project: RTS3
- //
- // File name: W3DCustomEdging.cpp
- //
- // Created: John Ahlquist, May 2001
- //
- // Desc: Draw buffer to handle all the custom tile edges in a scene.
- //
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // Includes
- //-----------------------------------------------------------------------------
- #include "W3DDevice/GameClient/W3DCustomEdging.h"
- #include <stdio.h>
- #include <string.h>
- #include <assetmgr.h>
- #include <texture.h>
- #include "common/GlobalData.h"
- #include "common/RandomValue.h"
- #include "W3DDevice/GameClient/TerrainTex.h"
- #include "W3DDevice/GameClient/HeightMap.h"
- #include "W3DDevice/GameClient/W3DDynamicLight.h"
- #include "WW3D2/Camera.h"
- #include "WW3D2/DX8Wrapper.h"
- #include "WW3D2/DX8Renderer.h"
- #include "WW3D2/Mesh.h"
- #include "WW3D2/MeshMdl.h"
- //-----------------------------------------------------------------------------
- // Private Data
- //-----------------------------------------------------------------------------
- // A W3D shader that does alpha, texturing, tests zbuffer, doesn't update zbuffer.
- #define SC_ALPHA_DETAIL ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
- ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::ALPHATEST_ENABLE, ShaderClass::CULL_MODE_DISABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass detailAlphaTestShader(SC_ALPHA_DETAIL);
- #define SC_NO_ALPHA ( SHADE_CNST(ShaderClass::PASS_ALWAYS, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
- ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass detailShader(SC_NO_ALPHA);
- #define SC_DETAIL_BLEND ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
- ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, ShaderClass::DETAILCOLOR_SCALE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass detailOpaqueShader(SC_DETAIL_BLEND);
- /*
- #define SC_ALPHA_MIRROR ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
- ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass mirrorAlphaShader(SC_ALPHA_DETAIL);
- // ShaderClass::PASS_ALWAYS,
- #define SC_ALPHA_2D ( SHADE_CNST(PASS_ALWAYS, DEPTH_WRITE_DISABLE, COLOR_WRITE_ENABLE, \
- SRCBLEND_SRC_ALPHA, DSTBLEND_ONE_MINUS_SRC_ALPHA, FOG_DISABLE, GRADIENT_DISABLE, \
- SECONDARY_GRADIENT_DISABLE, TEXTURING_ENABLE, DETAILCOLOR_DISABLE, DETAILALPHA_DISABLE, \
- ALPHATEST_DISABLE, CULL_MODE_ENABLE, DETAILCOLOR_DISABLE, DETAILALPHA_DISABLE) )
- ShaderClass ShaderClass::_PresetAlpha2DShader(SC_ALPHA_2D);
- */
- //-----------------------------------------------------------------------------
- // Private Functions
- //-----------------------------------------------------------------------------
- //=============================================================================
- // W3DCustomEdging::loadEdgingsInVertexAndIndexBuffers
- //=============================================================================
- /** Loads the trees into the vertex buffer for drawing. */
- //=============================================================================
- void W3DCustomEdging::loadEdgingsInVertexAndIndexBuffers(WorldHeightMap *pMap, Int minX, Int maxX, Int minY, Int maxY)
- {
- if (!m_indexEdging || !m_vertexEdging || !m_initialized) {
- return;
- }
- if (!m_anythingChanged) {
- return;
- }
- m_anythingChanged = false;
- m_curNumEdgingVertices = 0;
- m_curNumEdgingIndices = 0;
- VertexFormatXYZDUV2 *vb;
- UnsignedShort *ib;
- // Lock the buffers.
- DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexEdging);
- DX8VertexBufferClass::WriteLockClass lockVtxBuffer(m_vertexEdging);
- vb=(VertexFormatXYZDUV2*)lockVtxBuffer.Get_Vertex_Array();
- ib = lockIdxBuffer.Get_Index_Array();
- UnsignedShort *curIb = ib;
- VertexFormatXYZDUV2 *curVb = vb;
- if (minX<0) minX = 0;
- if (minY<0) minY = 0;
- if (maxX >= pMap->getXExtent()) maxX = pMap->getXExtent()-1;
- if (maxY >= pMap->getYExtent()) maxY = pMap->getYExtent()-1;
- Int row;
- Int column;
- for (row=minY; row<maxY-1; row++) {
- for (column = minX; column < maxX-1; column++) {
- Int cellNdx = column+row*pMap->getXExtent();
- Int blend = pMap->m_blendTileNdxes[cellNdx];
- if (blend == 0) continue; // no blend.
- if (pMap->m_blendedTiles[blend].customBlendEdgeClass<0) continue; // alpha blend.
- Int i, j;
- Real uOffset;
- Real vOffset;
- if (pMap->m_blendedTiles[blend].horiz) {
- uOffset = 0;
- vOffset = 0.25f * (1 + (row&1));
- if (pMap->m_blendedTiles[blend].inverted) {
- uOffset = 0.75f;
- }
- } else if (pMap->m_blendedTiles[blend].vert) {
- vOffset = 0.75;
- uOffset = 0.25f * (1 + (column&1));
- if (pMap->m_blendedTiles[blend].inverted) {
- vOffset = 0.0f;
- }
- } else if (pMap->m_blendedTiles[blend].rightDiagonal) {
- if (pMap->m_blendedTiles[blend].longDiagonal) {
- vOffset = 0.25;
- uOffset = 0.5;
- if (pMap->m_blendedTiles[blend].inverted) {
- uOffset = 0.5f;
- vOffset = 0.5f;
- }
- } else {
- vOffset = .75;
- uOffset = 0;
- if (pMap->m_blendedTiles[blend].inverted) {
- uOffset = 0.0f;
- vOffset = 0.0f;
- }
- }
- } else if (pMap->m_blendedTiles[blend].leftDiagonal) {
- if (pMap->m_blendedTiles[blend].longDiagonal) {
- uOffset = 0.25f;
- vOffset = 0.25f;
- if (pMap->m_blendedTiles[blend].inverted) {
- uOffset = 0.25f;
- vOffset = 0.5f;
- }
- } else {
- vOffset = 0.75;
- uOffset = 0.75f;
- if (pMap->m_blendedTiles[blend].inverted) {
- uOffset = 0.75f;
- vOffset = 0.0f;
- }
- }
- } else {
- continue;
- }
- Region2D range;
- pMap->getUVForBlend(pMap->m_blendedTiles[blend].customBlendEdgeClass, &range);
- uOffset = range.lo.x + range.width()*uOffset;
- vOffset = range.lo.y + range.height()*vOffset;
- UnsignedByte alpha[4];
- float UA[4], VA[4];
- Bool flipForBlend;
- pMap->getAlphaUVData(column-pMap->getDrawOrgX(), row-pMap->getDrawOrgY(), UA, VA, alpha, &flipForBlend, false);
- Int startVertex = m_curNumEdgingVertices;
- for (j=0; j<2; j++) {
- for (i=0; i<2; i++) {
- if (m_curNumEdgingVertices >= MAX_EDGE_VERTEX) return;
- cellNdx = column+i+(row+j)*pMap->getXExtent();
- Int diffuse = TheTerrainRenderObject->getStaticDiffuse(column+i, row+j);
- curVb->diffuse = 0x80000000 + (diffuse&0x00FFFFFF); // set alpha to 5b.
- Real theZ;
- theZ = ((float)pMap->getDataPtr()[cellNdx])*MAP_HEIGHT_SCALE;
- Real X = (column+i)*MAP_XY_FACTOR;
- Real Y = (row+j)*MAP_XY_FACTOR;
- curVb->u2 = uOffset + i*0.25f*range.width();
- curVb->v2 = vOffset + (1-j)*0.25f*range.height();
- Int ndx;
- if (j==0) ndx=i;
- if (j==1) ndx = 3-i;
- curVb->u1 = UA[ndx];
- curVb->v1 = VA[ndx];
- curVb->x = X;
- curVb->y = Y;
- curVb->z = theZ;
- curVb++;
- m_curNumEdgingVertices++;
- }
- }
- Int yOffset = 2;
- if (m_curNumEdgingIndices+6 > MAX_EDGE_INDEX) return;
- #ifdef FLIP_TRIANGLES // jba - reduces "diamonding" in some cases, not others. Better cliffs, though.
- if (flipForBlend) {
- *curIb++ = startVertex + 1;
- *curIb++ = startVertex + yOffset;
- *curIb++ = startVertex ;
- *curIb++ = startVertex + 1;
- *curIb++ = startVertex + 1+yOffset;
- *curIb++ = startVertex + yOffset;
- }
- else
- #endif
- {
- *curIb++ = startVertex;
- *curIb++ = startVertex + 1+yOffset;
- *curIb++ = startVertex + yOffset;
- *curIb++ = startVertex ;
- *curIb++ = startVertex + 1;
- *curIb++ = startVertex + 1+yOffset;
- }
- m_curNumEdgingIndices+=6;
- }
- }
- m_anythingChanged = false;
- }
- //-----------------------------------------------------------------------------
- // Public Functions
- //-----------------------------------------------------------------------------
- //=============================================================================
- // W3DCustomEdging::~W3DCustomEdging
- //=============================================================================
- /** Destructor. Releases w3d assets. */
- //=============================================================================
- W3DCustomEdging::~W3DCustomEdging(void)
- {
- freeEdgingBuffers();
- }
- //=============================================================================
- // W3DCustomEdging::W3DCustomEdging
- //=============================================================================
- /** Constructor. Sets m_initialized to true if it finds the w3d models it needs
- for the trees. */
- //=============================================================================
- W3DCustomEdging::W3DCustomEdging(void)
- {
- m_initialized = false;
- m_vertexEdging = NULL;
- m_indexEdging = NULL;
- clearAllEdging();
- allocateEdgingBuffers();
- m_initialized = true;
- }
- //=============================================================================
- // W3DCustomEdging::freeEdgingBuffers
- //=============================================================================
- /** Frees the index and vertex buffers. */
- //=============================================================================
- void W3DCustomEdging::freeEdgingBuffers(void)
- {
- REF_PTR_RELEASE(m_vertexEdging);
- REF_PTR_RELEASE(m_indexEdging);
- }
- //=============================================================================
- // W3DCustomEdging::allocateEdgingBuffers
- //=============================================================================
- /** Allocates the index and vertex buffers. */
- //=============================================================================
- void W3DCustomEdging::allocateEdgingBuffers(void)
- {
- m_vertexEdging=NEW_REF(DX8VertexBufferClass,(DX8_FVF_XYZDUV2,MAX_EDGE_VERTEX+4,DX8VertexBufferClass::USAGE_DYNAMIC));
- m_indexEdging=NEW_REF(DX8IndexBufferClass,(2*MAX_EDGE_INDEX+4, DX8IndexBufferClass::USAGE_DYNAMIC));
- m_curNumEdgingVertices=0;
- m_curNumEdgingIndices=0;
- //m_edgeTexture = MSGNEW("TextureClass") TextureClass("EdgingTemplate.tga","EdgingTemplate.tga", TextureClass::MIP_LEVELS_3);
- }
- //=============================================================================
- // W3DCustomEdging::clearAllEdging
- //=============================================================================
- /** Removes all trees. */
- //=============================================================================
- void W3DCustomEdging::clearAllEdging(void)
- {
- m_curNumEdgingVertices=0;
- m_curNumEdgingIndices=0;
- m_anythingChanged = true;
- }
- //=============================================================================
- // W3DCustomEdging::drawEdging
- //=============================================================================
- /** Draws the trees. Uses camera to cull. */
- //=============================================================================
- void W3DCustomEdging::drawEdging(WorldHeightMap *pMap, Int minX, Int maxX, Int minY, Int maxY,
- TextureClass * terrainTexture, TextureClass * cloudTexture, TextureClass * noiseTexture)
- {
- static Bool foo = false;
- if (foo) {
- return;
- }
- //m_anythingChanged = true;
- loadEdgingsInVertexAndIndexBuffers(pMap, minX, maxX, minY, maxY);
- if (m_curNumEdgingIndices == 0) {
- return;
- }
- TextureClass *edgeTex = pMap->getEdgeTerrainTexture();
- // Setup the vertex buffer, shader & texture.
- DX8Wrapper::Set_Index_Buffer(m_indexEdging,0);
- DX8Wrapper::Set_Vertex_Buffer(m_vertexEdging);
- DX8Wrapper::Set_Shader(detailAlphaTestShader);
- #ifdef _DEBUG
- //DX8Wrapper::Set_Shader(detailShader); // shows clipping.
- #endif
-
- DX8Wrapper::Set_Texture(0,terrainTexture);
- DX8Wrapper::Set_Texture(1,edgeTex);
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x7B);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_LESSEQUAL); //pass pixels who's alpha is not zero
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
- DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
- DX8Wrapper::Set_Texture(0,edgeTex);
- DX8Wrapper::Set_Texture(1, NULL);
- // Draw the custom edge.
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x84);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL); //pass pixels who's alpha is not zero
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
- DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
- #if 0 // Dumps out unmasked data.
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, false); //test pixels if transparent(clipped) before rendering.
- DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
- #endif
- DX8Wrapper::Set_Texture(1, NULL);
- if (cloudTexture) {
- DX8Wrapper::Set_Shader(detailOpaqueShader);
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Set_Texture(1,edgeTex);
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Set_Texture(0,cloudTexture);
- DX8Wrapper::Apply_Render_State_Changes();
- #if 1
- DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1 );
- #endif
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x80);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_NOTEQUAL); //pass pixels who's alpha is not zero
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
- DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
- }
- if (noiseTexture) {
- DX8Wrapper::Set_Texture(1, NULL);
- DX8Wrapper::Set_Texture(0,noiseTexture);
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Set_Texture(1,edgeTex);
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x80);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_NOTEQUAL); //pass pixels who's alpha is not zero
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
- DX8Wrapper::Draw_Triangles( m_curEdgingIndexOffset, m_curNumEdgingIndices/3, 0, m_curNumEdgingVertices);
- }
- }
|