W3DWater.cpp 122 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514
  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: W3DWater.cpp /////////////////////////////////////////////////////////////////////////////
  24. // Created: Mark Wilczynski, June 2001
  25. // Desc: Draw reflective water surface. Also handles drawing of waves/ripples
  26. // on the surface.
  27. ///////////////////////////////////////////////////////////////////////////////////////////////////
  28. #define SCROLL_UV
  29. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  30. #include "stdio.h"
  31. #include "W3DDevice/GameClient/W3DWater.h"
  32. #include "W3DDevice/GameClient/heightmap.h"
  33. #include "W3DDevice/GameClient/W3DShroud.h"
  34. #include "W3DDevice/GameClient/W3DWaterTracks.h"
  35. #include "W3DDevice/GameClient/W3DAssetManager.h"
  36. #include "texture.h"
  37. #include "assetmgr.h"
  38. #include "rinfo.h"
  39. #include "camera.h"
  40. #include "scene.h"
  41. #include "dx8wrapper.h"
  42. #include "light.h"
  43. #include "D3dx8math.h"
  44. #include "simplevec.h"
  45. #include "mesh.h"
  46. #include "matinfo.h"
  47. #include "Common/GameState.h"
  48. #include "Common/GlobalData.h"
  49. #include "Common/PerfTimer.h"
  50. #include "Common/Xfer.h"
  51. #include "Common/GameLOD.h"
  52. #include "GameClient/Water.h"
  53. #include "GameLogic/GameLogic.h"
  54. #include "GameLogic/PolygonTrigger.h"
  55. #include "GameLogic/ScriptEngine.h"
  56. #include "W3DDevice/GameClient/W3DShaderManager.h"
  57. #include "W3DDevice/GameClient/W3DDisplay.h"
  58. #include "W3DDevice/GameClient/W3DPoly.h"
  59. #include "W3DDevice/GameClient/W3DScene.h"
  60. #include "W3DDevice/GameClient/W3DCustomScene.h"
  61. #ifdef _INTERNAL
  62. // for occasional debugging...
  63. //#pragma optimize("", off)
  64. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  65. #endif
  66. #define MIPMAP_BUMP_TEXTURE
  67. // DEFINES ////////////////////////////////////////////////////////////////////////////////////////
  68. #define SKYPLANE_SIZE (384.0f*MAP_XY_FACTOR)
  69. #define SKYPLANE_HEIGHT (30.0f)
  70. #define SKYBODY_TEXTURE "TSMoonLarg.tga"
  71. #define SKYBODY_SIZE 45.0f //extent or radius of sky body
  72. #define SKYBODY_X 150.0f //location of skybody
  73. #define SKYBODY_Y 550.0f //location of skybody
  74. /* in the bay
  75. #define SKYBODY_X 120.0f //location of skybody
  76. #define SKYBODY_Y 75.0f //location of skybody
  77. */
  78. #define SKYBODY_HEIGHT SKYPLANE_HEIGHT //altitude of sky body (z-buffer disabled, so can equal sky height).
  79. //GeForce3 water system defines
  80. #define PATCH_SIZE 15 //number of vertices on patch edge. Large patches may waste vertices off edge of screen.
  81. #define PATCH_UV_TILES 42 //number of times the bump map texture is tiled across patch (must be integer!).
  82. #define PATCH_SCALE (4.0f * MAP_XY_FACTOR) //horizontal scale factor. Adjust this and size to get desired vertex density.
  83. #define SEA_REFLECTION_SIZE 256 //dimensions of reflection texture
  84. #define SEA_BUMP_SCALE (0.06f) //scales the du/dv offsets stored in bump map (~ amount to perturb)
  85. #define BUMP_SIZE (50.f)
  86. #define REFLECTION_FACTOR 0.1f
  87. #define PATCH_WIDTH (PATCH_SIZE-1) //internal defines
  88. #define PATCH_UV_SCALE ((Real)PATCH_UV_TILES/(Real)PATCH_WIDTH)
  89. //3D Grid Mesh Water defines.
  90. #define WATER_MESH_OPACITY 0.5f
  91. #define WATER_MESH_X_VERTICES 128
  92. #define WATER_MESH_Y_VERTICES 128
  93. #define WATER_MESH_SPACING MAP_XY_FACTOR //same as terrain
  94. #ifdef USE_MESH_NORMALS
  95. #define WATER_MESH_FVF DX8_FVF_XYZNDUV2
  96. typedef VertexFormatXYZNDUV2 MaterMeshVertexFormat;
  97. #else
  98. #define WATER_MESH_FVF DX8_FVF_XYZDUV2
  99. typedef VertexFormatXYZDUV2 MaterMeshVertexFormat;
  100. #endif
  101. // Converts a FLOAT to a DWORD for use in SetRenderState() calls
  102. static inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
  103. #define DRAW_WATER_WAKES
  104. /// @todo: Fix clipping of objects that intersect the mirror surface
  105. //#define CLIP_GEOMETRY_TO_PLANE // this enables clipping of objects that intersect the mirror surfaces
  106. // Some shader combinations that can be useful in rendering water:
  107. // Modulate stage0 with stage1 texture. Also modulate stage 0 with vertex color.
  108. #define SC_DETAIL_BLEND ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
  109. ShaderClass::SRCBLEND_SRC_ALPHA,ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
  110. ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, ShaderClass::DETAILCOLOR_DETAILBLEND, ShaderClass::DETAILALPHA_DISABLE) )
  111. // Just a z-buffer fill, nothing is written to the color buffer.
  112. #define SC_ZFILL_BLEND ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_DISABLE, ShaderClass::SRCBLEND_ZERO, \
  113. ShaderClass::DSTBLEND_ONE, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  114. ShaderClass::DETAILCOLOR_SCALE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, \
  115. ShaderClass::DETAILCOLOR_SCALE, ShaderClass::DETAILALPHA_DISABLE) )
  116. // No texturing, just vertex color with vertex alpha
  117. #define SC_ZFILL_BLENDx ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE, \
  118. ShaderClass::SRCBLEND_ZERO, ShaderClass::DSTBLEND_SRC_COLOR, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
  119. ShaderClass::TEXTURING_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, \
  120. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  121. // Modulate blended with vertex alpha modulation
  122. #define SC_ZFILL_MODULATE_TEX ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
  123. ShaderClass::SRCBLEND_ZERO, ShaderClass::DSTBLEND_SRC_COLOR, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
  124. ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  125. // Alpha blended with vertex alpha modulation
  126. #define SC_ZFILL_ALPHA_TEX ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
  127. ShaderClass::SRCBLEND_SRC_ALPHA, ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_DISABLE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
  128. ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  129. // Alpha blended with vertex alpha modulation
  130. #define SC_OPAQUE_TEXONLY ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
  131. ShaderClass::SRCBLEND_ONE, ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_DISABLE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
  132. ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  133. // Alpha blended with vertex alpha modulation
  134. #define SC_ZFILL_BLEND3 ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
  135. ShaderClass::SRCBLEND_SRC_ALPHA, ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
  136. ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  137. static ShaderClass zFillAlphaShader(SC_ZFILL_BLEND3);
  138. static ShaderClass blendStagesShader(SC_DETAIL_BLEND);
  139. WaterRenderObjClass *TheWaterRenderObj=NULL; ///<global water rendering object
  140. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  141. void doSkyBoxSet(Bool startDraw)
  142. {
  143. if (TheWritableGlobalData)
  144. TheWritableGlobalData->m_drawSkyBox = startDraw;
  145. }
  146. #define DONUT_SIDES 90
  147. #define INNER_RADIUS 200.0f
  148. #define OUTER_RADIUS 250.0f
  149. #define TEXTURE_REPEAT_COUNT 16
  150. #define DONUT_HEIGHT 15.0f
  151. //#define DO_FLAT_DONUT
  152. #define AMP_SCALE (30.0f/120.0f)
  153. #define WAVE_FREQ 0.3f
  154. #define AMP_SCALE2 (10.0f/120.0f)
  155. #define NOISE_FREQ (2.0f*PI/WAVE_FREQ)
  156. #define NOISE_REPEAT_FACTOR ((float)(1.0f/(16.0f)))
  157. static Bool wireframeForDebug = 0;
  158. void WaterRenderObjClass::setupJbaWaterShader(void)
  159. {
  160. if (!TheWaterTransparency->m_additiveBlend)
  161. DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaShader);
  162. else
  163. DX8Wrapper::Set_Shader(ShaderClass::_PresetAdditiveShader);
  164. VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  165. DX8Wrapper::Set_Material(vmat);
  166. REF_PTR_RELEASE(vmat);
  167. m_riverTexture->Get_Filter().Set_Mag_Filter(TextureFilterClass::FILTER_TYPE_BEST);
  168. m_riverTexture->Get_Filter().Set_Min_Filter(TextureFilterClass::FILTER_TYPE_BEST);
  169. m_riverTexture->Get_Filter().Set_Mip_Mapping(TextureFilterClass::FILTER_TYPE_BEST);
  170. // Setting *setting=&m_settings[m_tod];
  171. DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
  172. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_ADD );
  173. if (!m_riverAlphaEdge->Is_Initialized())
  174. m_riverAlphaEdge->Init();
  175. DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,m_riverAlphaEdge->Peek_D3D_Texture());
  176. DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  177. DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  178. DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, 0);
  179. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, 0);
  180. DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_TEXCOORDINDEX, 1);
  181. Bool doSparkles = true;
  182. if (m_riverWaterPixelShader && doSparkles) {
  183. if (!m_waterSparklesTexture->Is_Initialized())
  184. m_waterSparklesTexture->Init();
  185. DX8Wrapper::_Get_D3D_Device8()->SetTexture(1,m_waterSparklesTexture->Peek_D3D_Texture());
  186. if (!m_waterNoiseTexture->Is_Initialized())
  187. m_waterNoiseTexture->Init();
  188. DX8Wrapper::_Get_D3D_Device8()->SetTexture(2,m_waterNoiseTexture->Peek_D3D_Texture());
  189. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  190. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  191. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
  192. // Two output coordinates are used.
  193. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  194. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  195. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  196. D3DXMATRIX inv;
  197. float det;
  198. Matrix4x4 curView;
  199. DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
  200. D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
  201. D3DXMATRIX scale;
  202. D3DXMatrixScaling(&scale, NOISE_REPEAT_FACTOR, NOISE_REPEAT_FACTOR,1);
  203. D3DXMATRIX destMatrix = inv * scale;
  204. D3DXMatrixTranslation(&scale, m_riverVOrigin, m_riverVOrigin,0);
  205. destMatrix = destMatrix*scale;
  206. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, *(Matrix4x4*)&destMatrix);
  207. }
  208. m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  209. m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  210. m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  211. m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  212. m_pDev->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  213. m_pDev->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  214. m_pDev->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  215. m_pDev->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  216. if (m_riverWaterPixelShader){
  217. DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(0, D3DXVECTOR4(REFLECTION_FACTOR, REFLECTION_FACTOR, REFLECTION_FACTOR, 1.0f), 1);
  218. DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_riverWaterPixelShader);
  219. }
  220. }
  221. //-------------------------------------------------------------------------------------------------
  222. /** Destructor. Releases w3d assets. */
  223. //-------------------------------------------------------------------------------------------------
  224. WaterRenderObjClass::~WaterRenderObjClass(void)
  225. {
  226. REF_PTR_RELEASE(m_meshVertexMaterialClass);
  227. REF_PTR_RELEASE(m_vertexMaterialClass);
  228. REF_PTR_RELEASE(m_meshLight);
  229. REF_PTR_RELEASE(m_alphaClippingTexture);
  230. REF_PTR_RELEASE (m_skyBox);
  231. REF_PTR_RELEASE (m_riverTexture);
  232. REF_PTR_RELEASE (m_whiteTexture);
  233. REF_PTR_RELEASE (m_waterNoiseTexture);
  234. REF_PTR_RELEASE (m_riverAlphaEdge);
  235. REF_PTR_RELEASE (m_waterSparklesTexture);
  236. Int i;
  237. for(i=0; i<TIME_OF_DAY_COUNT; i++)
  238. { REF_PTR_RELEASE(m_settings[i].skyTexture);
  239. REF_PTR_RELEASE(m_settings[i].waterTexture);
  240. }
  241. i=NUM_BUMP_FRAMES;
  242. while (i--)
  243. { SAFE_RELEASE( m_pBumpTexture[i]);
  244. SAFE_RELEASE( m_pBumpTexture2[i]);
  245. }
  246. if (m_meshData)
  247. delete [] m_meshData;
  248. m_meshData = NULL;
  249. m_meshDataSize = 0;
  250. //Release strings allocated inside global water settings.
  251. for (i=0; i<TIME_OF_DAY_COUNT; i++)
  252. { WaterSettings[i].m_skyTextureFile.clear();
  253. WaterSettings[i].m_waterTextureFile.clear();
  254. }
  255. ((WaterTransparencySetting*)TheWaterTransparency.getNonOverloadedPointer())->deleteInstance();
  256. TheWaterTransparency = NULL;
  257. ReleaseResources();
  258. if (m_waterTrackSystem)
  259. delete m_waterTrackSystem;
  260. }
  261. //-------------------------------------------------------------------------------------------------
  262. /** Constructor. Just nulls out some variables. */
  263. //-------------------------------------------------------------------------------------------------
  264. WaterRenderObjClass::WaterRenderObjClass(void)
  265. {
  266. memset( &m_settings, 0, sizeof( m_settings ) );
  267. m_dx=0;
  268. m_dy=0;
  269. m_indexBuffer=NULL;
  270. m_waterTrackSystem = NULL;
  271. m_doWaterGrid = FALSE;
  272. m_meshVertexMaterialClass=NULL;
  273. m_meshLight=NULL;
  274. m_vertexMaterialClass=NULL;
  275. m_alphaClippingTexture=NULL;
  276. m_useCloudLayer=true;
  277. m_waterType = WATER_TYPE_0_TRANSLUCENT;
  278. m_tod=TIME_OF_DAY_AFTERNOON;
  279. m_pReflectionTexture=NULL;
  280. m_skyBox=NULL;
  281. m_vertexBufferD3D=NULL;
  282. m_indexBufferD3D=NULL;
  283. m_vertexBufferD3DOffset=0;
  284. m_dwWavePixelShader=NULL;
  285. m_dwWaveVertexShader=NULL;
  286. m_meshData=NULL;
  287. m_meshDataSize = 0;
  288. m_meshInMotion = FALSE;
  289. m_gridOrigin=Vector2(0,0);
  290. m_gridDirectionX=Vector2(1.0f,0.0f);
  291. m_gridDirectionY=Vector2(1.0f,0.0f);
  292. m_gridCellSize=WATER_MESH_SPACING;
  293. m_gridCellsX=WATER_MESH_X_VERTICES;
  294. m_gridCellsY=WATER_MESH_Y_VERTICES;
  295. m_gridWidth = m_gridCellsX * m_gridCellSize;
  296. m_gridHeight = m_gridCellsY * m_gridCellSize;
  297. Int i=NUM_BUMP_FRAMES;
  298. while (i--)
  299. m_pBumpTexture[i]=NULL;
  300. m_riverVOrigin=0;
  301. m_riverTexture=NULL;
  302. m_whiteTexture=NULL;
  303. m_waterNoiseTexture=NULL;
  304. m_riverAlphaEdge=NULL;
  305. m_waterPixelShader=0; ///<D3D handle to pixel shader.
  306. m_riverWaterPixelShader=0; ///<D3D handle to pixel shader.
  307. m_trapezoidWaterPixelShader=0; ///<D3D handle to pixel shader.
  308. m_waterSparklesTexture=0;
  309. m_riverXOffset=0;
  310. m_riverYOffset=0;
  311. }
  312. //-------------------------------------------------------------------------------------------------
  313. /** WW3D method that returns object bounding sphere used in frustum culling*/
  314. //-------------------------------------------------------------------------------------------------
  315. void WaterRenderObjClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  316. {
  317. //Since this object is more of a system (containing lots of water pieces),
  318. //let's disable culling by making bounds huge. Let each piece do it's own cull.
  319. Vector3 ObjSpaceCenter(0,0,0);
  320. // Vector3 ObjSpaceRadius(m_dx,m_dy,0);
  321. Vector3 ObjSpaceRadius(50000,50000,0);
  322. sphere.Init(ObjSpaceCenter,ObjSpaceRadius.Length());
  323. }
  324. //-------------------------------------------------------------------------------------------------
  325. /** WW3D method that returns object bounding box used in collision detection*/
  326. //-------------------------------------------------------------------------------------------------
  327. void WaterRenderObjClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  328. {
  329. //Since this object is more of a system (containing lots of water pieces),
  330. //let's disable culling by making bounds huge. Let each piece do it's own cull.
  331. Vector3 ObjSpaceCenter(0,0,0);
  332. Vector3 ObjSpaceExtents(50000,50000,0.001f*m_dy); //since mirror is a plane, it has no thickness. Set to m_dy/1000.
  333. box.Init(ObjSpaceCenter,ObjSpaceExtents);
  334. }
  335. //-------------------------------------------------------------------------------------------------
  336. /** returns the class id, so the scene can tell what kind of render object it has. */
  337. //-------------------------------------------------------------------------------------------------
  338. Int WaterRenderObjClass::Class_ID(void) const
  339. {
  340. return RenderObjClass::CLASSID_UNKNOWN;
  341. }
  342. //-------------------------------------------------------------------------------------------------
  343. /** Not used, but required virtual method. */
  344. //-------------------------------------------------------------------------------------------------
  345. RenderObjClass * WaterRenderObjClass::Clone(void) const
  346. {
  347. assert(false);
  348. return NULL;
  349. }
  350. //-------------------------------------------------------------------------------------------------
  351. /** Copies raw bits from pBumpSrc (a regular grayscale texture) into a D3D
  352. * bump-map format. */
  353. //-------------------------------------------------------------------------------------------------
  354. HRESULT WaterRenderObjClass::initBumpMap(LPDIRECT3DTEXTURE8 *pTex, TextureClass *pBumpSource)
  355. {
  356. SurfaceClass::SurfaceDescription d3dsd;
  357. SurfaceClass * surf;
  358. D3DLOCKED_RECT d3dlr;
  359. DWORD dwSrcPitch;
  360. BYTE* pSrc;
  361. Int numLevels;
  362. #ifdef MIPMAP_BUMP_TEXTURE
  363. pBumpSource->Get_Level_Description(d3dsd);
  364. if (Get_Bytes_Per_Pixel(d3dsd.Format) != 4)
  365. {
  366. // LORENZEN WAS BUGGED BY THIS,
  367. // DEBUG_CRASH(("WaterRenderObjClass::Invalid BumpMap format - Was it compressed?") );
  368. return S_OK;
  369. }
  370. if (pBumpSource->Peek_D3D_Texture())
  371. {
  372. numLevels=pBumpSource->Peek_D3D_Texture()->GetLevelCount();
  373. }
  374. else
  375. return S_OK;
  376. pTex[0]=DX8Wrapper::_Create_DX8_Texture(d3dsd.Width,d3dsd.Height,WW3D_FORMAT_U8V8,MIP_LEVELS_ALL,D3DPOOL_MANAGED,false);
  377. for (Int level=0; level < numLevels; level++)
  378. {
  379. surf=pBumpSource->Get_Surface_Level(level);
  380. surf->Get_Description(d3dsd);
  381. pSrc=(unsigned char *)surf->Lock((int *)&dwSrcPitch);
  382. pTex[0]->LockRect( level, &d3dlr, 0, 0 );
  383. DWORD dwDstPitch = (DWORD)d3dlr.Pitch;
  384. BYTE* pDst = (BYTE*)d3dlr.pBits;
  385. for( DWORD y=0; y<d3dsd.Height; y++ )
  386. {
  387. BYTE* pDstT = pDst;
  388. BYTE* pSrcB0 = (BYTE*)pSrc;
  389. BYTE* pSrcB1 = ( pSrcB0 + dwSrcPitch );
  390. BYTE* pSrcB2 = ( pSrcB0 - dwSrcPitch );
  391. if( y == d3dsd.Height-1 ) // Don't go past the last line
  392. pSrcB1 = pSrcB0;
  393. if( y == 0 ) // Don't go before first line
  394. pSrcB2 = pSrcB0;
  395. for( DWORD x=0; x<d3dsd.Width; x++ )
  396. {
  397. LONG v00 = 256-*(pSrcB0+0); // Get the current pixel
  398. LONG v01 = 256-*(pSrcB0+4); // and the pixel to the right
  399. LONG vM1 = 256-*(pSrcB0-4); // and the pixel to the left
  400. LONG v10 = 256-*(pSrcB1+0); // and the pixel one line below.
  401. LONG v1M = 256-*(pSrcB2+0); // and the pixel one line above.
  402. LONG iDu = (vM1-v01); // The delta-u bump value
  403. LONG iDv = (v1M-v10); // The delta-v bump value
  404. if( (v00 < vM1) && (v00 < v01) ) // If we are at valley
  405. {
  406. iDu = vM1-v00; // Choose greater of 1st order diffs
  407. if( iDu < v00-v01 )
  408. iDu = v00-v01;
  409. }
  410. // The luminance bump value (land masses are less shiny)
  411. WORD uL = ( v00>1 ) ? 63 : 127;
  412. switch( D3DFMT_V8U8)//m_BumpMapFormat )
  413. {
  414. case D3DFMT_V8U8:
  415. *pDstT++ = (BYTE)iDu;
  416. *pDstT++ = (BYTE)iDv;
  417. break;
  418. case D3DFMT_L6V5U5:
  419. *(WORD*)pDstT = (WORD)( ( (iDu>>3) & 0x1f ) << 0 );
  420. *(WORD*)pDstT |= (WORD)( ( (iDv>>3) & 0x1f ) << 5 );
  421. *(WORD*)pDstT |= (WORD)( ( ( uL>>2) & 0x3f ) << 10 );
  422. pDstT += 2;
  423. break;
  424. case D3DFMT_X8L8V8U8:
  425. *pDstT++ = (BYTE)iDu;
  426. *pDstT++ = (BYTE)iDv;
  427. *pDstT++ = (BYTE)uL;
  428. *pDstT++ = (BYTE)0L;
  429. break;
  430. }
  431. // Move one pixel to the left (src is 32-bpp)
  432. pSrcB0+=4; pSrcB1+=4; pSrcB2+=4;
  433. }
  434. // Move to the next line
  435. pSrc += dwSrcPitch; pDst += dwDstPitch;
  436. }
  437. pTex[0]->UnlockRect(level);
  438. surf->Unlock();
  439. REF_PTR_RELEASE (surf);
  440. }//for each level
  441. #else
  442. surf=pBumpSource->Get_Surface_Level();
  443. surf->Get_Description(d3dsd);
  444. pSrc=(unsigned char *)surf->Lock((int *)&dwSrcPitch);
  445. // Create the bumpmap's surface and texture objects
  446. m_pBumpTexture[i]=DX8Wrapper::_Create_DX8_Texture(d3dsd.Width,d3dsd.Height,WW3D_FORMAT_U8V8,TextureClass::MIP_LEVELS_1,D3DPOOL_MANAGED,false);
  447. // Fill the bits of the new texture surface with bits from
  448. // a private format.
  449. m_pBumpTexture[i]->LockRect( 0, &d3dlr, 0, 0 );
  450. DWORD dwDstPitch = (DWORD)d3dlr.Pitch;
  451. BYTE* pDst = (BYTE*)d3dlr.pBits;
  452. for( DWORD y=0; y<d3dsd.Height; y++ )
  453. {
  454. BYTE* pDstT = pDst;
  455. BYTE* pSrcB0 = (BYTE*)pSrc;
  456. BYTE* pSrcB1 = ( pSrcB0 + dwSrcPitch );
  457. BYTE* pSrcB2 = ( pSrcB0 - dwSrcPitch );
  458. if( y == d3dsd.Height-1 ) // Don't go past the last line
  459. pSrcB1 = pSrcB0;
  460. if( y == 0 ) // Don't go before first line
  461. pSrcB2 = pSrcB0;
  462. for( DWORD x=0; x<d3dsd.Width; x++ )
  463. {
  464. LONG v00 = 256-*(pSrcB0+0); // Get the current pixel
  465. LONG v01 = 256-*(pSrcB0+4); // and the pixel to the right
  466. LONG vM1 = 256-*(pSrcB0-4); // and the pixel to the left
  467. LONG v10 = 256-*(pSrcB1+0); // and the pixel one line below.
  468. LONG v1M = 256-*(pSrcB2+0); // and the pixel one line above.
  469. LONG iDu = (vM1-v01); // The delta-u bump value
  470. LONG iDv = (v1M-v10); // The delta-v bump value
  471. if( (v00 < vM1) && (v00 < v01) ) // If we are at valley
  472. {
  473. iDu = vM1-v00; // Choose greater of 1st order diffs
  474. if( iDu < v00-v01 )
  475. iDu = v00-v01;
  476. }
  477. // The luminance bump value (land masses are less shiny)
  478. WORD uL = ( v00>1 ) ? 63 : 127;
  479. switch( D3DFMT_V8U8)//m_BumpMapFormat )
  480. {
  481. case D3DFMT_V8U8:
  482. *pDstT++ = (BYTE)iDu;
  483. *pDstT++ = (BYTE)iDv;
  484. break;
  485. case D3DFMT_L6V5U5:
  486. *(WORD*)pDstT = (WORD)( ( (iDu>>3) & 0x1f ) << 0 );
  487. *(WORD*)pDstT |= (WORD)( ( (iDv>>3) & 0x1f ) << 5 );
  488. *(WORD*)pDstT |= (WORD)( ( ( uL>>2) & 0x3f ) << 10 );
  489. pDstT += 2;
  490. break;
  491. case D3DFMT_X8L8V8U8:
  492. *pDstT++ = (BYTE)iDu;
  493. *pDstT++ = (BYTE)iDv;
  494. *pDstT++ = (BYTE)uL;
  495. *pDstT++ = (BYTE)0L;
  496. break;
  497. }
  498. // Move one pixel to the left (src is 32-bpp)
  499. pSrcB0+=4; pSrcB1+=4; pSrcB2+=4;
  500. }
  501. // Move to the next line
  502. pSrc += dwSrcPitch; pDst += dwDstPitch;
  503. }
  504. m_pBumpTexture[i]->UnlockRect(0);
  505. surf->Unlock();
  506. #endif
  507. return S_OK;
  508. }
  509. //-------------------------------------------------------------------------------------------------
  510. /** Create and fill a D3D vertex buffer with water surface vertices */
  511. //-------------------------------------------------------------------------------------------------
  512. HRESULT WaterRenderObjClass::generateVertexBuffer( Int sizeX, Int sizeY, Int vertexSize, Bool doStatic)
  513. {
  514. m_numVertices=sizeX*sizeY;
  515. //Assuming dynamic vertex buffer, allocate maximum multiple of required size to allow rendering from
  516. //different parts of the buffer. 5-15-03: Disabled this since we use DISCARD mode instead to avoid Nvidia Runtime bug. -MW
  517. //m_numVertices=(65536 / (sizeX*sizeY))*sizeX*sizeY;
  518. SEA_PATCH_VERTEX* pVertices;
  519. Setting *setting=&m_settings[m_tod];
  520. HRESULT hr;
  521. //default setting for a dynamic vertex buffer
  522. D3DPOOL pool = D3DPOOL_DEFAULT;
  523. DWORD usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
  524. DWORD fvf = WATER_MESH_FVF;
  525. if (doStatic)
  526. { //change settings for a static vertex buffer
  527. pool = D3DPOOL_MANAGED;
  528. usage = D3DUSAGE_WRITEONLY;
  529. fvf=0;// DX8 Docs confusing on this. Say no FVF for vertex shaders. Else DX8_FVF_XYZDUV1;
  530. m_numVertices=sizeX*sizeY;
  531. }
  532. if (m_vertexBufferD3D == NULL)
  533. { // Create vertex buffer
  534. if (FAILED(hr=m_pDev->CreateVertexBuffer
  535. (
  536. m_numVertices*vertexSize,
  537. usage,
  538. fvf,
  539. pool,
  540. &m_vertexBufferD3D
  541. )))
  542. return hr;
  543. }
  544. m_vertexBufferD3DOffset=0;
  545. if (!doStatic)
  546. return S_OK; //only create the buffer, other code will fill it.
  547. // load results into buffer
  548. if (FAILED(hr=m_vertexBufferD3D->Lock
  549. (
  550. 0,
  551. m_numVertices*sizeof(SEA_PATCH_VERTEX),
  552. (BYTE**)&pVertices,
  553. 0//D3DLOCK_DISCARD
  554. )))
  555. return hr;
  556. Int x,z;
  557. for (z=0; z<sizeY; z++)
  558. {
  559. for (x=0; x<sizeX; x++)
  560. {
  561. pVertices->x=(float)x;
  562. pVertices->y=m_level;
  563. pVertices->z=(float)z;
  564. pVertices->tu=(float)x*PATCH_UV_SCALE;
  565. pVertices->tv=(float)z*PATCH_UV_SCALE;
  566. pVertices->c=setting->transparentWaterDiffuse; //vertex alpha/color
  567. pVertices++;
  568. }
  569. }
  570. if (FAILED(hr=m_vertexBufferD3D->Unlock())) return hr;
  571. return S_OK;
  572. }
  573. //-------------------------------------------------------------------------------------------------
  574. /** Create and fill a D3D index buffer with water surface strip indices */
  575. //-------------------------------------------------------------------------------------------------
  576. HRESULT WaterRenderObjClass::generateIndexBuffer(Int sizeX, Int sizeY)
  577. {
  578. HRESULT hr;
  579. //Will need SizeY-1 strips, each of length SizeX*2 (2 indices per strip segment).
  580. //Will also need 2 extra indices to connect each strip to next one (except last strip)
  581. //Total index buffer size = (SizeY-1)*(SizeX*2+2) - 2 (drop the extra 2 indices from last strip)
  582. m_numIndices=(sizeY-1)*(sizeX*2+2) - 2;
  583. //old way
  584. // Create index buffer
  585. WORD* pIndices;
  586. if (FAILED(hr=m_pDev->CreateIndexBuffer
  587. (
  588. (m_numIndices+2)*sizeof(WORD),
  589. D3DUSAGE_WRITEONLY,
  590. D3DFMT_INDEX16,
  591. D3DPOOL_MANAGED,
  592. &m_indexBufferD3D
  593. )))
  594. return hr;
  595. if (FAILED(hr=m_indexBufferD3D->Lock
  596. (
  597. 0,
  598. m_numIndices*sizeof(WORD),
  599. (BYTE**)&pIndices,
  600. 0
  601. )))
  602. return hr;
  603. Int i,j,k;
  604. for (i=0,j=0,k=0; i<m_numIndices; j++)
  605. {
  606. for (;k<(sizeX*(j+1)); k++,i+=2)
  607. {
  608. pIndices[i]=(UnsignedShort) k+sizeX;
  609. pIndices[i+1]=(UnsignedShort) k;
  610. }
  611. //Generate 4 degenerate triangle to connect current strip to next strip/row of map
  612. //To do this, we just repeat the last index of first strip and first index of new strip.
  613. //Any triangles with repeated vertices will be skipped during rendering.
  614. if (i<m_numIndices) //check if there is at least 1 more strip to go
  615. {
  616. pIndices[i]=k-1;
  617. pIndices[i+1]=k+sizeX;
  618. i+=2;
  619. }
  620. }
  621. /*Old way
  622. Int step=1;
  623. Int psize=(size-1)/step;
  624. m_numIndices=psize*((psize+1)*2)+(psize*2)-2;
  625. Int x,z,s_toggle=1;
  626. for (z=step; z<size; z+=step)
  627. {
  628. if (s_toggle)
  629. {
  630. for (x=0; x<(size-step); x+=step)
  631. {
  632. *pIndices++=(WORD)((z-0)*size+(x));
  633. *pIndices++=(WORD)((z-step)*size+(x));
  634. }
  635. *pIndices++=(WORD)((z-0)*size+(size-1));
  636. *pIndices++=(WORD)((z-step)*size+(size-1));
  637. // insert additional degenerate to start next row
  638. *pIndices++=pIndices[-2];
  639. *pIndices++=pIndices[-1];
  640. }
  641. else
  642. {
  643. *pIndices++=(WORD)((z-step)*size+(size-1));
  644. *pIndices++=(WORD)((z-0)*size+(size-1));
  645. for (x=size-1; x>0; x-=step)
  646. {
  647. *pIndices++=(WORD)((z-step)*size+(x-step));
  648. *pIndices++=(WORD)((z-0)*size+(x-step));
  649. }
  650. // insert additional degenerate to start next row
  651. *pIndices++=pIndices[-1];
  652. *pIndices++=pIndices[-1];
  653. }
  654. s_toggle=!s_toggle;
  655. }
  656. */
  657. if (FAILED(hr=m_indexBufferD3D->Unlock())) return hr;
  658. return S_OK;
  659. }
  660. //-------------------------------------------------------------------------------------------------
  661. /** Releases all w3d assets, to prepare for Reset device call. */
  662. //-------------------------------------------------------------------------------------------------
  663. void WaterRenderObjClass::ReleaseResources(void)
  664. {
  665. REF_PTR_RELEASE(m_indexBuffer);
  666. REF_PTR_RELEASE(m_pReflectionTexture);
  667. SAFE_RELEASE(m_vertexBufferD3D);
  668. SAFE_RELEASE(m_indexBufferD3D);
  669. if (m_waterTrackSystem)
  670. m_waterTrackSystem->ReleaseResources();
  671. if (m_dwWavePixelShader)
  672. m_pDev->DeletePixelShader(m_dwWavePixelShader);
  673. if (m_dwWaveVertexShader)
  674. m_pDev->DeleteVertexShader(m_dwWaveVertexShader);
  675. if (m_waterPixelShader)
  676. m_pDev->DeletePixelShader(m_waterPixelShader);
  677. if (m_trapezoidWaterPixelShader)
  678. m_pDev->DeletePixelShader(m_trapezoidWaterPixelShader);
  679. if (m_riverWaterPixelShader)
  680. m_pDev->DeletePixelShader(m_riverWaterPixelShader);
  681. m_dwWavePixelShader=0;
  682. m_dwWaveVertexShader=0;
  683. m_waterPixelShader = 0;
  684. m_trapezoidWaterPixelShader=0;
  685. m_riverWaterPixelShader=0;
  686. }
  687. //-------------------------------------------------------------------------------------------------
  688. /** (Re)allocates all W3D assets after a reset.. */
  689. //-------------------------------------------------------------------------------------------------
  690. void WaterRenderObjClass::ReAcquireResources(void)
  691. {
  692. HRESULT hr;
  693. m_indexBuffer=NEW_REF(DX8IndexBufferClass,(6));
  694. // Fill up the IB
  695. {
  696. DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexBuffer);
  697. UnsignedShort *ib=lockIdxBuffer.Get_Index_Array();
  698. //quad of 2 triangles:
  699. // 3-----2
  700. // | /|
  701. // | / |
  702. // |/ |
  703. // 0-----1
  704. ib[0]=3;
  705. ib[1]=0;
  706. ib[2]=2;
  707. ib[3]=2;
  708. ib[4]=0;
  709. ib[5]=1;
  710. }
  711. m_pDev=DX8Wrapper::_Get_D3D_Device8();
  712. //We're using the same grid for either 3D Water Mesh or Pixel/Vertex shader. Just
  713. //allocate the right size depending on usage
  714. if (m_meshData)
  715. {
  716. //Create new grid data
  717. if (FAILED(generateIndexBuffer(m_gridCellsX+1,m_gridCellsY+1)))
  718. return;
  719. if (FAILED(generateVertexBuffer(m_gridCellsX+1,m_gridCellsY+1,sizeof(MaterMeshVertexFormat),false)))
  720. return;
  721. }
  722. else
  723. if (m_waterType == WATER_TYPE_2_PVSHADER)
  724. { //pixel/vertex shader based water assets.
  725. if (FAILED(hr=generateIndexBuffer(PATCH_SIZE,PATCH_SIZE)))
  726. return;
  727. if (FAILED(hr=generateVertexBuffer(PATCH_SIZE,PATCH_SIZE,sizeof(SEA_PATCH_VERTEX),true)))
  728. return;
  729. //shader decleration
  730. DWORD Declaration[]=
  731. {
  732. (D3DVSD_STREAM(0)),
  733. (D3DVSD_REG(0, D3DVSDT_FLOAT3)), // Position
  734. (D3DVSD_REG(1, D3DVSDT_D3DCOLOR)), // Diffuse
  735. (D3DVSD_REG(2, D3DVSDT_FLOAT2)), // Bump map texture
  736. (D3DVSD_END())
  737. };
  738. hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\wave.pso", &Declaration[0], 0, false, &m_dwWavePixelShader);
  739. if (FAILED(hr))
  740. return;
  741. hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\wave.vso", &Declaration[0], 0, true, &m_dwWaveVertexShader);
  742. if (FAILED(hr))
  743. return;
  744. // Create reflection texture
  745. m_pReflectionTexture = DX8Wrapper::Create_Render_Target (SEA_REFLECTION_SIZE, SEA_REFLECTION_SIZE);
  746. }
  747. if (m_waterTrackSystem)
  748. m_waterTrackSystem->ReAcquireResources();
  749. if (W3DShaderManager::getChipset() >= DC_GENERIC_PIXEL_SHADER_1_1)
  750. {
  751. ID3DXBuffer *compiledShader;
  752. char *shader =
  753. "ps.1.1\n \
  754. tex t0 \n\
  755. tex t1 \n\
  756. tex t2 \n\
  757. tex t3\n\
  758. mul r0,v0,t0 ; blend vertex color into t0. \n\
  759. mul r1, t1, t2 ; mul\n\
  760. add r0.rgb, r0, t3\n\
  761. +mul r0.a, r0, t3\n\
  762. add r0.rgb, r0, r1\n";
  763. hr = D3DXAssembleShader( shader, strlen(shader), 0, NULL, &compiledShader, NULL);
  764. if (hr==0) {
  765. hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader((DWORD*)compiledShader->GetBufferPointer(), &m_riverWaterPixelShader);
  766. compiledShader->Release();
  767. }
  768. shader =
  769. "ps.1.1\n \
  770. tex t0 \n\
  771. tex t1 \n\
  772. texbem t2, t1 ; use t1 as env map adjustment on t2.\n\
  773. mul r0,v0,t0 ; blend vertex color into t0. \n\
  774. mul r1.rgb,t2,c0 ; reduce t2 (environment mapped reflection) by constant\n\
  775. add r0.rgb, r0, r1";
  776. hr = D3DXAssembleShader( shader, strlen(shader), 0, NULL, &compiledShader, NULL);
  777. if (hr==0) {
  778. hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader((DWORD*)compiledShader->GetBufferPointer(), &m_waterPixelShader);
  779. compiledShader->Release();
  780. }
  781. shader =
  782. "ps.1.1\n \
  783. tex t0 ;get water texture\n\
  784. tex t1 ;get white highlights on black background\n\
  785. tex t2 ;get white highlights with more tiling\n\
  786. tex t3 ; get black shroud \n\
  787. mul r0,v0,t0 ; blend vertex color and alpha into base texture. \n\
  788. mad r0.rgb, t1, t2, r0 ; blend sparkles and noise \n\
  789. mul r0.rgb, r0, t3 ; blend in black shroud \n\
  790. ;\n";
  791. hr = D3DXAssembleShader( shader, strlen(shader), 0, NULL, &compiledShader, NULL);
  792. if (hr==0) {
  793. hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader((DWORD*)compiledShader->GetBufferPointer(), &m_trapezoidWaterPixelShader);
  794. compiledShader->Release();
  795. }
  796. }
  797. //W3D Invalidate textures after losing the device and since we peek at the textures directly, it won't
  798. //know to reinit them for us. Do it here manually:
  799. if (m_riverTexture && !m_riverTexture->Is_Initialized())
  800. m_riverTexture->Init();
  801. if (m_waterNoiseTexture && !m_waterNoiseTexture->Is_Initialized())
  802. m_waterNoiseTexture->Init();
  803. if (m_riverAlphaEdge && !m_riverAlphaEdge->Is_Initialized())
  804. m_riverAlphaEdge->Init();
  805. if (m_waterSparklesTexture && !m_waterSparklesTexture->Is_Initialized())
  806. m_waterSparklesTexture->Init();
  807. if (m_whiteTexture && !m_whiteTexture->Is_Initialized())
  808. { m_whiteTexture->Init();
  809. SurfaceClass *surface=m_whiteTexture->Get_Surface_Level();
  810. surface->DrawPixel(0,0,0xffffffff);
  811. REF_PTR_RELEASE(surface);
  812. }
  813. }
  814. void WaterRenderObjClass::load(void)
  815. {
  816. if (m_waterTrackSystem)
  817. m_waterTrackSystem->loadTracks();
  818. }
  819. //-------------------------------------------------------------------------------------------------
  820. /** Initializes water with dimensions and parent scene.
  821. * During rendering, we will render a water surface of given dimensions
  822. * and reflect the parent scene in its surface. For now, waters are
  823. * forced to be rectangles. */
  824. //-------------------------------------------------------------------------------------------------
  825. Int WaterRenderObjClass::init(Real waterLevel, Real dx, Real dy, SceneClass *parentScene, WaterType type)
  826. {
  827. m_iBumpFrame=0;
  828. m_fBumpScale=SEA_BUMP_SCALE;
  829. m_dx=dx;
  830. m_dy=dy;
  831. m_level=waterLevel;
  832. m_LastUpdateTime=timeGetTime();
  833. m_uScrollPerMs=0.001f;
  834. m_vScrollPerMs=0.001f;
  835. m_uOffset=0;
  836. m_vOffset=0;
  837. m_parentScene=parentScene;
  838. m_waterType = type;
  839. /// Hack for now
  840. //m_waterType = WATER_TYPE_0_TRANSLUCENT;
  841. ///@todo: calculate a real normal/distance for arbitrary planes.
  842. m_planeNormal=Vector3(0,0,1); //water plane normal
  843. m_planeDistance=m_level; //water plane distance(always at zero for now)
  844. m_meshLight=NEW_REF(LightClass,(LightClass::DIRECTIONAL));
  845. m_meshLight->Set_Ambient(Vector3(0.1f,0.1f,0.1f));
  846. m_meshLight->Set_Diffuse(Vector3(1.0f,1.0f,1.0f));
  847. m_meshLight->Set_Specular(Vector3(1.0f,1.0f,1.0f));
  848. m_meshLight->Set_Position(Vector3(1000,1000,1000));
  849. //testLight->Set_Spot_Direction(Vector3(TheGlobalData->m_terrainLightX,TheGlobalData->m_terrainLightY,TheGlobalData->m_terrainLightZ));
  850. m_meshLight->Set_Spot_Direction(Vector3(-0.57f,-0.57f,-0.57f));
  851. //Setup material for 3D Mesh water.
  852. m_meshVertexMaterialClass=NEW_REF(VertexMaterialClass,());
  853. m_meshVertexMaterialClass->Set_Shininess(20.0);
  854. m_meshVertexMaterialClass->Set_Ambient(1.0f,1.0f,1.0f);
  855. m_meshVertexMaterialClass->Set_Diffuse(1.0f,1.0f,1.0f);
  856. m_meshVertexMaterialClass->Set_Specular(0.5,0.5,0.5);
  857. m_meshVertexMaterialClass->Set_Opacity(WATER_MESH_OPACITY);
  858. m_meshVertexMaterialClass->Set_Lighting(true);
  859. //
  860. // assign the data from the WaterSettings[] global to the data for this
  861. // render object (we at present only have one water plane)
  862. //
  863. loadSetting( &m_settings[ TIME_OF_DAY_MORNING ], TIME_OF_DAY_MORNING );
  864. loadSetting( &m_settings[ TIME_OF_DAY_AFTERNOON ], TIME_OF_DAY_AFTERNOON );
  865. loadSetting( &m_settings[ TIME_OF_DAY_EVENING ], TIME_OF_DAY_EVENING );
  866. loadSetting( &m_settings[ TIME_OF_DAY_NIGHT ], TIME_OF_DAY_NIGHT );
  867. Set_Sort_Level(2); //force water to be drawn after all other non translucent objects in scene.
  868. Set_Force_Visible(TRUE); //water is always visible since it's a composite object made of multiple planes all over the map.
  869. ReAcquireResources();
  870. #if 0 //MD does not support the old bump-mapped water at all so no point loading textures. -MW 8-11-03
  871. if (type == WATER_TYPE_2_PVSHADER || (W3DShaderManager::getChipset() >= DC_GENERIC_PIXEL_SHADER_1_1))
  872. { //geforce3 specific water requires some extra D3D assets
  873. m_pDev=DX8Wrapper::_Get_D3D_Device8();
  874. //save previous thumbnail mode
  875. bool thumbnails_enabled = WW3D::Get_Thumbnail_Enabled();
  876. WW3D::Set_Thumbnail_Enabled(false);
  877. //load bump map textures off disk
  878. TextureClass *pBumpSource; //temporary textures in a format W3D understands
  879. TextureClass *pBumpSource2; //temporary textures in a format W3D understands
  880. Int i;
  881. i=NUM_BUMP_FRAMES;
  882. while (i--)
  883. {
  884. char bump_name[128];
  885. sprintf(bump_name,"caust%.2d.tga",i);
  886. pBumpSource=WW3DAssetManager::Get_Instance()->Get_Texture(bump_name);
  887. sprintf(bump_name,"caustS%.2d.tga",i);
  888. pBumpSource2=WW3DAssetManager::Get_Instance()->Get_Texture(bump_name);
  889. initBumpMap(m_pBumpTexture+i, pBumpSource);
  890. initBumpMap(m_pBumpTexture2+i, pBumpSource2);
  891. WW3DAssetManager::Get_Instance()->Release_Texture(pBumpSource);
  892. WW3DAssetManager::Get_Instance()->Release_Texture(pBumpSource2);
  893. REF_PTR_RELEASE(pBumpSource);
  894. REF_PTR_RELEASE(pBumpSource2);
  895. }
  896. //restore previous thumpnail mode
  897. WW3D::Set_Thumbnail_Enabled(thumbnails_enabled);
  898. }
  899. #endif
  900. //Setup material for regular water
  901. m_vertexMaterialClass=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  902. m_shaderClass = zFillAlphaShader;//ShaderClass::_PresetAlphaShader;ShaderClass::_PresetOpaqueShader;//detailOpaqueShader;
  903. m_shaderClass.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE); //water should be visible from both sides
  904. //Assets used for all types of water
  905. m_alphaClippingTexture=WW3DAssetManager::Get_Instance()->Get_Texture(SKYBODY_TEXTURE);
  906. #ifdef CLIP_GEOMETRY_TO_PLANE
  907. m_alphaClippingTexture=WW3DAssetManager::Get_Instance()->Get_Texture("alphaclip.tga");
  908. #endif
  909. m_skyBox = ((W3DAssetManager*)W3DAssetManager::Get_Instance())->Create_Render_Obj( "new_skybox", TheGlobalData->m_skyBoxScale, 0);
  910. //Enable clamping on all textures used by the skybox (to reduce corner seams).
  911. if (m_skyBox && m_skyBox->Class_ID() == RenderObjClass::CLASSID_MESH)
  912. {
  913. MeshClass *mesh=(MeshClass*) m_skyBox;
  914. MaterialInfoClass *material = mesh->Get_Material_Info();
  915. for (Int i=0; i<material->Texture_Count(); i++)
  916. {
  917. if (material->Peek_Texture(i))
  918. {
  919. material->Peek_Texture(i)->Get_Filter().Set_U_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
  920. material->Peek_Texture(i)->Get_Filter().Set_V_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
  921. }
  922. }
  923. REF_PTR_RELEASE(material);
  924. }
  925. m_riverTexture=WW3DAssetManager::Get_Instance()->Get_Texture(TheWaterTransparency->m_standingWaterTexture.str());
  926. //For some reason setting a NULL texture does not result in 0xffffffff for pixel shaders so using explicit "white" texture.
  927. m_whiteTexture=MSGNEW("TextureClass") TextureClass(1,1,WW3D_FORMAT_A4R4G4B4,MIP_LEVELS_1);
  928. SurfaceClass *surface=m_whiteTexture->Get_Surface_Level();
  929. surface->DrawPixel(0,0,0xffffffff);
  930. REF_PTR_RELEASE(surface);
  931. m_waterNoiseTexture=WW3DAssetManager::Get_Instance()->Get_Texture("Noise0000.tga");
  932. m_riverAlphaEdge=WW3DAssetManager::Get_Instance()->Get_Texture("TWAlphaEdge.tga");
  933. m_waterSparklesTexture=WW3DAssetManager::Get_Instance()->Get_Texture("WaterSurfaceBubbles.tga");
  934. #ifdef DRAW_WATER_WAKES
  935. m_waterTrackSystem = NEW WaterTracksRenderSystem;
  936. m_waterTrackSystem->init();
  937. #endif
  938. return 0;
  939. }
  940. void WaterRenderObjClass::updateMapOverrides(void)
  941. {
  942. if (m_riverTexture && TheWaterTransparency->m_standingWaterTexture.compareNoCase(m_riverTexture->Get_Texture_Name()) != 0)
  943. {
  944. REF_PTR_RELEASE(m_riverTexture);
  945. m_riverTexture = WW3DAssetManager::Get_Instance()->Get_Texture(TheWaterTransparency->m_standingWaterTexture.str());
  946. }
  947. }
  948. // ------------------------------------------------------------------------------------------------
  949. // ------------------------------------------------------------------------------------------------
  950. void WaterRenderObjClass::reset( void )
  951. {
  952. // for vertex animated water mesh reset the values
  953. if( m_meshData)
  954. {
  955. Int i, j;
  956. WaterMeshData *pData;
  957. Int mx = m_gridCellsX + 1;
  958. Int my = m_gridCellsY + 1;
  959. // go through each mesh point and adjust the height according to the velocity
  960. for( j = 0, pData = m_meshData; j < (my + 2); j++ )
  961. {
  962. for( i = 0; i < (mx + 2); i++ )
  963. {
  964. // areset grid values for this cell
  965. pData->velocity = 0.0f;
  966. pData->height = 0.0f;
  967. pData->preferredHeight = 0.0f;
  968. pData->status = WaterRenderObjClass::AT_REST;
  969. // on to the next one
  970. pData++;
  971. } // end for i
  972. } // end for j
  973. // mesh data is no longer in motion
  974. m_meshInMotion = FALSE;
  975. } // end if, water type 3
  976. if (m_waterTrackSystem)
  977. m_waterTrackSystem->reset();
  978. }
  979. void WaterRenderObjClass::enableWaterGrid(Bool state)
  980. {
  981. m_doWaterGrid = state;
  982. m_drawingRiver = false;
  983. m_disableRiver = false;
  984. if (state && m_meshData == NULL)
  985. { //water type has changed, must allocate necessary assets for new water.
  986. //contains the current deformed water surface z(height) values. With 1 vertex invisible border
  987. //around surface to speed up normal calculations.
  988. m_meshDataSize = (m_gridCellsX+1+2)*(m_gridCellsY+1+2);
  989. m_meshData=NEW WaterMeshData[ m_meshDataSize ];
  990. memset(m_meshData,0,sizeof(WaterMeshData)*(m_gridCellsX+1+2)*(m_gridCellsY+1+2));
  991. reset();
  992. //Release existing grid data
  993. SAFE_RELEASE(m_vertexBufferD3D);
  994. SAFE_RELEASE(m_indexBufferD3D);
  995. //Create new grid data
  996. if (FAILED(generateIndexBuffer(m_gridCellsX+1,m_gridCellsY+1)))
  997. return;
  998. if (FAILED(generateVertexBuffer(m_gridCellsX+1,m_gridCellsY+1,sizeof(MaterMeshVertexFormat),false)))
  999. return;
  1000. }
  1001. }
  1002. // ------------------------------------------------------------------------------------------------
  1003. /** Update phase for water if we need it. This called once per client frame reguardless
  1004. * of how fast the logic framerate is running */
  1005. // ------------------------------------------------------------------------------------------------
  1006. void WaterRenderObjClass::update( void )
  1007. {
  1008. static UnsignedInt lastLogicFrame = 0;
  1009. UnsignedInt currLogicFrame = 0;
  1010. if( TheGameLogic )
  1011. currLogicFrame = TheGameLogic->getFrame();
  1012. m_riverVOrigin += 0.002f;
  1013. m_riverXOffset += (Real)(0.0125*33/5000);
  1014. m_riverYOffset += (Real)(2*0.0125*33/5000);
  1015. if (m_riverXOffset > 1) m_riverXOffset -= 1;
  1016. if (m_riverYOffset > 1) m_riverYOffset -= 1;
  1017. if (m_riverXOffset < -1) m_riverXOffset += 1;
  1018. if (m_riverYOffset < -1) m_riverYOffset += 1;
  1019. m_iBumpFrame++;
  1020. if (m_iBumpFrame >= NUM_BUMP_FRAMES) {
  1021. m_iBumpFrame = 0;
  1022. }
  1023. // we only process some things if the logic frame has changed
  1024. if( lastLogicFrame != currLogicFrame )
  1025. {
  1026. // for vertex animated water we need to update the vector field
  1027. if( m_doWaterGrid && m_meshInMotion == TRUE )
  1028. {
  1029. const Real PREFERRED_HEIGHT_FUDGE = 1.0f; ///< this is close enough to at rest
  1030. const Real AT_REST_VELOCITY_FUDGE = 1.0f; ///< when we're close enought to at rest height and velocity we will stop
  1031. const Real WATER_DAMPENING = 0.93f; ///< use with up force of 15.0
  1032. Int i, j;
  1033. Int mx = m_gridCellsX+1;
  1034. Int my = m_gridCellsY+1;
  1035. WaterMeshData *pData;
  1036. //
  1037. // we will mark the mesh as clean now ... if any of the fields are still in motion
  1038. // they will continue to mark the mesh as dirty so processing continues next frame
  1039. //
  1040. m_meshInMotion = FALSE;
  1041. // go through each mesh point and adjust the height according to the velocity
  1042. for( j = 0, pData = m_meshData; j < (my + 2); j++ )
  1043. {
  1044. for( i = 0; i < (mx + 2); i++ )
  1045. {
  1046. // only pay attention to mesh points that are in motion
  1047. if( BitTest( pData->status, WaterRenderObjClass::IN_MOTION ) )
  1048. {
  1049. // DAMPENING to slow the changes down
  1050. pData->velocity *= WATER_DAMPENING;
  1051. // if the height here is below our preferred height, we want to add upward force to counteract it
  1052. if( pData->height < pData->preferredHeight )
  1053. pData->velocity -= TheGlobalData->m_gravity * 3.0f;
  1054. else
  1055. pData->velocity += TheGlobalData->m_gravity * 3.0f;
  1056. // adjust the height at this grid location according to the current velocity
  1057. pData->height = pData->height + pData->velocity;
  1058. //
  1059. // if we are close enough to our preferred height and our velocity is small enough
  1060. // this will be our resting location
  1061. //
  1062. if( fabs( pData->height - pData->preferredHeight ) < PREFERRED_HEIGHT_FUDGE &&
  1063. fabs( pData->velocity ) < AT_REST_VELOCITY_FUDGE )
  1064. {
  1065. BitClear( pData->status, WaterRenderObjClass::IN_MOTION );
  1066. pData->height = pData->preferredHeight;
  1067. pData->velocity = 0.0f;
  1068. } // end if
  1069. else
  1070. {
  1071. // there is still motion in the mesh, we need to process next frame
  1072. m_meshInMotion = TRUE;
  1073. } // end else
  1074. } // end if
  1075. // on to the next one
  1076. pData++;
  1077. } // end for i
  1078. } // end for j
  1079. } // end if
  1080. // mark the last logic frame we processed on
  1081. lastLogicFrame = currLogicFrame;
  1082. } // end if, a logic frame has passed
  1083. } // end update
  1084. //-------------------------------------------------------------------------------------------------
  1085. //-------------------------------------------------------------------------------------------------
  1086. void WaterRenderObjClass::replaceSkyboxTexture(const AsciiString& oldTexName, const AsciiString& newTextName)
  1087. {
  1088. W3DAssetManager* assetManager = ((W3DAssetManager*)W3DAssetManager::Get_Instance());
  1089. assetManager->replacePrototypeTexture(m_skyBox, oldTexName.str(), newTextName.str());
  1090. //Enable clamping on all textures used by the skybox (to reduce corner seams).
  1091. if (m_skyBox && m_skyBox->Class_ID() == RenderObjClass::CLASSID_MESH)
  1092. {
  1093. MeshClass *mesh=(MeshClass*) m_skyBox;
  1094. MaterialInfoClass *material = mesh->Get_Material_Info();
  1095. for (Int i=0; i<material->Texture_Count(); i++)
  1096. {
  1097. if (material->Peek_Texture(i))
  1098. {
  1099. material->Peek_Texture(i)->Get_Filter().Set_U_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
  1100. material->Peek_Texture(i)->Get_Filter().Set_V_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
  1101. }
  1102. }
  1103. }
  1104. }
  1105. //-------------------------------------------------------------------------------------------------
  1106. /** Adjusts various water/sky rendering settings that depend on time of day. */
  1107. //-------------------------------------------------------------------------------------------------
  1108. void WaterRenderObjClass::setTimeOfDay(TimeOfDay tod)
  1109. {
  1110. m_tod=tod;
  1111. if (m_waterType == WATER_TYPE_2_PVSHADER)
  1112. generateVertexBuffer(PATCH_SIZE,PATCH_SIZE,sizeof(SEA_PATCH_VERTEX),true); //update the water mesh with new lighting/alpha
  1113. }
  1114. //-------------------------------------------------------------------------------------------------
  1115. /**Copies GDF settings dealing with a particular time of day into our own
  1116. * structures. Also allocates any required W3D assets (textures). */
  1117. //-------------------------------------------------------------------------------------------------
  1118. void WaterRenderObjClass::loadSetting( Setting *setting, TimeOfDay timeOfDay )
  1119. {
  1120. SurfaceClass::SurfaceDescription surfaceDesc;
  1121. // sanity
  1122. DEBUG_ASSERTCRASH( setting, ("WaterRenderObjClass::loadSetting, NULL setting\n") );
  1123. // textures
  1124. setting->skyTexture = WW3DAssetManager::Get_Instance()->Get_Texture( WaterSettings[ timeOfDay ].m_skyTextureFile.str() );
  1125. setting->waterTexture = WW3DAssetManager::Get_Instance()->Get_Texture( WaterSettings[ timeOfDay ].m_waterTextureFile.str() );
  1126. // texelss per unit
  1127. setting->skyTexelsPerUnit = WaterSettings[ timeOfDay ].m_skyTexelsPerUnit;
  1128. setting->waterTexture->Get_Level_Description( surfaceDesc, 0 );
  1129. setting->skyTexelsPerUnit /= (Real)surfaceDesc.Width;
  1130. // water repeat
  1131. setting->waterRepeatCount = WaterSettings[ timeOfDay ].m_waterRepeatCount;
  1132. // U and V scroll per ms
  1133. setting->uScrollPerMs = WaterSettings[ timeOfDay ].m_uScrollPerMs;
  1134. setting->vScrollPerMs = WaterSettings[ timeOfDay ].m_vScrollPerMs;
  1135. //
  1136. // vertex colors
  1137. //
  1138. // bottom left
  1139. setting->vertex00Diffuse = (WaterSettings[ timeOfDay ].m_vertex00Diffuse.red << 16) |
  1140. (WaterSettings[ timeOfDay ].m_vertex00Diffuse.green << 8) |
  1141. WaterSettings[ timeOfDay ].m_vertex00Diffuse.blue;
  1142. // top left
  1143. setting->vertex01Diffuse = (WaterSettings[ timeOfDay ].m_vertex01Diffuse.red << 16) |
  1144. (WaterSettings[ timeOfDay ].m_vertex01Diffuse.green << 8) |
  1145. WaterSettings[ timeOfDay ].m_vertex01Diffuse.blue;
  1146. // bottom right
  1147. setting->vertex10Diffuse = (WaterSettings[ timeOfDay ].m_vertex10Diffuse.red << 16) |
  1148. (WaterSettings[ timeOfDay ].m_vertex10Diffuse.green << 8) |
  1149. WaterSettings[ timeOfDay ].m_vertex10Diffuse.blue;
  1150. // top right
  1151. setting->vertex11Diffuse = (WaterSettings[ timeOfDay ].m_vertex11Diffuse.red << 16) |
  1152. (WaterSettings[ timeOfDay ].m_vertex11Diffuse.green << 8) |
  1153. WaterSettings[ timeOfDay ].m_vertex11Diffuse.blue;
  1154. // diffuse water color
  1155. setting->waterDiffuse = (WaterSettings[ timeOfDay ].m_waterDiffuseColor.alpha << 24) |
  1156. (WaterSettings[ timeOfDay ].m_waterDiffuseColor.red << 16) |
  1157. (WaterSettings[ timeOfDay ].m_waterDiffuseColor.green << 8) |
  1158. WaterSettings[ timeOfDay ].m_waterDiffuseColor.blue;
  1159. // transparent water color
  1160. setting->transparentWaterDiffuse = (WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.alpha << 24) |
  1161. (WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.red << 16) |
  1162. (WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.green << 8) |
  1163. WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.blue;
  1164. }
  1165. //-------------------------------------------------------------------------------------------------
  1166. /** Our water may use effects that require run-time rendered textures. These
  1167. * textures need to be updated before we start rendering to the main screen
  1168. * render target because D3D doesn't multiple render targets. */
  1169. //-------------------------------------------------------------------------------------------------
  1170. void WaterRenderObjClass::updateRenderTargetTextures(CameraClass *cam)
  1171. {
  1172. if (m_waterType == WATER_TYPE_2_PVSHADER && getClippedWaterPlane(cam, NULL) &&
  1173. TheTerrainRenderObject && TheTerrainRenderObject->getMap())
  1174. renderMirror(cam); //generate texture containing reflected scene
  1175. }
  1176. //-------------------------------------------------------------------------------------------------
  1177. /** Renders the reflected scene into an offscreen texture. */
  1178. //-------------------------------------------------------------------------------------------------
  1179. void WaterRenderObjClass::renderMirror(CameraClass *cam)
  1180. {
  1181. #ifdef EXTENDED_STATS
  1182. if (DX8Wrapper::stats.m_disableWater) {
  1183. return;
  1184. }
  1185. #endif
  1186. Matrix3D OldCameraMatrix=cam->Get_Transform();
  1187. Matrix4x4 FullMatrix4(cam->Get_Transform()); //copy 3x4 matrix into a 4x4
  1188. Vector3 WaterNormal(0,0,1); //normal of plane used for reflection
  1189. Vector4 WaterPlane(WaterNormal.X,WaterNormal.Y,WaterNormal.Z,m_level);
  1190. Vector3 rRight,rUp,rN,rPos; //orientation and translation vectors of camera
  1191. Matrix4x4 FullMatrix(FullMatrix4.Transpose()); //swap rows/columns
  1192. //reflect camera right vector
  1193. Real axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[0],WaterNormal);
  1194. rRight = (Vector3&)FullMatrix[0] - (2.0f*axis_distance*WaterNormal);
  1195. //reflect camera up vector
  1196. axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[1],WaterNormal);
  1197. rUp = (Vector3&)FullMatrix[1] - (2.0f*axis_distance*WaterNormal);
  1198. //reflect camera n vector
  1199. axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[2],WaterNormal);
  1200. rN = (Vector3&)FullMatrix[2] - (2.0f*axis_distance*WaterNormal);
  1201. //reflect camera position
  1202. axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[3],WaterNormal); //distance cam to origin
  1203. axis_distance -= WaterPlane.W; // subtract mirror plane distance to get distance camera to plane
  1204. rPos = (Vector3&)FullMatrix[3] - (2.0f*axis_distance*WaterNormal);
  1205. //generate a new camera matrix from reflected vectors
  1206. Matrix3D reflectedTransform(rRight,rUp,rN,rPos);
  1207. DX8Wrapper::Set_Render_Target_With_Z((TextureClass*)m_pReflectionTexture);
  1208. // Clear the backbuffer
  1209. WW3D::Begin_Render(false,true,Vector3(0.0f,0.0f,0.0f)); //clearing only z-buffer since background always filled with clouds
  1210. cam->Set_Transform( reflectedTransform );
  1211. //Force reflected image to be drawn into full texture size - not a viewport inside texture.
  1212. Vector2 vMin,vMax,vOldMax,vOldMin;
  1213. cam->Get_Viewport(vOldMin,vOldMax);
  1214. vMax.X=vMax.Y=1.0f;
  1215. vMin.X=vMin.Y=0.0f;
  1216. cam->Set_Viewport(vMin,vMax);
  1217. cam->Apply(); //force an update of all the camera dependent parameters like frustum clip planes
  1218. //flip the winding order of polygons to draw the reflected back sides.
  1219. ShaderClass::Invert_Backface_Culling(true);
  1220. // Render the scene
  1221. renderSky();
  1222. if (m_tod == TIME_OF_DAY_NIGHT)
  1223. renderSkyBody(&reflectedTransform);
  1224. WW3D::Render(m_parentScene,cam);
  1225. cam->Set_Transform(OldCameraMatrix); //restore original non-reflected matrix
  1226. cam->Set_Viewport(vOldMin,vOldMax);
  1227. cam->Apply(); //force an update of all the camera dependent parameters like frustum clip planes
  1228. ShaderClass::Invert_Backface_Culling(false);
  1229. WW3D::End_Render(false);
  1230. // Change the rendertarget back to the main backbuffer
  1231. DX8Wrapper::Set_Render_Target((IDirect3DSurface8 *)NULL);
  1232. }
  1233. //-------------------------------------------------------------------------------------------------
  1234. /** Renders (draws) the water.
  1235. * Algorithm:
  1236. * Draw reflected scene.
  1237. * Draw reflected sky layer(s) and bodies.
  1238. * Clear Zbuffer
  1239. * Fill Zbuffer by drawing water surface (allows proper sorting into regular scene).
  1240. * Draw non-reflected scene (done in regular app render loop).
  1241. *
  1242. * This algorithm doesn't apply to translucent water, which is rendered into a
  1243. * texture and rendered at end of scene. */
  1244. //-------------------------------------------------------------------------------------------------
  1245. //DECLARE_PERF_TIMER(Water)
  1246. void WaterRenderObjClass::Render(RenderInfoClass & rinfo)
  1247. {
  1248. //USE_PERF_TIMER(Water)
  1249. if (TheTerrainRenderObject && !TheTerrainRenderObject->getMap())
  1250. return; //no map has been loaded yet.
  1251. if (((RTS3DScene *)rinfo.Camera.Get_User_Data())->getCustomPassMode() == SCENE_PASS_ALPHA_MASK ||
  1252. ((SceneClass *)rinfo.Camera.Get_User_Data())->Get_Extra_Pass_Polygon_Mode() == SceneClass::EXTRA_PASS_CLEAR_LINE)
  1253. return; //water is not drawn in wireframe or custom scene passes
  1254. #ifdef EXTENDED_STATS
  1255. if (DX8Wrapper::stats.m_disableWater) {
  1256. return;
  1257. }
  1258. #endif
  1259. if (ShaderClass::Is_Backface_Culling_Inverted())
  1260. return; //the water object will not reflect in itself, so don't do anything if rendering a mirror.
  1261. //this water type needs to rendered after the rest of scene, so buffer it up for later
  1262. // If static sort lists are enabled and this mesh has a sort level, put it on the list instead
  1263. // of rendering it.
  1264. unsigned int sort_level = (unsigned int)Get_Sort_Level();
  1265. if (WW3D::Are_Static_Sort_Lists_Enabled() && sort_level != SORT_LEVEL_NONE)
  1266. {
  1267. WW3D::Add_To_Static_Sort_List(this, sort_level);
  1268. return;
  1269. }
  1270. switch(m_waterType)
  1271. {
  1272. case WATER_TYPE_0_TRANSLUCENT:
  1273. case WATER_TYPE_3_GRIDMESH:
  1274. //Draw the water surface as a bunch of alpha blended tiles covering areas where water is visible
  1275. renderWater();
  1276. if (!m_drawingRiver || m_disableRiver) {
  1277. renderWaterMesh(); //Draw water surface as 3D deforming mesh if it's enabled on this map.
  1278. }
  1279. break;
  1280. case WATER_TYPE_2_PVSHADER:
  1281. //Pixel/Vertex Shader based water which uses an off-screen rendered reflection texture
  1282. drawSea(rinfo); //draw water surface
  1283. break;
  1284. case WATER_TYPE_1_FB_REFLECTION:
  1285. {
  1286. //Normal frame buffer reflection water type. Non translucent. Legacy code we're not using anymore.
  1287. Matrix3D OldCameraMatrix=rinfo.Camera.Get_Transform();
  1288. Matrix4x4 FullMatrix4(rinfo.Camera.Get_Transform()); //copy 3x4 matrix into a 4x4
  1289. Vector3 WaterNormal(0,0,1); //normal of plane used for reflection
  1290. Vector4 WaterPlane(WaterNormal.X,WaterNormal.Y,WaterNormal.Z,m_level); //assume distance to origin 0
  1291. Vector3 rRight,rUp,rN,rPos; //orientation and translation vectors of camera
  1292. Matrix4x4 FullMatrix(FullMatrix4.Transpose()); //swap rows/columns
  1293. //reflect camera right vector
  1294. Real axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[0],WaterNormal);
  1295. rRight = (Vector3&)FullMatrix[0] - (2.0f*axis_distance*WaterNormal);
  1296. //reflect camera up vector
  1297. axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[1],WaterNormal);
  1298. rUp = (Vector3&)FullMatrix[1] - (2.0f*axis_distance*WaterNormal);
  1299. //reflect camera n vector
  1300. axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[2],WaterNormal);
  1301. rN = (Vector3&)FullMatrix[2] - (2.0f*axis_distance*WaterNormal);
  1302. //reflect camera position
  1303. axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[3],WaterNormal); //distance cam to origin
  1304. axis_distance -= WaterPlane.W; // subtract mirror plane distance to get distance camera to plane
  1305. rPos = (Vector3&)FullMatrix[3] - (2.0f*axis_distance*WaterNormal);
  1306. //generate a new camera matrix from reflected vectors
  1307. Matrix3D reflectedTransform(rRight,rUp,rN,rPos);
  1308. //flip the winding order of polygons to draw the reflected back sides.
  1309. ShaderClass::Invert_Backface_Culling(true);
  1310. #ifdef CLIP_GEOMETRY_TO_PLANE
  1311. // Set a clip plane, so that only objects above the water are reflected
  1312. WaterPlane.W *= -1.0f; //flip sign of plane distance for D3D use.
  1313. // DX8Wrapper::Set_DX8_Clip_Plane( 0, &WaterPlane.X );
  1314. // DX8Wrapper::Set_DX8_Render_State(D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 ); //turn on first clip plane
  1315. // Alternate Clipping Method using alpha testing hack!
  1316. /**************************************************************************************/
  1317. D3DXMATRIX inv;
  1318. D3DXMATRIX clipMatrix;
  1319. Real det;
  1320. Matrix4x4 curView;
  1321. //get current view matrix
  1322. DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
  1323. //get inverse of view matrix(= view to world matrix)
  1324. D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
  1325. //create clipping matrix by inserting our plane equation into the 1st column
  1326. D3DXMatrixIdentity(&clipMatrix);
  1327. clipMatrix(0,0)=WaterNormal.X;
  1328. clipMatrix(1,0)=WaterNormal.Y;
  1329. clipMatrix(2,0)=WaterNormal.Z;
  1330. clipMatrix(3,0)=WaterPlane.W+0.5f;
  1331. inv *=clipMatrix;
  1332. // Change texture wrapping mode to 'clamp' for texture stage 1
  1333. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  1334. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  1335. // Use CameraSpace vertices as input to matrix and use texture wrap mode from stage 1
  1336. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION|1);
  1337. // Two output coordinates are used.
  1338. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  1339. // Set texture generation matrix for stage 1
  1340. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, *((Matrix4*)&inv));
  1341. // Disable bilinear filtering
  1342. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
  1343. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
  1344. // Pass stage 0 texture data untouched(by modulating with white)
  1345. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //stage 1 texture
  1346. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); //previous stage texture
  1347. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); //module with white => does nothing
  1348. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); //stage 1 texture
  1349. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT ); //previous stage texture
  1350. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); //modulate with clipping texture
  1351. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x00);
  1352. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_NOTEQUAL); //pass pixels who's alpha is not zero
  1353. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
  1354. // Set clipping texture
  1355. m_alphaClippingTexture->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
  1356. m_alphaClippingTexture->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
  1357. m_alphaClippingTexture->Set_Min_Filter(TextureClass::FILTER_TYPE_NONE);
  1358. m_alphaClippingTexture->Set_Mag_Filter(TextureClass::FILTER_TYPE_NONE);
  1359. m_alphaClippingTexture->Set_Mip_Mapping(TextureClass::FILTER_TYPE_NONE);
  1360. DX8Wrapper::Set_Texture(0,m_alphaClippingTexture);
  1361. //TODO: Will have to make sure that the shader system is not resetting my stage 1 setup
  1362. //while rendering the scene
  1363. /*************************************************************************************/
  1364. #endif
  1365. #if 0 // No longer do simple rendering.
  1366. if (TheGlobalData->m_useWaterPlane)
  1367. {
  1368. //@todo : Would it be better to create a new camera or change the transform of the
  1369. //existing one?
  1370. rinfo.Camera.Set_Transform( reflectedTransform );
  1371. rinfo.Camera.Apply(); //force an update of all the camera dependent parameters like frustum clip planes
  1372. if(m_useCloudLayer)
  1373. {
  1374. if (TheGlobalData && TheGlobalData->m_drawEntireTerrain)
  1375. m_skyBox->Render(rinfo);
  1376. else
  1377. {
  1378. renderSky();
  1379. if (m_tod == TIME_OF_DAY_NIGHT)
  1380. renderSkyBody(&reflectedTransform);
  1381. }
  1382. }
  1383. WW3D::Render(m_parentScene,&rinfo.Camera);
  1384. rinfo.Camera.Set_Transform(OldCameraMatrix); //restore original non-reflected matrix
  1385. rinfo.Camera.Apply(); //force an update of all the camera dependent parameters like frustum clip planes
  1386. //clear the z-buffer to remove changes made by objects inside mirror
  1387. DX8Wrapper::Clear(false,true,Vector3(0.1f,0.1f,0.1f));
  1388. }
  1389. #endif
  1390. #ifdef CLIP_GEOMETRY_TO_PLANE
  1391. //restore default culling mode
  1392. // DX8Wrapper::Set_DX8_Render_State(D3DRS_CLIPPLANEENABLE, 0 ); //turn off first clip plane
  1393. //disable texture coordinate generation
  1394. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  1395. DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, false); //disable alpha testing
  1396. #endif
  1397. ShaderClass::Invert_Backface_Culling(false); //return culling back to normal
  1398. ShaderClass::Invalidate(); //reset shading system so it forces full state set.
  1399. renderWater();
  1400. } //WATER_TYPE_1
  1401. default:
  1402. break;
  1403. }//switch
  1404. if (TheGlobalData && TheGlobalData->m_drawSkyBox)
  1405. { //center skybox around camera
  1406. Vector3 pos=rinfo.Camera.Get_Position();
  1407. pos.Z = TheGlobalData->m_skyBoxPositionZ;
  1408. m_skyBox->Set_Position(pos);
  1409. m_skyBox->Render(rinfo);
  1410. }
  1411. //Clean up after any pixel shaders.
  1412. //Force render state apply so that the "NULL" texture gets applied to D3D, thus releasing shroud reference count.
  1413. DX8Wrapper::Apply_Render_State_Changes();
  1414. DX8Wrapper::Invalidate_Cached_Render_States();
  1415. if (m_waterTrackSystem)
  1416. m_waterTrackSystem->flush(rinfo);
  1417. // renderWaterMesh();
  1418. // renderWaterWave();
  1419. }
  1420. //-------------------------------------------------------------------------------------------------
  1421. /** Clips the water plane to the current camera frustum and returns a bounding
  1422. * box enclosing the clipped plane. Returns false if water plane is not visible. */
  1423. //-------------------------------------------------------------------------------------------------
  1424. Bool WaterRenderObjClass::getClippedWaterPlane(CameraClass *cam, AABoxClass *box)
  1425. {
  1426. const FrustumClass & frustum = cam->Get_Frustum();
  1427. ClipPolyClass ClippedPoly0;
  1428. ClipPolyClass ClippedPoly1;
  1429. ///@todo: generate proper sized polygon
  1430. ClippedPoly0.Reset();
  1431. ClippedPoly0.Add_Vertex(Vector3(0,0,m_level));
  1432. ClippedPoly0.Add_Vertex(Vector3(0,m_dy,m_level));
  1433. ClippedPoly0.Add_Vertex(Vector3(m_dx,m_dy,m_level));
  1434. ClippedPoly0.Add_Vertex(Vector3(m_dx,0,m_level));
  1435. //clip against all 6 frustum planes
  1436. ClippedPoly0.Clip(frustum.Planes[0],ClippedPoly1);
  1437. ClippedPoly1.Clip(frustum.Planes[1],ClippedPoly0);
  1438. ClippedPoly0.Clip(frustum.Planes[2],ClippedPoly1);
  1439. ClippedPoly1.Clip(frustum.Planes[3],ClippedPoly0);
  1440. ClippedPoly0.Clip(frustum.Planes[4],ClippedPoly1);
  1441. ClippedPoly1.Clip(frustum.Planes[5],ClippedPoly0);
  1442. Int final_vcount = ClippedPoly0.Verts.Count();
  1443. //make sure the polygon is visible
  1444. if (final_vcount >= 3)
  1445. {
  1446. //find axis aligned bounding box around visible polygon
  1447. if (box)
  1448. box->Init(&(ClippedPoly0.Verts[0]),final_vcount);
  1449. return TRUE;
  1450. }
  1451. return FALSE; //water plane is not visible
  1452. }
  1453. //-------------------------------------------------------------------------------------------------
  1454. /** Draws the water surface using a custom D3D vertex/pixel shader and a
  1455. * reflection texture. Only tested to work on GeForce3. */
  1456. //-------------------------------------------------------------------------------------------------
  1457. void WaterRenderObjClass::drawSea(RenderInfoClass & rinfo)
  1458. {
  1459. AABoxClass seaBox;
  1460. if (!getClippedWaterPlane(&rinfo.Camera,&seaBox))
  1461. return; //the sea is not visible
  1462. D3DXMATRIX matProj, matView, matWW3D;
  1463. //create a transform which will flip the y and z coordinates to fit our system
  1464. memset(&matWW3D,0,sizeof(D3DMATRIX));
  1465. matWW3D._11=1.0f;
  1466. matWW3D._32=1.0f;
  1467. matWW3D._23=1.0f;
  1468. matWW3D._44=1.0f;
  1469. Matrix3D tm(Transform);
  1470. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
  1471. DX8Wrapper::Set_Texture(0,NULL); //we'll be setting our own textures, so reset W3D
  1472. DX8Wrapper::Set_Texture(1,NULL); //we'll be setting our own textures, so reset W3D
  1473. DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
  1474. Vector3 camTran;
  1475. rinfo.Camera.Get_Transform().Get_Translation(&camTran);
  1476. DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, *(Matrix4x4*)&matView);
  1477. DX8Wrapper::_Get_DX8_Transform(D3DTS_PROJECTION, *(Matrix4x4*)&matProj);
  1478. //default setup from Kenny's demo
  1479. m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1480. m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  1481. m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  1482. m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1483. m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  1484. m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1485. m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  1486. m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
  1487. m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1488. m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
  1489. m_pDev->SetTextureStageState( 2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  1490. m_pDev->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|2);
  1491. m_pDev->SetTextureStageState( 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  1492. m_pDev->SetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|3);
  1493. // m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  1494. // m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  1495. // m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT );
  1496. // m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_POINT );
  1497. // m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_POINT );
  1498. // m_pDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE );
  1499. //end of default setup
  1500. m_pDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  1501. m_pDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  1502. m_pDev->SetRenderState( D3DRS_WRAP0, D3DWRAP_U | D3DWRAP_V);
  1503. m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
  1504. m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
  1505. m_pDev->SetTexture( 0, m_pBumpTexture[m_iBumpFrame]);
  1506. #ifdef MIPMAP_BUMP_TEXTURE
  1507. m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT );
  1508. m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  1509. m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  1510. #endif
  1511. m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT00, F2DW(m_fBumpScale) );
  1512. m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT01, F2DW(0.0f) );
  1513. m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT10, F2DW(0.0f) );
  1514. m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT11, F2DW(m_fBumpScale) );
  1515. m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVLSCALE, F2DW(1.0f) );
  1516. m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVLOFFSET, F2DW(0.0f) );
  1517. m_pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1518. m_pDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1519. m_pDev->SetRenderState(D3DRS_ZWRITEENABLE , FALSE);
  1520. D3DXMATRIX mat;
  1521. memset(&mat,0,sizeof(D3DXMATRIX));
  1522. mat._11 = 0.5f; mat._12 = -0.5f; mat._13 = 0.5f; mat._14=0.5f;
  1523. mat._21 = 0.5f; mat._22 = 0.5f; mat._23 = 0.0f; mat._24=0.0f;
  1524. mat._31 = 0.0f; mat._32 = 0.0f; mat._33 = 0.0f; mat._34=1.0f;
  1525. mat._41 = 0.0f; mat._42 = 0.0f; mat._43 = 0.0f; mat._44=1.0f;
  1526. m_pDev->SetVertexShaderConstant(CV_TEXPROJ_0, &mat, 4);
  1527. // Setup constants
  1528. m_pDev->SetVertexShaderConstant(CV_ZERO, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1);
  1529. m_pDev->SetVertexShaderConstant(CV_ONE, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);
  1530. m_pDev->SetVertexShader(m_dwWaveVertexShader);
  1531. m_pDev->SetPixelShader(m_dwWavePixelShader);
  1532. // Make reflection brighter to compensate for darker coloring on sea floor
  1533. // m_pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
  1534. // m_pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );
  1535. m_pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  1536. m_pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  1537. m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , TRUE);
  1538. m_pDev->SetTexture( 1, m_pReflectionTexture->Peek_D3D_Texture());
  1539. // m_pDev->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);//LORENZEN
  1540. Int patchX,patchY,startX,startY;
  1541. D3DXMATRIX patchMatrix;
  1542. memset(&patchMatrix,0,sizeof(D3DXMATRIX));
  1543. patchMatrix._11=PATCH_SCALE;
  1544. patchMatrix._22=1.0f;
  1545. patchMatrix._33=PATCH_SCALE;
  1546. patchMatrix._44=1.0f;
  1547. m_pDev->SetStreamSource(0,m_vertexBufferD3D,sizeof(WaterRenderObjClass::SEA_PATCH_VERTEX));
  1548. m_pDev->SetIndices(m_indexBufferD3D,0);
  1549. for (startY=patchY=(seaBox.Center.Y-seaBox.Extent.Y)/(PATCH_WIDTH*PATCH_SCALE); (patchY*PATCH_WIDTH*PATCH_SCALE)<(seaBox.Center.Y+seaBox.Extent.Y); patchY++)
  1550. {
  1551. for (startX=patchX=(seaBox.Center.X-seaBox.Extent.X)/(PATCH_WIDTH*PATCH_SCALE); (patchX*PATCH_WIDTH*PATCH_SCALE)<(seaBox.Center.X+seaBox.Extent.X); patchX++)
  1552. {
  1553. D3DXMATRIX matWorldViewProj, matTemp, matTempWorld;
  1554. patchMatrix._41=(float)(patchX*PATCH_WIDTH*PATCH_SCALE );
  1555. patchMatrix._43=(float)(patchY*PATCH_WIDTH*PATCH_SCALE );
  1556. //convert the default D3D coordinate system into ours
  1557. D3DXMatrixMultiply(&matTempWorld, &patchMatrix, &matWW3D);
  1558. D3DXMatrixMultiply(&matTemp, &matTempWorld, &matView);
  1559. D3DXMatrixMultiply(&matWorldViewProj, &matTemp, &matProj);
  1560. //matrices must be transposed before loading into vertex shader registers
  1561. D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
  1562. m_pDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj, 4); //pass transform matrix into shader
  1563. m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,m_numVertices,0,m_numIndices);
  1564. }
  1565. }
  1566. // m_pDev->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
  1567. m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , FALSE);
  1568. m_pDev->SetTexture( 0, NULL); //release reference to bump texture
  1569. m_pDev->SetTexture( 1, NULL); //release reference to reflection texture
  1570. m_pDev->SetTexture( 2, NULL); //release reference to reflection texture
  1571. m_pDev->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  1572. m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
  1573. m_pDev->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  1574. m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
  1575. m_pDev->SetRenderState(D3DRS_ZWRITEENABLE , TRUE);
  1576. m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  1577. m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  1578. m_pDev->SetRenderState( D3DRS_WRAP0, 0); //turn off texture wrapping
  1579. m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1580. m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1581. m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1582. m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1583. m_pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
  1584. m_pDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  1585. //Restore old transforms
  1586. DX8Wrapper::_Set_DX8_Transform(D3DTS_VIEW, *(Matrix4x4*)&matView);
  1587. DX8Wrapper::_Set_DX8_Transform(D3DTS_PROJECTION, *(Matrix4x4*)&matProj);
  1588. m_pDev->SetPixelShader(0); //turn off pixel shader
  1589. m_pDev->SetVertexShader(DX8_FVF_XYZDUV1); //turn off custom vertex shader
  1590. DX8Wrapper::Invalidate_Cached_Render_States();
  1591. if (TheTerrainRenderObject->getShroud())
  1592. {
  1593. //do second pass to apply the shroud on water plane
  1594. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  1595. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
  1596. m_pDev->SetStreamSource(0,m_vertexBufferD3D,sizeof(WaterRenderObjClass::SEA_PATCH_VERTEX));
  1597. m_pDev->SetIndices(m_indexBufferD3D,0);
  1598. for (startY=patchY=(seaBox.Center.Y-seaBox.Extent.Y)/(PATCH_WIDTH*PATCH_SCALE); (patchY*PATCH_WIDTH*PATCH_SCALE)<(seaBox.Center.Y+seaBox.Extent.Y); patchY++)
  1599. {
  1600. for (startX=patchX=(seaBox.Center.X-seaBox.Extent.X)/(PATCH_WIDTH*PATCH_SCALE); (patchX*PATCH_WIDTH*PATCH_SCALE)<(seaBox.Center.X+seaBox.Extent.X); patchX++)
  1601. {
  1602. D3DXMATRIX matTemp;
  1603. patchMatrix._41=(float)(patchX*PATCH_WIDTH*PATCH_SCALE);
  1604. patchMatrix._43=(float)(patchY*PATCH_WIDTH*PATCH_SCALE);
  1605. D3DXMatrixMultiply(&matTemp, &patchMatrix, &matWW3D);
  1606. DX8Wrapper::_Set_DX8_Transform(D3DTS_WORLD, *(Matrix4x4*)&matTemp);
  1607. m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,m_numVertices,0,m_numIndices);
  1608. }
  1609. }
  1610. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  1611. }
  1612. }
  1613. #define FEATHER_LAYER_COUNT (5.0f)
  1614. #define FEATHER_THICKNESS (4.0f)
  1615. //-------------------------------------------------------------------------------------------------
  1616. /** Renders (draws) the water surface.*/
  1617. //-------------------------------------------------------------------------------------------------
  1618. void WaterRenderObjClass::renderWater(void)
  1619. {
  1620. for (PolygonTrigger *pTrig=PolygonTrigger::getFirstPolygonTrigger(); pTrig; pTrig = pTrig->getNext()) {
  1621. if (pTrig->isWaterArea()) {
  1622. if (pTrig->getNumPoints()>2) {
  1623. if (pTrig->isRiver()) {
  1624. drawRiverWater(pTrig);
  1625. continue;
  1626. }
  1627. Int k;
  1628. for (k=1; k<pTrig->getNumPoints()-1; k=k+2) {
  1629. ICoord3D pt3 = *pTrig->getPoint(0);
  1630. ICoord3D pt2 = *pTrig->getPoint(k);
  1631. ICoord3D pt1 = *pTrig->getPoint(k+1);
  1632. ICoord3D pt0 = *pTrig->getPoint(k+1);
  1633. if (k+2<pTrig->getNumPoints()) {
  1634. pt0 = *pTrig->getPoint(k+2);
  1635. }
  1636. Vector3 points[4];
  1637. points[0].Set(pt0.x, pt0.y, pt0.z);
  1638. points[1].Set(pt1.x, pt1.y, pt1.z);
  1639. points[2].Set(pt2.x, pt2.y, pt2.z);
  1640. points[3].Set(pt3.x, pt3.y, pt3.z);
  1641. if ( TheGlobalData->m_featherWater )
  1642. {
  1643. for (int r = 0; r < TheGlobalData->m_featherWater; ++r)
  1644. {
  1645. drawTrapezoidWater(points);
  1646. points[0].Z += (FEATHER_THICKNESS/TheGlobalData->m_featherWater);
  1647. }
  1648. }
  1649. else
  1650. drawTrapezoidWater(points);
  1651. }
  1652. }
  1653. }
  1654. }
  1655. }
  1656. //-------------------------------------------------------------------------------------------------
  1657. /** Renders (draws) the sky plane. Will apply current time-of-day settings including
  1658. * some simple UV scrolling animation. */
  1659. //-------------------------------------------------------------------------------------------------
  1660. void WaterRenderObjClass::renderSky(void)
  1661. {
  1662. Int timeNow,timeDiff;
  1663. Real fu,fv;
  1664. Setting *setting=&m_settings[m_tod];
  1665. timeNow=timeGetTime();
  1666. timeDiff=timeNow-m_LastUpdateTime;
  1667. m_LastUpdateTime=timeNow;
  1668. m_uOffset += timeDiff * setting->uScrollPerMs * setting->skyTexelsPerUnit;
  1669. m_vOffset += timeDiff * setting->vScrollPerMs * setting->skyTexelsPerUnit;
  1670. //clamp uv coordinate into 0,1 range
  1671. m_uOffset = m_uOffset - (Real)((Int) m_uOffset);
  1672. m_vOffset = m_vOffset - (Real)((Int) m_vOffset);
  1673. fu= m_uOffset + (SKYPLANE_SIZE * 2) * setting->skyTexelsPerUnit;
  1674. fv= m_vOffset + (SKYPLANE_SIZE * 2) * setting->skyTexelsPerUnit;
  1675. VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  1676. DX8Wrapper::Set_Material(vmat);
  1677. REF_PTR_RELEASE(vmat);
  1678. ShaderClass m_shader2=ShaderClass::_PresetOpaqueShader;
  1679. m_shader2.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
  1680. m_shader2.Set_Depth_Compare(ShaderClass::PASS_ALWAYS); //no need to check against z-buffer, sky always rendered first.
  1681. m_shader2.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); //sky is always behind everything so no need to update z-buffer
  1682. DX8Wrapper::Set_Shader(m_shader2);
  1683. DX8Wrapper::Set_Texture(0,setting->skyTexture);
  1684. //draw an infinite sky plane
  1685. DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,4);
  1686. {
  1687. DynamicVBAccessClass::WriteLockClass lock(&vb_access);
  1688. VertexFormatXYZNDUV2* verts=lock.Get_Formatted_Vertex_Array();
  1689. if(verts)
  1690. {
  1691. verts[0].x=-SKYPLANE_SIZE;
  1692. verts[0].y=SKYPLANE_SIZE;
  1693. verts[0].z=SKYPLANE_HEIGHT;
  1694. verts[0].u1=m_uOffset;
  1695. verts[0].v1=fv;
  1696. verts[0].diffuse=setting->vertex01Diffuse;
  1697. verts[1].x=SKYPLANE_SIZE;
  1698. verts[1].y=SKYPLANE_SIZE;
  1699. verts[1].z=SKYPLANE_HEIGHT;
  1700. verts[1].u1=fu;
  1701. verts[1].v1=fv;
  1702. verts[1].diffuse=setting->vertex11Diffuse;
  1703. verts[2].x=SKYPLANE_SIZE;
  1704. verts[2].y=-SKYPLANE_SIZE;
  1705. verts[2].z=SKYPLANE_HEIGHT;
  1706. verts[2].u1=fu;
  1707. verts[2].v1=m_vOffset;
  1708. verts[2].diffuse=setting->vertex10Diffuse;
  1709. verts[3].x=-SKYPLANE_SIZE;
  1710. verts[3].y=-SKYPLANE_SIZE;
  1711. verts[3].z=SKYPLANE_HEIGHT;
  1712. verts[3].u1=m_uOffset;
  1713. verts[3].v1=m_vOffset;
  1714. verts[3].diffuse=setting->vertex00Diffuse;
  1715. }
  1716. }
  1717. DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
  1718. DX8Wrapper::Set_Vertex_Buffer(vb_access);
  1719. Matrix3D tm(1);
  1720. tm.Set_Translation(Vector3(0,0,0));
  1721. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
  1722. DX8Wrapper::Draw_Triangles( 0,2, 0, 4); //draw a quad, 2 triangles, 4 verts
  1723. }
  1724. //-------------------------------------------------------------------------------------------------
  1725. /** Renders (draws) the sky body. Used for moon and sun. We rotate the image
  1726. * so that it always faces the camera. This removes perspective and helps hide that
  1727. * it's a flat image. */
  1728. //-------------------------------------------------------------------------------------------------
  1729. /// @todo: Add code to render properly sorted sun sky body.
  1730. void WaterRenderObjClass::renderSkyBody(Matrix3D *mat)
  1731. {
  1732. Vector3 cPos;
  1733. Vector3 pView,pRight,pUp,pPos(SKYBODY_X,SKYBODY_Y,SKYBODY_HEIGHT);
  1734. mat->Get_Translation(&cPos);
  1735. pView=cPos-pPos; //billboard to camera
  1736. pView.Normalize(); //particle view direction
  1737. Vector3 WorldUp(0,0,-1); ///@todo: hacked so only works for reflections across xy plane
  1738. #ifdef ALLOW_TEMPORARIES
  1739. Vector3 rotAxis=Vector3::Cross_Product(WorldUp,pView); //get axis of rotation.
  1740. rotAxis.Normalize();
  1741. #else
  1742. Vector3 rotAxis;
  1743. Vector3::Normalized_Cross_Product(WorldUp, pView, &rotAxis);
  1744. #endif
  1745. Real angle=Vector3::Dot_Product(WorldUp,pView);
  1746. angle = acos(angle);
  1747. Matrix3D tm(1);
  1748. tm.Set(rotAxis,angle);
  1749. tm.Adjust_Translation(Vector3(SKYBODY_X,SKYBODY_Y,SKYBODY_HEIGHT));
  1750. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
  1751. VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  1752. DX8Wrapper::Set_Material(vmat);
  1753. REF_PTR_RELEASE(vmat);
  1754. ShaderClass m_shader2=ShaderClass::_PresetAlphaShader;
  1755. m_shader2.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
  1756. m_shader2.Set_Depth_Compare(ShaderClass::PASS_ALWAYS); //no need to check against z-buffer, sky always rendered first.
  1757. m_shader2.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); //sky is always behind everything so no need to update z-buffer
  1758. DX8Wrapper::Set_Shader(m_shader2);
  1759. // DX8Wrapper::Set_Shader(ShaderClass::/*_PresetAdditiveShader*//*_PresetOpaqueShader*/_PresetAlphaShader);
  1760. // DX8Wrapper::Set_Texture(0,setting->skyBodyTexture);
  1761. DX8Wrapper::Set_Texture(0,m_alphaClippingTexture);
  1762. //draw an infinite sky plane
  1763. DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,4);
  1764. {
  1765. DynamicVBAccessClass::WriteLockClass lock(&vb_access);
  1766. VertexFormatXYZNDUV2* verts=lock.Get_Formatted_Vertex_Array();
  1767. if(verts)
  1768. {
  1769. verts[0].x=-SKYBODY_SIZE;
  1770. verts[0].y=SKYBODY_SIZE;
  1771. verts[0].z=0;
  1772. verts[0].u2=0;
  1773. verts[0].v2=1;
  1774. verts[0].diffuse=0xffffffff;
  1775. verts[1].x=SKYBODY_SIZE;
  1776. verts[1].y=SKYBODY_SIZE;
  1777. verts[1].z=0;
  1778. verts[1].u2=1;
  1779. verts[1].v2=1;
  1780. verts[1].diffuse=0xffffffff;
  1781. verts[2].x=SKYBODY_SIZE;
  1782. verts[2].y=-SKYBODY_SIZE;
  1783. verts[2].z=0;
  1784. verts[2].u2=1;
  1785. verts[2].v2=0;
  1786. verts[2].diffuse=0xffffffff;
  1787. verts[3].x=-SKYBODY_SIZE;
  1788. verts[3].y=-SKYBODY_SIZE;
  1789. verts[3].z=0;
  1790. verts[3].u2=0;
  1791. verts[3].v2=0;
  1792. verts[3].diffuse=0xffffffff;
  1793. }
  1794. }
  1795. DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
  1796. DX8Wrapper::Set_Vertex_Buffer(vb_access);
  1797. DX8Wrapper::Draw_Triangles( 0,2, 0, 4); //draw a quad, 2 triangles, 4 verts
  1798. }
  1799. //Defines for procedural water animation.
  1800. #define WATER_FREQ (2.0*3.2831/4.0) //2pi (full cycle) cover 4 units
  1801. #define WATER_AMP (1.0f)
  1802. #define WATER_OFFSET (0.1f)
  1803. //-------------------------------------------------------------------------------------------------
  1804. /** Renders (draws) the water surface mesh geometry.
  1805. * This is a work-in-progress! Do not use this code! */
  1806. //-------------------------------------------------------------------------------------------------
  1807. void WaterRenderObjClass::renderWaterMesh(void)
  1808. {
  1809. if (!m_doWaterGrid)
  1810. return; //the water grid is disabled.
  1811. //According to Nvidia there's a D3D bug that happens if you don't start with a
  1812. //new dynamic VB each frame - so we force a DISCARD by overflowing the counter.
  1813. m_vertexBufferD3DOffset = 0xffff;
  1814. Setting *setting=&m_settings[m_tod];
  1815. WaterMeshData *pData;
  1816. Int mx=m_gridCellsX+1;
  1817. Int my=m_gridCellsY+1;
  1818. Int i,j;
  1819. Real cellSizeX=m_gridCellSize;
  1820. Real cellSizeY=m_gridCellSize;
  1821. // Real uScale2=5.0f*setting->waterRepeatCount/(128.0f)*cellSizeX/10.0f;
  1822. // Real vScale2=5.0f*setting->waterRepeatCount/(128.0f)*cellSizeY/10.0f;
  1823. //Old waterRepeatCount settings in INI were based on 128x128 water grid of cellsize=10
  1824. //Scale values to correct size.
  1825. Real uScale=setting->waterRepeatCount/(128.0f)*cellSizeX/10.0f*0.2f;
  1826. Real vScale=setting->waterRepeatCount/(128.0f)*cellSizeY/10.0f*0.2f;
  1827. Vector3 nx(cellSizeX*2.0f,0,0);
  1828. Vector3 ny(0,cellSizeY*2.0f,0);
  1829. Vector3 C;
  1830. #ifdef DO_WATER_SIMULATION //Debug code used to create a dummy water animation
  1831. //
  1832. // Mark: If you re-enable this water simulation, you might want to consider moving
  1833. // this code to the update() method of the water render object (Colin)
  1834. //
  1835. static Real PhasePerFrameX=0.1f;
  1836. static Real PhasePerFrameY=0.1f;
  1837. //update the mesh heights for this frame (update buffer is 2 samples wider/taller due to border)
  1838. for (j=0,pData=m_meshData; j<(my+2); j++)
  1839. {
  1840. for (i=0; i<(mx+2); i++)
  1841. {
  1842. //*pData = WATER_AMP * sin(WATER_FREQ*(0.7f*i + 0.7f*j) - PhasePerFrame);
  1843. pData->height=WATER_OFFSET+WATER_AMP*(sin((float)i*WATER_FREQ*0.4+PhasePerFrameX*0.5)+sin((float)i*WATER_FREQ*0.6+PhasePerFrameX*0.2)+sin((float)j*WATER_FREQ+PhasePerFrameX)+sin((float)j*WATER_FREQ*0.7+PhasePerFrameX*0.3));
  1844. // *pData=WATER_OFFSET+WATER_AMP*(sin((float)i*WATER_FREQ*0.4+PhasePerFrameX*0.5)+sin((float)i*WATER_FREQ*0.6+PhasePerFrameX*0.2)+sin((float)j*WATER_FREQ+PhasePerFrameX)+sin((float)j*WATER_FREQ*0.7+PhasePerFrameX*0.3));
  1845. pData++;
  1846. }
  1847. }
  1848. PhasePerFrameX -= 0.08f;
  1849. PhasePerFrameY -= 0.1f;
  1850. #endif
  1851. MaterMeshVertexFormat *vb;
  1852. if (m_vertexBufferD3DOffset < m_numVertices)
  1853. { //we have room in current VB, append new verts
  1854. if(m_vertexBufferD3D->Lock(m_vertexBufferD3DOffset*sizeof(MaterMeshVertexFormat),mx*my*sizeof(MaterMeshVertexFormat),(unsigned char**)&vb,D3DLOCK_NOOVERWRITE) != D3D_OK)
  1855. return;
  1856. }
  1857. else
  1858. { //ran out of room in last VB, request a substitute VB.
  1859. if(m_vertexBufferD3D->Lock(0,mx*my*sizeof(MaterMeshVertexFormat),(unsigned char**)&vb,D3DLOCK_DISCARD) != D3D_OK)
  1860. return;
  1861. m_vertexBufferD3DOffset=0; //reset start of page to first vertex
  1862. }
  1863. Int diffuse;
  1864. diffuse = setting->waterDiffuse&0x00ffffff;
  1865. Int alpha = (setting->waterDiffuse & 0xff000000)>>24;
  1866. // Reduce alpha for wave mesh
  1867. alpha -= 0x20;
  1868. diffuse |= alpha<<24;
  1869. //I pulled some of these constants out of the loops for speed:
  1870. Real uvCosScale=0.02*cos(3*m_riverVOrigin);
  1871. Real sinOffset=25*m_riverVOrigin;
  1872. Real originScale=m_riverVOrigin/vScale;
  1873. Real bumpSizeDiv=cellSizeY/BUMP_SIZE;
  1874. Real bumpSizeDiv2=0.3f*cellSizeY/BUMP_SIZE;
  1875. //Data has a 1 vertex padding all around it so we don't need to special-case edges. Improves performance
  1876. for (j=0,pData=m_meshData+mx+2+1; j<my; j++,pData+=2) //skip 2 horizontal border samples after each row
  1877. {
  1878. Real y=(float)j*cellSizeY;
  1879. Real v1Offset=m_riverVOrigin+(float)j*vScale + uvCosScale*WWMath::Fast_Sin(sinOffset+y*PI/(8*MAP_XY_FACTOR));
  1880. Real v2Offset=((float)j+originScale)*bumpSizeDiv + (float)j*bumpSizeDiv2;
  1881. for (i=0; i<mx; i++)
  1882. {
  1883. //compute normal by looking at 4 vertex neightbors
  1884. #ifdef USE_MESH_NORMALS
  1885. nx.Z=(pData+1)->height - (pData-1)->height;
  1886. ny.Z=(pData+mx+2)->height - (pData-mx-2)->height;
  1887. // nx.Z=*(pData+1)-*(pData-1);
  1888. // ny.Z=*(pData+mx+2)-*(pData-mx-2);
  1889. Vector3::Cross_Product(nx,ny,&C);
  1890. C.Normalize();
  1891. vb->nx = C.X;
  1892. vb->ny = C.X;
  1893. vb->nz = C.X;
  1894. #endif
  1895. Real x = (float)i*cellSizeX;
  1896. vb->x= x;
  1897. vb->y= y;
  1898. vb->z= pData->height;//WATER_OFFSET+WATER_AMP*(sin((float)i*WATER_FREQ+PhasePerFrame)+cos((float)j*WATER_FREQ+PhasePerFrame));
  1899. vb->diffuse = diffuse;
  1900. #ifdef SCROLL_UV
  1901. // vb->diffuse=0x80ffffff;
  1902. vb->u1=(float)i*uScale;
  1903. vb->v1=v1Offset;
  1904. //old slow version
  1905. //vb->v1=m_riverVOrigin+(float)j*vScale + 0.02*cos(3*m_riverVOrigin)*sin(25*m_riverVOrigin+y*PI/(8*MAP_XY_FACTOR));
  1906. // vb->u2=m_initialGridU2+(float)i*uScale2;
  1907. // vb->v2=m_initialGridV2+(float)j*vScale2;
  1908. #else
  1909. vb->u1=(float)i*uScale;
  1910. vb->v1=(float)j*vScale;
  1911. #endif
  1912. vb->u2=(float)(i)*cellSizeX/BUMP_SIZE;
  1913. vb->v2=v2Offset;
  1914. //old slow code
  1915. //vb->v2=(float)(j+m_riverVOrigin/vScale )*cellSizeY/BUMP_SIZE+ 0.3f*(float)j*cellSizeY/BUMP_SIZE;
  1916. vb++;
  1917. pData++;
  1918. }
  1919. }
  1920. m_vertexBufferD3D->Unlock();
  1921. Matrix3D tm(Transform);
  1922. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
  1923. DX8Wrapper::Set_Material(m_meshVertexMaterialClass);
  1924. ShaderClass::CullModeType oldCullMode=m_shaderClass.Get_Cull_Mode();
  1925. ShaderClass::DepthMaskType oldDepthMask=m_shaderClass.Get_Depth_Mask();
  1926. m_shaderClass.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); //disable writing to z-buffer to prevent particle clipping.
  1927. m_shaderClass.Set_Cull_Mode(ShaderClass::CULL_MODE_ENABLE); //water should be visible from both sides
  1928. DX8Wrapper::Set_Shader(m_shaderClass);
  1929. #if 1
  1930. setupFlatWaterShader();
  1931. #else
  1932. //DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
  1933. DX8Wrapper::Set_Texture(0,setting->waterTexture);
  1934. DX8Wrapper::Set_Texture(1,setting->waterTexture);
  1935. DX8Wrapper::Set_Light(0,*m_meshLight);
  1936. DX8Wrapper::Set_Light(1,NULL);
  1937. DX8Wrapper::Set_Light(2,NULL);
  1938. DX8Wrapper::Set_Light(3,NULL);
  1939. /*
  1940. DX8Wrapper::Set_DX8_Render_State(D3DRS_AMBIENT,0); //turn off scene ambient
  1941. DX8Wrapper::Set_DX8_Render_State(D3DRS_SPECULARENABLE,TRUE);
  1942. DX8Wrapper::Set_DX8_Render_State(D3DRS_LOCALVIEWER,TRUE);
  1943. */
  1944. DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
  1945. #endif
  1946. // m_pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_ALWAYS); //used to display grid under map.
  1947. m_pDev->SetIndices(m_indexBufferD3D,m_vertexBufferD3DOffset);
  1948. m_pDev->SetStreamSource(0,m_vertexBufferD3D,sizeof(MaterMeshVertexFormat));
  1949. m_pDev->SetVertexShader(WATER_MESH_FVF);
  1950. if (TheTerrainRenderObject->getShroud() && !m_trapezoidWaterPixelShader)
  1951. { //we have a shroud to apply and can't do it inside the pixel shader.
  1952. //so do it in stage1
  1953. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  1954. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 1);
  1955. //modulate with shroud texture
  1956. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //stage 1 texture
  1957. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); //previous stage texture
  1958. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
  1959. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  1960. //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
  1961. //write to the zbuffer. Change to LESSEQUAL.
  1962. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  1963. m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,mx*my,0,m_numIndices-2);
  1964. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
  1965. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  1966. }
  1967. else
  1968. m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,mx*my,0,m_numIndices-2);
  1969. Debug_Statistics::Record_DX8_Polys_And_Vertices(m_numIndices-2,mx*my,ShaderClass::_PresetOpaqueShader);
  1970. // m_pDev->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
  1971. if (m_trapezoidWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(NULL);
  1972. m_vertexBufferD3DOffset += mx*my; //advance past vertices already in buffer
  1973. DX8Wrapper::Set_Texture(0,NULL);
  1974. DX8Wrapper::Set_Texture(1,NULL);
  1975. ShaderClass::Invalidate();
  1976. m_shaderClass.Set_Cull_Mode(oldCullMode); //water should be visible from both sides
  1977. // restore shader to old mask
  1978. m_shaderClass.Set_Depth_Mask(oldDepthMask);
  1979. //W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  1980. }
  1981. inline void WaterRenderObjClass::setGridVertexHeight(Int x, Int y, Real value)
  1982. {
  1983. DEBUG_ASSERTCRASH( x < (m_gridCellsX+1) && y < (m_gridCellsY+1), ("Invalid Water Mesh Coordinates\n") );
  1984. if (m_meshData)
  1985. {
  1986. m_meshData[(y+1)*(m_gridCellsX+1+2)+x+1].height = value;
  1987. }
  1988. }
  1989. void WaterRenderObjClass::setGridHeightClamps(Real minz, Real maxz)
  1990. {
  1991. m_minGridHeight = minz;
  1992. m_maxGridHeight = maxz;
  1993. }
  1994. void WaterRenderObjClass::addVelocity( Real worldX, Real worldY,
  1995. Real zVelocity, Real preferredHeight )
  1996. {
  1997. if( m_doWaterGrid)
  1998. {
  1999. Real gx,gy;
  2000. Real minX,maxX,minY,maxY;
  2001. Int x,y;
  2002. WaterMeshData *meshPoint;
  2003. m_disableRiver = true;
  2004. //check if center falls within grid bounds
  2005. if (worldToGridSpace(worldX, worldY, gx, gy))
  2006. {
  2007. //find extents of influence
  2008. minX = floorf(gx - m_gridChangeMaxRange);
  2009. if (minX < 0 )
  2010. minX = 0; //clamp extent to fall within box
  2011. maxX = ceilf(gx + m_gridChangeMaxRange);
  2012. if (maxX > m_gridCellsX)
  2013. maxX = m_gridCellsX; //clamp extent to fall within box
  2014. minY = floorf(gy - m_gridChangeMaxRange);
  2015. if (minY < 0 )
  2016. minY = 0; //clamp extent to fall within box
  2017. maxY = ceilf(gy + m_gridChangeMaxRange);
  2018. if (maxY > m_gridCellsY)
  2019. maxY = m_gridCellsY; //clamp extent to fall within box
  2020. for (y=minY; y<=maxY; y++)
  2021. {
  2022. for (x=minX; x<=maxX; x++)
  2023. {
  2024. // get the mesh point that we're concerned with
  2025. meshPoint = &m_meshData[ (y + 1) * (m_gridCellsX + 1 + 2) + x + 1 ];
  2026. // we now have a new preferred height
  2027. meshPoint->preferredHeight = preferredHeight;
  2028. //
  2029. // set the velocity of this point based on the distance from the center of the
  2030. // "core" point for this call
  2031. //
  2032. meshPoint->velocity = meshPoint->velocity + zVelocity;
  2033. // this point is now "in motion"
  2034. BitSet( meshPoint->status, WaterRenderObjClass::IN_MOTION );
  2035. }
  2036. }
  2037. //
  2038. // the mesh data is now dirty, we need to pass through the velocity field
  2039. // during an update phase to update the positions
  2040. //
  2041. m_meshInMotion = TRUE;
  2042. }
  2043. } // end if, water type is 3
  2044. }
  2045. void WaterRenderObjClass::changeGridHeight(Real wx, Real wy, Real delta)
  2046. {
  2047. Real gx,gy;
  2048. Real *oldData;
  2049. Real newData;
  2050. Real distance;
  2051. Real minX,maxX,minY,maxY;
  2052. Int x,y;
  2053. //check if center falls within grid bounds
  2054. if (worldToGridSpace(wx, wy, gx, gy))
  2055. { //find extents of influence
  2056. minX = floorf(gx - m_gridChangeMaxRange);
  2057. if (minX < 0 )
  2058. minX = 0; //clamp extent to fall within box
  2059. maxX = ceilf(gx + m_gridChangeMaxRange);
  2060. if (maxX > m_gridCellsX)
  2061. maxX = m_gridCellsX; //clamp extent to fall within box
  2062. minY = floorf(gy - m_gridChangeMaxRange);
  2063. if (minY < 0 )
  2064. minY = 0; //clamp extent to fall within box
  2065. maxY = ceilf(gy + m_gridChangeMaxRange);
  2066. if (maxY > m_gridCellsY)
  2067. maxY = m_gridCellsY; //clamp extent to fall within box
  2068. for (y=minY; y<=maxY; y++)
  2069. {
  2070. for (x=minX; x<=maxX; x++)
  2071. { oldData = &m_meshData[(y+1)*(m_gridCellsX+1+2)+x+1].height;
  2072. distance = (gx - (Real)x)*(gx - (Real)x) + (gy - (Real)y)*(gy - (Real)y);
  2073. distance = sqrt(distance);
  2074. newData = *oldData + 1.0f/(m_gridChangeAtt0+m_gridChangeAtt1*distance+distance*distance*m_gridChangeAtt2)*delta;
  2075. //Clamp to min/max values
  2076. if (newData < m_minGridHeight)
  2077. newData = m_minGridHeight;
  2078. if (newData > m_maxGridHeight)
  2079. newData = m_maxGridHeight;
  2080. *oldData = newData;
  2081. }
  2082. }
  2083. }
  2084. }
  2085. void WaterRenderObjClass::setGridChangeAttenuationFactors(Real a, Real b, Real c, Real range)
  2086. {
  2087. m_gridChangeAtt0 = a;
  2088. m_gridChangeAtt1 = b;
  2089. m_gridChangeAtt2 = c;
  2090. m_gridChangeMaxRange = range/m_gridCellSize; //convert range to grid space
  2091. }
  2092. void WaterRenderObjClass::setGridTransform(Real angle, Real x, Real y, Real z)
  2093. {
  2094. m_gridDirectionX = Vector2(1.0f,0.0f);
  2095. m_gridOrigin.X = x;
  2096. m_gridOrigin.Y = y;
  2097. Matrix3D xform(1);
  2098. xform.Rotate_Z(angle);
  2099. m_gridDirectionX.X = xform.Get_X_Vector().X;
  2100. m_gridDirectionX.Y = xform.Get_X_Vector().Y;
  2101. m_gridDirectionY.X = xform.Get_Y_Vector().X;
  2102. m_gridDirectionY.Y = xform.Get_Y_Vector().Y;
  2103. xform.Set_Translation(Vector3(x,y,z));
  2104. Set_Transform(xform);
  2105. }
  2106. void WaterRenderObjClass::setGridTransform(const Matrix3D *transform )
  2107. {
  2108. if( transform )
  2109. Set_Transform( *transform );
  2110. }
  2111. void WaterRenderObjClass::getGridTransform(Matrix3D *transform )
  2112. {
  2113. if( transform )
  2114. *transform = Get_Transform();
  2115. }
  2116. void WaterRenderObjClass::setGridResolution(Real gridCellsX, Real gridCellsY, Real cellSize)
  2117. {
  2118. m_gridCellSize=cellSize;
  2119. if (m_gridCellsX != gridCellsX || m_gridCellsY != m_gridCellsY)
  2120. { //resolutoin has changed
  2121. m_gridCellsX=gridCellsX;
  2122. m_gridCellsY=gridCellsY;
  2123. if (m_meshData)
  2124. {
  2125. delete [] m_meshData;//free previously allocated grid and allocate new size
  2126. m_meshData = NULL; // must set to NULL so that we properly re-allocate
  2127. m_meshDataSize = 0;
  2128. Bool enable = m_doWaterGrid;
  2129. enableWaterGrid(true); // allocates buffers.
  2130. m_doWaterGrid = enable;
  2131. }
  2132. }
  2133. }
  2134. void WaterRenderObjClass::getGridResolution( Real *gridCellsX, Real *gridCellsY, Real *cellSize )
  2135. {
  2136. if( gridCellsX )
  2137. *gridCellsX = m_gridCellsX;
  2138. if( gridCellsY )
  2139. *gridCellsY = m_gridCellsY;
  2140. if( cellSize )
  2141. *cellSize = m_gridCellSize;
  2142. }
  2143. static Real wobble(Real baseV, Real offset, Bool wobble)
  2144. {
  2145. if (!wobble) return 0;
  2146. offset = sin(2*PI*baseV - 3*offset);
  2147. return offset/22;
  2148. }
  2149. /**Utility function used to query water heights in a manner that works in both RTS and WB.*/
  2150. Real WaterRenderObjClass::getWaterHeight(Real x, Real y)
  2151. {
  2152. const WaterHandle *waterHandle = NULL;
  2153. Real waterZ = 0.0f;
  2154. ICoord3D iLoc;
  2155. iLoc.x = REAL_TO_INT_FLOOR( x + 0.5f );
  2156. iLoc.y = REAL_TO_INT_FLOOR( y + 0.5f );
  2157. iLoc.z = 0;
  2158. for( PolygonTrigger *pTrig = PolygonTrigger::getFirstPolygonTrigger(); pTrig; pTrig = pTrig->getNext() )
  2159. {
  2160. if( !pTrig->isWaterArea() )
  2161. continue;
  2162. // See if point is in a water area
  2163. if( pTrig->pointInTrigger( iLoc ) )
  2164. {
  2165. if( pTrig->getPoint( 0 )->z >= waterZ )
  2166. {
  2167. waterZ = pTrig->getPoint( 0 )->z;
  2168. waterHandle = pTrig->getWaterHandle();
  2169. } // end if
  2170. } // end if
  2171. } // end for
  2172. if (waterHandle)
  2173. return waterHandle->m_polygon->getPoint( 0 )->z;
  2174. return INVALID_WATER_HEIGHT; //point not underwater
  2175. }
  2176. //-------------------------------------------------------------------------------------------------
  2177. //Draw a many sided river polygon.
  2178. //-------------------------------------------------------------------------------------------------
  2179. void WaterRenderObjClass::drawRiverWater(PolygonTrigger *pTrig)
  2180. {
  2181. DX8Wrapper::Invalidate_Cached_Render_States(); ///@todo: Figure out why rivers don't draw without reset of all states.
  2182. Int rectangleCount = pTrig->getNumPoints()/2;
  2183. rectangleCount--;
  2184. Real bumpFactor = 5;
  2185. static Bool doWobble = true;
  2186. if (m_disableRiver) return;
  2187. m_drawingRiver = true;
  2188. //allocate 2 triangles per side with 3 indices per triangle
  2189. DynamicIBAccessClass ib_access(BUFFER_TYPE_DYNAMIC_DX8,(rectangleCount+1)*2*3);
  2190. {
  2191. DynamicIBAccessClass::WriteLockClass lockib(&ib_access);
  2192. UnsignedShort *curIb = lockib.Get_Index_Array();
  2193. try {
  2194. for (Int i=0; i<rectangleCount; i++)
  2195. {
  2196. //triangle 1
  2197. curIb[0] = i*2;
  2198. curIb[1] = i*2+1;
  2199. curIb[2] = i*2+3;
  2200. //triangle 2
  2201. curIb[3] = i*2;
  2202. curIb[4] = i*2+3;
  2203. curIb[5] = i*2+2;
  2204. curIb += 6; //skip the 6 indices we just added.
  2205. }
  2206. IndexBufferExceptionFunc();
  2207. } catch(...) {
  2208. IndexBufferExceptionFunc();
  2209. }
  2210. }
  2211. Real shadeR=TheWaterTransparency->m_standingWaterColor.red;
  2212. Real shadeG=TheWaterTransparency->m_standingWaterColor.green;
  2213. Real shadeB=TheWaterTransparency->m_standingWaterColor.blue;
  2214. //If the water color is not overridden, use legacy lighting code.
  2215. if ( shadeR==1.0f && shadeG==1.0f && shadeB==1.0f)
  2216. {
  2217. shadeR = TheGlobalData->m_terrainAmbient[0].red;
  2218. shadeG = TheGlobalData->m_terrainAmbient[0].green;
  2219. shadeB = TheGlobalData->m_terrainAmbient[0].blue;
  2220. //Add in diffuse lighting from each terrain light
  2221. for (Int lightIndex=0; lightIndex < TheGlobalData->m_numGlobalLights; lightIndex++)
  2222. {
  2223. if (-TheGlobalData->m_terrainLightPos[lightIndex].z > 0)
  2224. { shadeR += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].red;
  2225. shadeG += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].green;
  2226. shadeB += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].blue;
  2227. }
  2228. }
  2229. //Get water material colors
  2230. Real waterShadeR = (m_settings[m_tod].waterDiffuse & 0xff) / 255.0f;
  2231. Real waterShadeG = ((m_settings[m_tod].waterDiffuse >> 8) & 0xff) / 255.0f;
  2232. Real waterShadeB = ((m_settings[m_tod].waterDiffuse >> 16) & 0xff) / 255.0f;
  2233. shadeR=shadeR*waterShadeR*255.0f;
  2234. shadeG=shadeG*waterShadeG*255.0f;
  2235. shadeB=shadeB*waterShadeB*255.0f;
  2236. }
  2237. else
  2238. {
  2239. shadeR=shadeR*255.0f;
  2240. shadeG=shadeG*255.0f;
  2241. shadeB=shadeB*255.0f;
  2242. if (shadeR == 0 && shadeG == 0 && shadeB == 0)
  2243. { //special case where we disable lighting
  2244. shadeR=255;
  2245. shadeG=255;
  2246. shadeB=255;
  2247. }
  2248. }
  2249. Int diffuse=REAL_TO_INT(shadeB) | (REAL_TO_INT(shadeG) << 8) | (REAL_TO_INT(shadeR) << 16);
  2250. //Keep diffuse from lighting calculations but substitute custom alpha
  2251. diffuse |= m_settings[m_tod].waterDiffuse & 0xff000000; //copy alpha/opacity from ini setting
  2252. Int innerNdx = pTrig->getRiverStart();
  2253. Int outerNdx = innerNdx+1;
  2254. Real endLen=0;
  2255. Real totalLen=0;
  2256. Int i;
  2257. for (i=0; i<pTrig->getNumPoints()-1; i++) {
  2258. ICoord3D innerPt = *pTrig->getPoint(i);
  2259. ICoord3D outerPt = *pTrig->getPoint(i+1);
  2260. Real dx = innerPt.x-outerPt.x;
  2261. Real dy = innerPt.y-outerPt.y;
  2262. Real curLen = sqrt(dx*dx+dy*dy);
  2263. totalLen += curLen;
  2264. if ( i==innerNdx) {
  2265. endLen = curLen;
  2266. }
  2267. }
  2268. bumpFactor = endLen/BUMP_SIZE;
  2269. Real lengthOfRiver = (totalLen/2)-endLen;
  2270. Real repeatCount = lengthOfRiver / (endLen);
  2271. Real vScale=(Real)repeatCount/(Real)rectangleCount;
  2272. #define HEIGHT_TO_USE (0.5f)
  2273. if (innerNdx >= pTrig->getNumPoints()-1) return;
  2274. //allocate 2 vertices per side
  2275. DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,(rectangleCount+1)*2);
  2276. {
  2277. DynamicVBAccessClass::WriteLockClass lock(&vb_access);
  2278. VertexFormatXYZNDUV2* vb=lock.Get_Formatted_Vertex_Array();
  2279. Real constA=3*m_riverVOrigin;
  2280. for (i=0; i<(pTrig->getNumPoints()/2); i++)
  2281. {
  2282. Real x,y;
  2283. ICoord3D innerPt = *pTrig->getPoint(outerNdx);
  2284. ICoord3D outerPt = *pTrig->getPoint(innerNdx);
  2285. outerNdx++;
  2286. innerNdx--;
  2287. if (innerNdx<0) {
  2288. innerNdx = pTrig->getNumPoints()-1;
  2289. }
  2290. if (outerNdx >= pTrig->getNumPoints()) {
  2291. outerNdx = 0;
  2292. }
  2293. x=innerPt.x;
  2294. y=innerPt.y;
  2295. vb->x=x;
  2296. vb->y=y;
  2297. vb->z=innerPt.z;
  2298. vb->diffuse= diffuse;
  2299. Real wobbleConst=-m_riverVOrigin+vScale*(Real)i + WWMath::Fast_Sin(2*PI*(vScale*(Real)i) - constA)/22.0f;
  2300. //old slower version
  2301. //vb->v1=-m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
  2302. vb->v1=wobbleConst;
  2303. vb->u1=HEIGHT_TO_USE ;
  2304. //old slower version
  2305. //vb->v2 = -m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
  2306. vb->v2=wobbleConst;
  2307. vb->u2 = 1.0f;
  2308. vb->nx = 0;
  2309. vb->ny = 0;
  2310. vb->nz = 1.0f;
  2311. vb++;
  2312. x=outerPt.x;
  2313. y=outerPt.y;
  2314. vb->x=x;
  2315. vb->y=y;
  2316. vb->z=outerPt.z;
  2317. vb->diffuse= diffuse;
  2318. //old slower version
  2319. //vb->v1=-m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
  2320. vb->v1=wobbleConst;
  2321. vb->u1=0;
  2322. //old slower version
  2323. //vb->v2 = -m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
  2324. vb->v2 =wobbleConst;
  2325. vb->u2 = 0;
  2326. vb->nx = 0;
  2327. vb->ny = 0;
  2328. vb->nz = 1.0f;
  2329. vb++;
  2330. }
  2331. }
  2332. Matrix3D tm(1);
  2333. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
  2334. DX8Wrapper::Set_Index_Buffer(ib_access,0);
  2335. DX8Wrapper::Set_Vertex_Buffer(vb_access);
  2336. DX8Wrapper::Set_Texture(0,m_riverTexture); //set to blue
  2337. setupJbaWaterShader();
  2338. //In additive blending we need to use the alpha at the edges of river to darken
  2339. //rgb instead.
  2340. if (TheWaterTransparency->m_additiveBlend)
  2341. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  2342. if (m_riverWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_riverWaterPixelShader);
  2343. DWORD cull;
  2344. DX8Wrapper::_Get_D3D_Device8()->GetRenderState(D3DRS_CULLMODE, &cull);
  2345. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  2346. if (wireframeForDebug) {
  2347. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
  2348. }
  2349. DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
  2350. if (wireframeForDebug) {
  2351. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
  2352. }
  2353. if (m_riverWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(NULL);
  2354. //restore blend mode to what W3D expects.
  2355. if (TheWaterTransparency->m_additiveBlend)
  2356. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_ONE );
  2357. //do second pass to apply the shroud on water plane
  2358. if (TheTerrainRenderObject->getShroud())
  2359. {
  2360. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  2361. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
  2362. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  2363. //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
  2364. //write to the zbuffer. Change to LESSEQUAL.
  2365. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  2366. DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
  2367. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
  2368. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  2369. }
  2370. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, cull);
  2371. }
  2372. void WaterRenderObjClass::setupFlatWaterShader(void)
  2373. {
  2374. DX8Wrapper::Set_Texture(0,m_riverTexture);
  2375. if (!TheWaterTransparency->m_additiveBlend)
  2376. DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaShader);
  2377. else
  2378. DX8Wrapper::Set_Shader(ShaderClass::_PresetAdditiveShader);
  2379. VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  2380. DX8Wrapper::Set_Material(vmat);
  2381. REF_PTR_RELEASE(vmat);
  2382. m_riverTexture->Get_Filter().Set_Mag_Filter(TextureFilterClass::FILTER_TYPE_BEST);
  2383. m_riverTexture->Get_Filter().Set_Min_Filter(TextureFilterClass::FILTER_TYPE_BEST);
  2384. m_riverTexture->Get_Filter().Set_Mip_Mapping(TextureFilterClass::FILTER_TYPE_BEST);
  2385. DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
  2386. //Setup shroud to render in same pass as water
  2387. if (m_trapezoidWaterPixelShader)
  2388. { if (TheTerrainRenderObject->getShroud())
  2389. {
  2390. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  2391. //Use stage 3 to apply the shroud
  2392. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 3);
  2393. //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
  2394. //write to the zbuffer. Change to LESSEQUAL.
  2395. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  2396. }
  2397. else
  2398. { //Assume no shroud, so stage 3 will be "NULL" texture but using actual white because
  2399. //pixel shader on GF4 generates random colors with SetTexture(3,NULL).
  2400. if (!m_whiteTexture->Is_Initialized())
  2401. { m_whiteTexture->Init();
  2402. SurfaceClass *surface=m_whiteTexture->Get_Surface_Level();
  2403. surface->DrawPixel(0,0,0xffffffff);
  2404. REF_PTR_RELEASE(surface);
  2405. }
  2406. DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,m_whiteTexture->Peek_D3D_Texture());
  2407. }
  2408. }
  2409. DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_ADD );
  2410. DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, 0);
  2411. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, 0);
  2412. Bool doSparkles = true;
  2413. if (m_trapezoidWaterPixelShader && doSparkles) {
  2414. if (!m_waterSparklesTexture->Is_Initialized())
  2415. m_waterSparklesTexture->Init();
  2416. DX8Wrapper::_Get_D3D_Device8()->SetTexture(1,m_waterSparklesTexture->Peek_D3D_Texture());
  2417. if (!m_waterNoiseTexture->Is_Initialized())
  2418. m_waterNoiseTexture->Init();
  2419. DX8Wrapper::_Get_D3D_Device8()->SetTexture(2,m_waterNoiseTexture->Peek_D3D_Texture());
  2420. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  2421. DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  2422. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
  2423. // Two output coordinates are used.
  2424. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  2425. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  2426. DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  2427. D3DXMATRIX inv;
  2428. float det;
  2429. Matrix4x4 curView;
  2430. DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
  2431. D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
  2432. D3DXMATRIX scale;
  2433. D3DXMatrixScaling(&scale, NOISE_REPEAT_FACTOR, NOISE_REPEAT_FACTOR,1);
  2434. D3DXMATRIX destMatrix = inv * scale;
  2435. D3DXMatrixTranslation(&scale, m_riverVOrigin, m_riverVOrigin,0);
  2436. destMatrix = destMatrix*scale;
  2437. DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, *(Matrix4x4*)&destMatrix);
  2438. }
  2439. m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  2440. m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  2441. m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  2442. m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  2443. m_pDev->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  2444. m_pDev->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  2445. if (m_trapezoidWaterPixelShader){
  2446. DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(0, D3DXVECTOR4(REFLECTION_FACTOR, REFLECTION_FACTOR, REFLECTION_FACTOR, 1.0f), 1);
  2447. DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_trapezoidWaterPixelShader);
  2448. }
  2449. }
  2450. //-------------------------------------------------------------------------------------------------
  2451. //Draw a 4 sided flat water area.
  2452. //-------------------------------------------------------------------------------------------------
  2453. void WaterRenderObjClass::drawTrapezoidWater(Vector3 points[4])
  2454. {
  2455. Vector3 origin(points[0]);
  2456. Vector3 uVec1(points[1]);
  2457. Vector3 vVec1(points[3]);
  2458. Vector3 uVec2(points[2]);
  2459. Vector3 vVec2(points[2]);
  2460. uVec2 -= vVec1;
  2461. vVec2 -= uVec1;
  2462. uVec1 -= origin;
  2463. vVec1 -= origin;
  2464. Int uCount = (uVec1.Length()+uVec2.Length()) / (8*MAP_XY_FACTOR);
  2465. if (uCount<1) uCount = 1;
  2466. Int vCount = (vVec1.Length()+vVec2.Length()) / (8*MAP_XY_FACTOR);
  2467. if (vCount<1) vCount = 1;
  2468. if (uCount>50) uCount = 50;
  2469. if (vCount>50) vCount = 50;
  2470. static Bool doWobble = true;
  2471. Int rectangleCount = uCount*vCount;
  2472. uCount++;
  2473. vCount++;
  2474. Int i, j;
  2475. //allocate 2 triangles per side with 3 indices per triangle
  2476. DynamicIBAccessClass ib_access(BUFFER_TYPE_DYNAMIC_DX8,(rectangleCount+1)*2*3);
  2477. {
  2478. DynamicIBAccessClass::WriteLockClass lockib(&ib_access);
  2479. UnsignedShort *curIb = lockib.Get_Index_Array();
  2480. try {
  2481. for (j=0; j<vCount-1; j++)
  2482. { for (i=0; i<uCount-1; i++)
  2483. {
  2484. //triangle 1
  2485. curIb[0] = (j)*uCount + i;
  2486. curIb[1] = (j+1)*uCount + i+1;
  2487. curIb[2] = (j+1)*uCount + i;
  2488. //triangle 2
  2489. curIb[3] = (j)*uCount + i;
  2490. curIb[4] = (j)*uCount + i+1;
  2491. curIb[5] = (j+1)*uCount + i+1;
  2492. curIb += 6; //skip the 6 indices we just added.
  2493. }
  2494. }
  2495. IndexBufferExceptionFunc();
  2496. } catch(...) {
  2497. IndexBufferExceptionFunc();
  2498. }
  2499. }
  2500. Real waterFactor=150;
  2501. Real shadeR=TheWaterTransparency->m_standingWaterColor.red;
  2502. Real shadeG=TheWaterTransparency->m_standingWaterColor.green;
  2503. Real shadeB=TheWaterTransparency->m_standingWaterColor.blue;
  2504. //If the water color is not overridden, use legacy lighting code.
  2505. if ( shadeR==1.0f && shadeG==1.0f && shadeB==1.0f)
  2506. {
  2507. shadeR = TheGlobalData->m_terrainAmbient[0].red;
  2508. shadeG = TheGlobalData->m_terrainAmbient[0].green;
  2509. shadeB = TheGlobalData->m_terrainAmbient[0].blue;
  2510. //Add in diffuse lighting from each terrain light
  2511. for (Int lightIndex=0; lightIndex < TheGlobalData->m_numGlobalLights; lightIndex++)
  2512. {
  2513. if (-TheGlobalData->m_terrainLightPos[lightIndex].z > 0)
  2514. { shadeR += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].red;
  2515. shadeG += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].green;
  2516. shadeB += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].blue;
  2517. }
  2518. }
  2519. //Get water material colors
  2520. Real waterShadeR = (m_settings[m_tod].waterDiffuse & 0xff) / 255.0f;
  2521. Real waterShadeG = ((m_settings[m_tod].waterDiffuse >> 8) & 0xff) / 255.0f;
  2522. Real waterShadeB = ((m_settings[m_tod].waterDiffuse >> 16) & 0xff) / 255.0f;
  2523. shadeR=shadeR*waterShadeR*255.0f;
  2524. shadeG=shadeG*waterShadeG*255.0f;
  2525. shadeB=shadeB*waterShadeB*255.0f;
  2526. }
  2527. else
  2528. {
  2529. shadeR=shadeR*255.0f;
  2530. shadeG=shadeG*255.0f;
  2531. shadeB=shadeB*255.0f;
  2532. if (shadeR == 0 && shadeG == 0 && shadeB == 0)
  2533. { //special case where we disable lighting
  2534. shadeR=255;
  2535. shadeG=255;
  2536. shadeB=255;
  2537. }
  2538. }
  2539. Int diffuse=REAL_TO_INT(shadeB) | (REAL_TO_INT(shadeG) << 8) | (REAL_TO_INT(shadeR) << 16);
  2540. //Keep diffuse from lighting calculations but substitute custom alpha
  2541. diffuse |= m_settings[m_tod].waterDiffuse & 0xff000000; //copy alpha/opacity from ini setting
  2542. DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,(rectangleCount+1)*2);
  2543. //#define WAVY_WATER
  2544. //#define FEATHER_LAYER_COUNT (3) //LORENZEN
  2545. //#define FEATHER_LAYER_THICKNESS (2.5f)
  2546. //#define FEATHER_WATER
  2547. //#ifdef WAVY_WATER // the NEW WATER a'la LORENZEN
  2548. if ( TheGlobalData->m_featherWater )
  2549. {
  2550. DynamicVBAccessClass::WriteLockClass lock(&vb_access);
  2551. VertexFormatXYZNDUV2* vb=lock.Get_Formatted_Vertex_Array();
  2552. Real phase = 0;
  2553. Real mapCoeff = PI/(4*MAP_XY_FACTOR);
  2554. Real wave = 0;
  2555. Real amplitude = 0.5f;
  2556. //The first (high order) byte is the Alpha value for this patch
  2557. // It needs to be set proportional to the number of feather layers
  2558. // this comes from TheGlobalData->m_featherWater, which is a count of layers
  2559. Int Alpha = 0;
  2560. if ( TheGlobalData->m_featherWater == 5) Alpha = 80;
  2561. if ( TheGlobalData->m_featherWater == 4) Alpha = 110;
  2562. if ( TheGlobalData->m_featherWater == 3) Alpha = 140;
  2563. if ( TheGlobalData->m_featherWater == 2) Alpha = 200;
  2564. if ( TheGlobalData->m_featherWater == 1) Alpha = 255;
  2565. //Keep diffuse from lighting calculations but substitute custom alpha
  2566. Int customDiffuse = (diffuse & 0x00ffffff) | (Alpha<< 24);//(0x80 << 16)|(0x90 << 8)|0xa0;
  2567. for (j=0; j<vCount; j++)
  2568. {
  2569. Real dv = j;
  2570. dv /= (vCount-1);
  2571. for (i=0; i<uCount; i++)
  2572. {
  2573. Real du = i;
  2574. du /= (uCount-1);
  2575. Vector3 vertex = origin;
  2576. vertex += uVec1*du;
  2577. vertex += vVec1*dv;
  2578. vertex += (dv)*(du)*(vVec2-vVec1);
  2579. vb->x=vertex.X;
  2580. vb->y=vertex.Y;
  2581. // common to all the waving effects
  2582. phase = 25 * m_riverVOrigin + vertex.X * mapCoeff;
  2583. wave = (sin(phase) - 1.0f) * amplitude;
  2584. vb->z = (vertex.Z + wave);
  2585. vb->diffuse = customDiffuse;
  2586. vb->u1 = (vertex.X/waterFactor) + 0.02*cos(11*m_riverVOrigin)*wave;
  2587. vb->v1 = (vertex.Y/waterFactor) + 0.02*cos(5*m_riverVOrigin)*wave;
  2588. vb->u2 = vertex.X/BUMP_SIZE;
  2589. vb->v2 = vertex.Y/BUMP_SIZE + 0.3f*vertex.X/BUMP_SIZE;
  2590. vb->nx = 0;
  2591. vb->ny = 0;
  2592. vb->nz = 1.0f;
  2593. vb++;
  2594. }
  2595. }
  2596. }
  2597. //#else // STILL THE OLD FLAT WATER
  2598. else
  2599. {
  2600. DynamicVBAccessClass::WriteLockClass lock(&vb_access);
  2601. VertexFormatXYZNDUV2* vb=lock.Get_Formatted_Vertex_Array();
  2602. //Pulling some constants out of the inner loops to improve performance -MW
  2603. Real constA=0.02*cos(11*m_riverVOrigin);
  2604. Real constB=0.02*cos(5*m_riverVOrigin);
  2605. Real constC=25*m_riverVOrigin;
  2606. Real ooWaterFactor = 1.0f/waterFactor;
  2607. const Real constD=PI/(4*MAP_XY_FACTOR);
  2608. Real constE=1.0f/(Real)(vCount-1);
  2609. Real constF=1.0f/(Real)(uCount-1);
  2610. for (j=0; j<vCount; j++)
  2611. {
  2612. Real dv = (Real)j * constE;
  2613. for (i=0; i<uCount; i++)
  2614. {
  2615. Real du = (Real)i * constF;
  2616. Vector3 vertex = origin;
  2617. vertex += uVec1*du;
  2618. vertex += vVec1*dv;
  2619. vertex += (dv)*(du)*(vVec2-vVec1);
  2620. vb->x=vertex.X;
  2621. vb->y=vertex.Y;
  2622. vb->z=vertex.Z;
  2623. vb->diffuse= diffuse;
  2624. //Old slower version
  2625. //vb->u1=(vertex.X/waterFactor) + 0.02*cos(11*m_riverVOrigin)*sin(25*m_riverVOrigin+vertex.X*PI/(4*MAP_XY_FACTOR));
  2626. //vb->v1=(vertex.Y/waterFactor) + 0.02*cos(5*m_riverVOrigin)*sin(25*m_riverVOrigin+vertex.Y*PI/(4*MAP_XY_FACTOR));
  2627. vb->u1=vertex.X*ooWaterFactor + constA*WWMath::Fast_Sin(constC+vertex.X*constD);
  2628. vb->v1=vertex.Y*ooWaterFactor + constB*WWMath::Fast_Sin(constC+vertex.Y*constD);
  2629. vb->u2 = vertex.X/BUMP_SIZE;
  2630. //Old slower version
  2631. //vb->v2 = vertex.Y/BUMP_SIZE + 0.3f*vertex.X/BUMP_SIZE;
  2632. vb->v2 = (vertex.Y+0.3f*vertex.X)/BUMP_SIZE;
  2633. vb->nx = 0;
  2634. vb->ny = 0;
  2635. vb->nz = 1.0f;
  2636. vb++;
  2637. }
  2638. }
  2639. }
  2640. //#endif // OLD VS NEW WATER
  2641. Matrix3D tm(1);
  2642. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
  2643. DX8Wrapper::Set_Index_Buffer(ib_access,0);
  2644. DX8Wrapper::Set_Vertex_Buffer(vb_access);
  2645. setupFlatWaterShader();// lorenzen sez use the alpha shader
  2646. //If video card supports it and it's enabled, feather the water edge using destination alpha
  2647. if (DX8Wrapper::getBackBufferFormat() == WW3D_FORMAT_A8R8G8B8 && TheGlobalData->m_showSoftWaterEdge && TheWaterTransparency->m_transparentWaterDepth !=0)
  2648. { DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA );
  2649. if (!TheWaterTransparency->m_additiveBlend)
  2650. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA );
  2651. }
  2652. DWORD cull;
  2653. DX8Wrapper::_Get_D3D_Device8()->GetRenderState(D3DRS_CULLMODE, &cull);
  2654. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  2655. //#ifdef FEATHER_WATER // the NEW WATER a'la LORENZEN
  2656. // int layer = 0;//LORENZEN
  2657. // for (layer = 0; layer < FEATHER_LAYER_COUNT; ++layer)//LORENZEN
  2658. //#endif // FEATHER_WATER
  2659. {
  2660. //#ifdef WAVY_WATER // the NEW WATER a'la LORENZEN
  2661. //increment the depth of the water's surface for every vert in the buffer
  2662. //#ifdef FEATHER_WATER
  2663. // VertexFormatXYZNDUV2 *vertBuf = vertexBufferStart;
  2664. // while (vertBuf < vertexBufferStart + vCount * uCount)
  2665. // {
  2666. // vertBuf->z *= FEATHER_LAYER_THICKNESS;
  2667. // ++vertBuf;
  2668. // }
  2669. //#endif // FEATHER_WATER
  2670. //#endif //WAVY_WATER
  2671. DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);//lorenzen thinks this is where to itereate the soft shoreline effect
  2672. }
  2673. if (false) {
  2674. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
  2675. m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , false);
  2676. DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
  2677. m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , true);
  2678. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
  2679. }
  2680. if (m_riverWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(NULL);
  2681. //Restore alpha blend to default values since we may have changed them to feather edges.
  2682. if (!TheWaterTransparency->m_additiveBlend)
  2683. { DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  2684. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  2685. }
  2686. else
  2687. {
  2688. DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_ONE );
  2689. DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_ONE );
  2690. }
  2691. if (TheTerrainRenderObject->getShroud())
  2692. {
  2693. if (m_trapezoidWaterPixelShader)
  2694. { //shroud was applied in stage3 of main pass so just need to restore state here.
  2695. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  2696. DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,NULL); //free possible reference to shroud texture
  2697. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
  2698. }
  2699. else
  2700. { //do second pass to apply the shroud on water plane for cards that can't do it in main pass.
  2701. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  2702. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
  2703. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  2704. //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
  2705. //write to the zbuffer. Change to LESSEQUAL.
  2706. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  2707. DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
  2708. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
  2709. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  2710. }
  2711. }
  2712. DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, cull);
  2713. }
  2714. //-------------------------------------------------------------------------------------------------
  2715. //debug version where moon rotates with the camera (always upright on screen)
  2716. //-------------------------------------------------------------------------------------------------
  2717. #if 0
  2718. void WaterRenderObjClass::renderSkyBody(Matrix3D *mat)
  2719. {
  2720. Vector3 vRight,vUp,V0,V1,V2,V3;
  2721. mat->Get_X_Vector(&vRight);
  2722. mat->Get_Y_Vector(&vUp);
  2723. //calculate offsets from quad center to each of the 4 corners
  2724. // 0-----1
  2725. // | /|
  2726. // | / |
  2727. // |/ |
  2728. // 3-----2
  2729. V0=-vRight+vUp;
  2730. V2=vRight+vUp;
  2731. V2=vRight-vUp;
  2732. V3=-vRight-vUp;
  2733. VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  2734. DX8Wrapper::Set_Material(vmat);
  2735. REF_PTR_RELEASE(vmat);
  2736. DX8Wrapper::Set_Shader(ShaderClass::/*_PresetAdditiveShader*//*_PresetOpaqueShader*/_PresetAlphaShader);
  2737. // DX8Wrapper::Set_Texture(0,setting->skyBodyTexture);
  2738. DX8Wrapper::Set_Texture(0,m_alphaClippingTexture);
  2739. //draw an infinite sky plane
  2740. DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,4);
  2741. {
  2742. DynamicVBAccessClass::WriteLockClass lock(&vb_access);
  2743. VertexFormatXYZNDUV2* verts=lock.Get_Formatted_Vertex_Array();
  2744. if(verts)
  2745. {
  2746. verts[0].x=SKYBODY_SIZE*V0.X;
  2747. verts[0].y=SKYBODY_SIZE*V0.Y;
  2748. verts[0].z=SKYBODY_SIZE*V0.Z;
  2749. verts[0].u2=0;
  2750. verts[0].v2=1;
  2751. verts[0].diffuse=0xffffffff;
  2752. verts[1].x=SKYBODY_SIZE*V1.X;
  2753. verts[1].y=SKYBODY_SIZE*V1.Y;
  2754. verts[1].z=SKYBODY_SIZE*V1.Z;
  2755. verts[1].u2=1;
  2756. verts[1].v2=1;
  2757. verts[1].diffuse=0xffffffff;
  2758. verts[2].x=SKYBODY_SIZE*V2.X;
  2759. verts[2].y=SKYBODY_SIZE*V2.Y;
  2760. verts[2].z=SKYBODY_SIZE*V2.Z;
  2761. verts[2].u2=1;
  2762. verts[2].v2=0;
  2763. verts[2].diffuse=0xffffffff;
  2764. verts[3].x=SKYBODY_SIZE*V3.X;
  2765. verts[3].y=SKYBODY_SIZE*V3.Y;
  2766. verts[3].z=SKYBODY_SIZE*V3.Z;
  2767. verts[3].u2=0;
  2768. verts[3].v2=0;
  2769. verts[3].diffuse=0xffffffff;
  2770. }
  2771. }
  2772. DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
  2773. DX8Wrapper::Set_Vertex_Buffer(vb_access);
  2774. Matrix3D tm(1);
  2775. //set postion of skybody in world
  2776. // tm.Set_Translation(Vector3(40,0,0));
  2777. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
  2778. DX8Wrapper::Draw_Triangles( 0,2, 0, 4); //draw a quad, 2 triangles, 4 verts
  2779. }
  2780. #endif
  2781. // ------------------------------------------------------------------------------------------------
  2782. /** CRC */
  2783. // ------------------------------------------------------------------------------------------------
  2784. void WaterRenderObjClass::crc( Xfer *xfer )
  2785. {
  2786. } // end crc
  2787. // ------------------------------------------------------------------------------------------------
  2788. /** Xfer
  2789. * Version Info:
  2790. * 1: Initial version */
  2791. // ------------------------------------------------------------------------------------------------
  2792. void WaterRenderObjClass::xfer( Xfer *xfer )
  2793. {
  2794. // version
  2795. XferVersion currentVersion = 1;
  2796. XferVersion version = currentVersion;
  2797. xfer->xferVersion( &version, currentVersion );
  2798. // grid cells x
  2799. Int cellsX = m_gridCellsX;
  2800. xfer->xferInt( &cellsX );
  2801. if( cellsX != m_gridCellsX )
  2802. {
  2803. DEBUG_CRASH(( "WaterRenderObjClass::xfer - cells X mismatch\n" ));
  2804. throw SC_INVALID_DATA;
  2805. } // end if
  2806. // grid cells Y
  2807. Int cellsY = m_gridCellsY;
  2808. xfer->xferInt( &cellsY );
  2809. if( cellsY != m_gridCellsY )
  2810. {
  2811. DEBUG_CRASH(( "WaterRenderObjClass::xfer - cells Y mismatch\n" ));
  2812. throw SC_INVALID_DATA;
  2813. } // end if
  2814. // xfer each of the mesh data points
  2815. for( Int i = 0; i < m_meshDataSize; ++i )
  2816. {
  2817. // height
  2818. xfer->xferReal( &m_meshData[ i ].height );
  2819. // velocity
  2820. xfer->xferReal( &m_meshData[ i ].velocity );
  2821. // status
  2822. xfer->xferUnsignedByte( &m_meshData[ i ].status );
  2823. // preferred height
  2824. xfer->xferUnsignedByte( &m_meshData[ i ].preferredHeight );
  2825. } // end for, i
  2826. } // end xfer
  2827. // ------------------------------------------------------------------------------------------------
  2828. /** Load post process */
  2829. // ------------------------------------------------------------------------------------------------
  2830. void WaterRenderObjClass::loadPostProcess( void )
  2831. {
  2832. } // end loadPostProcess