W3DWater.cpp 118 KB

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