| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DWater.cpp /////////////////////////////////////////////////////////////////////////////
- // Created: Mark Wilczynski, June 2001
- // Desc: Draw reflective water surface. Also handles drawing of waves/ripples
- // on the surface.
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- #define SCROLL_UV
-
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "stdio.h"
- #include "W3DDevice/GameClient/W3DWater.h"
- #include "W3DDevice/GameClient/heightmap.h"
- #include "W3DDevice/GameClient/W3DShroud.h"
- #include "W3DDevice/GameClient/W3DWaterTracks.h"
- #include "W3DDevice/GameClient/W3DAssetManager.h"
- #include "texture.h"
- #include "assetmgr.h"
- #include "rinfo.h"
- #include "camera.h"
- #include "scene.h"
- #include "dx8wrapper.h"
- #include "light.h"
- #include "D3dx8math.h"
- #include "simplevec.h"
- #include "mesh.h"
- #include "matinfo.h"
- #include "Common/GameState.h"
- #include "Common/GlobalData.h"
- #include "Common/PerfTimer.h"
- #include "Common/Xfer.h"
- #include "Common/GameLOD.h"
- #include "GameClient/Water.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/PolygonTrigger.h"
- #include "GameLogic/ScriptEngine.h"
- #include "W3DDevice/GameClient/W3DShaderManager.h"
- #include "W3DDevice/GameClient/W3DDisplay.h"
- #include "W3DDevice/GameClient/W3DPoly.h"
- #include "W3DDevice/GameClient/W3DScene.h"
- #include "W3DDevice/GameClient/W3DCustomScene.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- #define MIPMAP_BUMP_TEXTURE
- // DEFINES ////////////////////////////////////////////////////////////////////////////////////////
- #define SKYPLANE_SIZE (384.0f*MAP_XY_FACTOR)
- #define SKYPLANE_HEIGHT (30.0f)
- #define SKYBODY_TEXTURE "TSMoonLarg.tga"
- #define SKYBODY_SIZE 45.0f //extent or radius of sky body
- #define SKYBODY_X 150.0f //location of skybody
- #define SKYBODY_Y 550.0f //location of skybody
- /* in the bay
- #define SKYBODY_X 120.0f //location of skybody
- #define SKYBODY_Y 75.0f //location of skybody
- */
- #define SKYBODY_HEIGHT SKYPLANE_HEIGHT //altitude of sky body (z-buffer disabled, so can equal sky height).
- //GeForce3 water system defines
- #define PATCH_SIZE 15 //number of vertices on patch edge. Large patches may waste vertices off edge of screen.
- #define PATCH_UV_TILES 42 //number of times the bump map texture is tiled across patch (must be integer!).
- #define PATCH_SCALE (4.0f * MAP_XY_FACTOR) //horizontal scale factor. Adjust this and size to get desired vertex density.
- #define SEA_REFLECTION_SIZE 256 //dimensions of reflection texture
- #define SEA_BUMP_SCALE (0.06f) //scales the du/dv offsets stored in bump map (~ amount to perturb)
- #define BUMP_SIZE (50.f)
- #define REFLECTION_FACTOR 0.1f
- #define PATCH_WIDTH (PATCH_SIZE-1) //internal defines
- #define PATCH_UV_SCALE ((Real)PATCH_UV_TILES/(Real)PATCH_WIDTH)
- //3D Grid Mesh Water defines.
- #define WATER_MESH_OPACITY 0.5f
- #define WATER_MESH_X_VERTICES 128
- #define WATER_MESH_Y_VERTICES 128
- #define WATER_MESH_SPACING MAP_XY_FACTOR //same as terrain
- #ifdef USE_MESH_NORMALS
- #define WATER_MESH_FVF DX8_FVF_XYZNDUV2
- typedef VertexFormatXYZNDUV2 MaterMeshVertexFormat;
- #else
- #define WATER_MESH_FVF DX8_FVF_XYZDUV2
- typedef VertexFormatXYZDUV2 MaterMeshVertexFormat;
- #endif
- // Converts a FLOAT to a DWORD for use in SetRenderState() calls
- static inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
- #define DRAW_WATER_WAKES
- /// @todo: Fix clipping of objects that intersect the mirror surface
- //#define CLIP_GEOMETRY_TO_PLANE // this enables clipping of objects that intersect the mirror surfaces
- // Some shader combinations that can be useful in rendering water:
- // Modulate stage0 with stage1 texture. Also modulate stage 0 with vertex color.
- #define SC_DETAIL_BLEND ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
- ShaderClass::SRCBLEND_SRC_ALPHA,ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
- ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, ShaderClass::DETAILCOLOR_DETAILBLEND, ShaderClass::DETAILALPHA_DISABLE) )
- // Just a z-buffer fill, nothing is written to the color buffer.
- #define SC_ZFILL_BLEND ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_DISABLE, ShaderClass::SRCBLEND_ZERO, \
- ShaderClass::DSTBLEND_ONE, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::DETAILCOLOR_SCALE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, \
- ShaderClass::DETAILCOLOR_SCALE, ShaderClass::DETAILALPHA_DISABLE) )
- // No texturing, just vertex color with vertex alpha
- #define SC_ZFILL_BLENDx ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE, \
- ShaderClass::SRCBLEND_ZERO, ShaderClass::DSTBLEND_SRC_COLOR, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
- ShaderClass::TEXTURING_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- // Modulate blended with vertex alpha modulation
- #define SC_ZFILL_MODULATE_TEX ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
- ShaderClass::SRCBLEND_ZERO, ShaderClass::DSTBLEND_SRC_COLOR, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
- ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- // Alpha blended with vertex alpha modulation
- #define SC_ZFILL_ALPHA_TEX ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
- ShaderClass::SRCBLEND_SRC_ALPHA, ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_DISABLE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
- ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- // Alpha blended with vertex alpha modulation
- #define SC_OPAQUE_TEXONLY ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
- ShaderClass::SRCBLEND_ONE, ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_DISABLE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
- ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- // Alpha blended with vertex alpha modulation
- #define SC_ZFILL_BLEND3 ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE,\
- ShaderClass::SRCBLEND_SRC_ALPHA, ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, \
- ShaderClass::TEXTURING_ENABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass zFillAlphaShader(SC_ZFILL_BLEND3);
- static ShaderClass blendStagesShader(SC_DETAIL_BLEND);
- WaterRenderObjClass *TheWaterRenderObj=NULL; ///<global water rendering object
- #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
- void doSkyBoxSet(Bool startDraw)
- {
- if (TheWritableGlobalData)
- TheWritableGlobalData->m_drawSkyBox = startDraw;
- }
- #define DONUT_SIDES 90
- #define INNER_RADIUS 200.0f
- #define OUTER_RADIUS 250.0f
- #define TEXTURE_REPEAT_COUNT 16
- #define DONUT_HEIGHT 15.0f
- //#define DO_FLAT_DONUT
- #define AMP_SCALE (30.0f/120.0f)
- #define WAVE_FREQ 0.3f
- #define AMP_SCALE2 (10.0f/120.0f)
- #define NOISE_FREQ (2.0f*PI/WAVE_FREQ)
- #define NOISE_REPEAT_FACTOR ((float)(1.0f/(16.0f)))
-
- static Bool wireframeForDebug = 0;
- void WaterRenderObjClass::setupJbaWaterShader(void)
- {
- DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaShader);
- VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
- DX8Wrapper::Set_Material(vmat);
- REF_PTR_RELEASE(vmat);
- m_riverTexture->Set_Mag_Filter(TextureClass::FILTER_TYPE_BEST);
- m_riverTexture->Set_Min_Filter(TextureClass::FILTER_TYPE_BEST);
- m_riverTexture->Set_Mip_Mapping(TextureClass::FILTER_TYPE_BEST);
- // Setting *setting=&m_settings[m_tod];
- DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
- DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_ADD );
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,m_riverAlphaEdge->Peek_DX8_Texture());
- DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
- DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, 0);
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, 0);
- DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_TEXCOORDINDEX, 1);
-
- Bool doSparkles = true;
- if (m_riverWaterPixelShader && doSparkles) {
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(1,m_waterSparklesTexture->Peek_DX8_Texture());
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(2,m_waterNoiseTexture->Peek_DX8_Texture());
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
-
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
- // Two output coordinates are used.
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
- D3DXMATRIX inv;
- float det;
- Matrix4 curView;
- DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
- D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
- D3DXMATRIX scale;
- D3DXMatrixScaling(&scale, NOISE_REPEAT_FACTOR, NOISE_REPEAT_FACTOR,1);
- D3DXMATRIX destMatrix = inv * scale;
- D3DXMatrixTranslation(&scale, m_riverVOrigin, m_riverVOrigin,0);
- destMatrix = destMatrix*scale;
- DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, *(Matrix4*)&destMatrix);
-
- }
- m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- if (m_riverWaterPixelShader){
- DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(0, D3DXVECTOR4(REFLECTION_FACTOR, REFLECTION_FACTOR, REFLECTION_FACTOR, 1.0f), 1);
- DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_riverWaterPixelShader);
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Destructor. Releases w3d assets. */
- //-------------------------------------------------------------------------------------------------
- WaterRenderObjClass::~WaterRenderObjClass(void)
- {
- REF_PTR_RELEASE(m_meshVertexMaterialClass);
- REF_PTR_RELEASE(m_vertexMaterialClass);
- REF_PTR_RELEASE(m_meshLight);
- REF_PTR_RELEASE(m_alphaClippingTexture);
- REF_PTR_RELEASE (m_skyBox);
- REF_PTR_RELEASE (m_riverTexture);
- REF_PTR_RELEASE (m_whiteTexture);
- REF_PTR_RELEASE (m_waterNoiseTexture);
- REF_PTR_RELEASE (m_riverAlphaEdge);
- REF_PTR_RELEASE (m_waterSparklesTexture);
- Int i;
- for(i=0; i<TIME_OF_DAY_COUNT; i++)
- { REF_PTR_RELEASE(m_settings[i].skyTexture);
- REF_PTR_RELEASE(m_settings[i].waterTexture);
- }
- i=NUM_BUMP_FRAMES;
- while (i--)
- { SAFE_RELEASE( m_pBumpTexture[i]);
- SAFE_RELEASE( m_pBumpTexture2[i]);
- }
- if (m_meshData)
- delete [] m_meshData;
- m_meshData = NULL;
- m_meshDataSize = 0;
- //Release strings allocated inside global water settings.
- for (i=0; i<TIME_OF_DAY_COUNT; i++)
- { WaterSettings[i].m_skyTextureFile.clear();
- WaterSettings[i].m_waterTextureFile.clear();
- }
- ReleaseResources();
- if (m_waterTrackSystem)
- delete m_waterTrackSystem;
- }
- //-------------------------------------------------------------------------------------------------
- /** Constructor. Just nulls out some variables. */
- //-------------------------------------------------------------------------------------------------
- WaterRenderObjClass::WaterRenderObjClass(void)
- {
- memset( &m_settings, 0, sizeof( m_settings ) );
- m_dx=0;
- m_dy=0;
- m_indexBuffer=NULL;
- m_waterTrackSystem = NULL;
- m_doWaterGrid = FALSE;
- m_meshVertexMaterialClass=NULL;
- m_meshLight=NULL;
- m_vertexMaterialClass=NULL;
- m_alphaClippingTexture=NULL;
- m_useCloudLayer=true;
- m_waterType = WATER_TYPE_0_TRANSLUCENT;
- m_tod=TIME_OF_DAY_AFTERNOON;
- m_pReflectionTexture=NULL;
- m_skyBox=NULL;
- m_vertexBufferD3D=NULL;
- m_indexBufferD3D=NULL;
- m_vertexBufferD3DOffset=0;
- m_dwWavePixelShader=NULL;
- m_dwWaveVertexShader=NULL;
- m_meshData=NULL;
- m_meshDataSize = 0;
- m_meshInMotion = FALSE;
- m_gridOrigin=Vector2(0,0);
- m_gridDirectionX=Vector2(1.0f,0.0f);
- m_gridDirectionY=Vector2(1.0f,0.0f);
- m_gridCellSize=WATER_MESH_SPACING;
- m_gridCellsX=WATER_MESH_X_VERTICES;
- m_gridCellsY=WATER_MESH_Y_VERTICES;
- m_gridWidth = m_gridCellsX * m_gridCellSize;
- m_gridHeight = m_gridCellsY * m_gridCellSize;
-
- Int i=NUM_BUMP_FRAMES;
- while (i--)
- m_pBumpTexture[i]=NULL;
- m_riverVOrigin=0;
- m_riverTexture=NULL;
- m_whiteTexture=NULL;
- m_waterNoiseTexture=NULL;
- m_riverAlphaEdge=NULL;
- m_waterPixelShader=0; ///<D3D handle to pixel shader.
- m_riverWaterPixelShader=0; ///<D3D handle to pixel shader.
- m_trapezoidWaterPixelShader=0; ///<D3D handle to pixel shader.
- m_waterSparklesTexture=0;
- m_riverXOffset=0;
- m_riverYOffset=0;
- }
- //-------------------------------------------------------------------------------------------------
- /** WW3D method that returns object bounding sphere used in frustum culling*/
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
- {
- //Since this object is more of a system (containing lots of water pieces),
- //let's disable culling by making bounds huge. Let each piece do it's own cull.
- Vector3 ObjSpaceCenter(0,0,0);
- // Vector3 ObjSpaceRadius(m_dx,m_dy,0);
- Vector3 ObjSpaceRadius(50000,50000,0);
- sphere.Init(ObjSpaceCenter,ObjSpaceRadius.Length());
- }
- //-------------------------------------------------------------------------------------------------
- /** WW3D method that returns object bounding box used in collision detection*/
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
- {
- //Since this object is more of a system (containing lots of water pieces),
- //let's disable culling by making bounds huge. Let each piece do it's own cull.
- Vector3 ObjSpaceCenter(0,0,0);
- Vector3 ObjSpaceExtents(50000,50000,0.001f*m_dy); //since mirror is a plane, it has no thickness. Set to m_dy/1000.
- box.Init(ObjSpaceCenter,ObjSpaceExtents);
- }
- //-------------------------------------------------------------------------------------------------
- /** returns the class id, so the scene can tell what kind of render object it has. */
- //-------------------------------------------------------------------------------------------------
- Int WaterRenderObjClass::Class_ID(void) const
- {
- return RenderObjClass::CLASSID_UNKNOWN;
- }
- //-------------------------------------------------------------------------------------------------
- /** Not used, but required virtual method. */
- //-------------------------------------------------------------------------------------------------
- RenderObjClass * WaterRenderObjClass::Clone(void) const
- {
- assert(false);
- return NULL;
- }
- //-------------------------------------------------------------------------------------------------
- /** Copies raw bits from pBumpSrc (a regular grayscale texture) into a D3D
- * bump-map format. */
- //-------------------------------------------------------------------------------------------------
- HRESULT WaterRenderObjClass::initBumpMap(LPDIRECT3DTEXTURE8 *pTex, TextureClass *pBumpSource)
- {
- SurfaceClass::SurfaceDescription d3dsd;
- SurfaceClass * surf;
- D3DLOCKED_RECT d3dlr;
- DWORD dwSrcPitch;
- BYTE* pSrc;
- Int numLevels;
- #ifdef MIPMAP_BUMP_TEXTURE
- numLevels=pBumpSource->Get_Mip_Level_Count();
- pBumpSource->Get_Level_Description(d3dsd);
- if (Get_Bytes_Per_Pixel(d3dsd.Format) != 4)
- {
- // LORENZEN WAS BUGGED BY THIS,
- // DEBUG_CRASH(("WaterRenderObjClass::Invalid BumpMap format - Was it compressed?") );
- return S_OK;
- }
- pTex[0]=DX8Wrapper::_Create_DX8_Texture(d3dsd.Width,d3dsd.Height,WW3D_FORMAT_U8V8,TextureClass::MIP_LEVELS_ALL,D3DPOOL_MANAGED,false);
- for (Int level=0; level < numLevels; level++)
- {
- surf=pBumpSource->Get_Surface_Level(level);
- surf->Get_Description(d3dsd);
- pSrc=(unsigned char *)surf->Lock((int *)&dwSrcPitch);
- pTex[0]->LockRect( level, &d3dlr, 0, 0 );
- DWORD dwDstPitch = (DWORD)d3dlr.Pitch;
- BYTE* pDst = (BYTE*)d3dlr.pBits;
- for( DWORD y=0; y<d3dsd.Height; y++ )
- {
- BYTE* pDstT = pDst;
- BYTE* pSrcB0 = (BYTE*)pSrc;
- BYTE* pSrcB1 = ( pSrcB0 + dwSrcPitch );
- BYTE* pSrcB2 = ( pSrcB0 - dwSrcPitch );
- if( y == d3dsd.Height-1 ) // Don't go past the last line
- pSrcB1 = pSrcB0;
- if( y == 0 ) // Don't go before first line
- pSrcB2 = pSrcB0;
- for( DWORD x=0; x<d3dsd.Width; x++ )
- {
- LONG v00 = 256-*(pSrcB0+0); // Get the current pixel
- LONG v01 = 256-*(pSrcB0+4); // and the pixel to the right
- LONG vM1 = 256-*(pSrcB0-4); // and the pixel to the left
- LONG v10 = 256-*(pSrcB1+0); // and the pixel one line below.
- LONG v1M = 256-*(pSrcB2+0); // and the pixel one line above.
- LONG iDu = (vM1-v01); // The delta-u bump value
- LONG iDv = (v1M-v10); // The delta-v bump value
- if( (v00 < vM1) && (v00 < v01) ) // If we are at valley
- {
- iDu = vM1-v00; // Choose greater of 1st order diffs
- if( iDu < v00-v01 )
- iDu = v00-v01;
- }
- // The luminance bump value (land masses are less shiny)
- WORD uL = ( v00>1 ) ? 63 : 127;
- switch( D3DFMT_V8U8)//m_BumpMapFormat )
- {
- case D3DFMT_V8U8:
- *pDstT++ = (BYTE)iDu;
- *pDstT++ = (BYTE)iDv;
- break;
- case D3DFMT_L6V5U5:
- *(WORD*)pDstT = (WORD)( ( (iDu>>3) & 0x1f ) << 0 );
- *(WORD*)pDstT |= (WORD)( ( (iDv>>3) & 0x1f ) << 5 );
- *(WORD*)pDstT |= (WORD)( ( ( uL>>2) & 0x3f ) << 10 );
- pDstT += 2;
- break;
- case D3DFMT_X8L8V8U8:
- *pDstT++ = (BYTE)iDu;
- *pDstT++ = (BYTE)iDv;
- *pDstT++ = (BYTE)uL;
- *pDstT++ = (BYTE)0L;
- break;
- }
- // Move one pixel to the left (src is 32-bpp)
- pSrcB0+=4; pSrcB1+=4; pSrcB2+=4;
- }
- // Move to the next line
- pSrc += dwSrcPitch; pDst += dwDstPitch;
- }
- pTex[0]->UnlockRect(level);
- surf->Unlock();
- REF_PTR_RELEASE (surf);
- }//for each level
- #else
- surf=pBumpSource->Get_Surface_Level();
- surf->Get_Description(d3dsd);
- pSrc=(unsigned char *)surf->Lock((int *)&dwSrcPitch);
- // Create the bumpmap's surface and texture objects
- m_pBumpTexture[i]=DX8Wrapper::_Create_DX8_Texture(d3dsd.Width,d3dsd.Height,WW3D_FORMAT_U8V8,TextureClass::MIP_LEVELS_1,D3DPOOL_MANAGED,false);
- // Fill the bits of the new texture surface with bits from
- // a private format.
- m_pBumpTexture[i]->LockRect( 0, &d3dlr, 0, 0 );
- DWORD dwDstPitch = (DWORD)d3dlr.Pitch;
- BYTE* pDst = (BYTE*)d3dlr.pBits;
- for( DWORD y=0; y<d3dsd.Height; y++ )
- {
- BYTE* pDstT = pDst;
- BYTE* pSrcB0 = (BYTE*)pSrc;
- BYTE* pSrcB1 = ( pSrcB0 + dwSrcPitch );
- BYTE* pSrcB2 = ( pSrcB0 - dwSrcPitch );
- if( y == d3dsd.Height-1 ) // Don't go past the last line
- pSrcB1 = pSrcB0;
- if( y == 0 ) // Don't go before first line
- pSrcB2 = pSrcB0;
- for( DWORD x=0; x<d3dsd.Width; x++ )
- {
- LONG v00 = 256-*(pSrcB0+0); // Get the current pixel
- LONG v01 = 256-*(pSrcB0+4); // and the pixel to the right
- LONG vM1 = 256-*(pSrcB0-4); // and the pixel to the left
- LONG v10 = 256-*(pSrcB1+0); // and the pixel one line below.
- LONG v1M = 256-*(pSrcB2+0); // and the pixel one line above.
- LONG iDu = (vM1-v01); // The delta-u bump value
- LONG iDv = (v1M-v10); // The delta-v bump value
- if( (v00 < vM1) && (v00 < v01) ) // If we are at valley
- {
- iDu = vM1-v00; // Choose greater of 1st order diffs
- if( iDu < v00-v01 )
- iDu = v00-v01;
- }
- // The luminance bump value (land masses are less shiny)
- WORD uL = ( v00>1 ) ? 63 : 127;
- switch( D3DFMT_V8U8)//m_BumpMapFormat )
- {
- case D3DFMT_V8U8:
- *pDstT++ = (BYTE)iDu;
- *pDstT++ = (BYTE)iDv;
- break;
- case D3DFMT_L6V5U5:
- *(WORD*)pDstT = (WORD)( ( (iDu>>3) & 0x1f ) << 0 );
- *(WORD*)pDstT |= (WORD)( ( (iDv>>3) & 0x1f ) << 5 );
- *(WORD*)pDstT |= (WORD)( ( ( uL>>2) & 0x3f ) << 10 );
- pDstT += 2;
- break;
- case D3DFMT_X8L8V8U8:
- *pDstT++ = (BYTE)iDu;
- *pDstT++ = (BYTE)iDv;
- *pDstT++ = (BYTE)uL;
- *pDstT++ = (BYTE)0L;
- break;
- }
- // Move one pixel to the left (src is 32-bpp)
- pSrcB0+=4; pSrcB1+=4; pSrcB2+=4;
- }
- // Move to the next line
- pSrc += dwSrcPitch; pDst += dwDstPitch;
- }
- m_pBumpTexture[i]->UnlockRect(0);
- surf->Unlock();
- #endif
- return S_OK;
- }
- //-------------------------------------------------------------------------------------------------
- /** Create and fill a D3D vertex buffer with water surface vertices */
- //-------------------------------------------------------------------------------------------------
- HRESULT WaterRenderObjClass::generateVertexBuffer( Int sizeX, Int sizeY, Int vertexSize, Bool doStatic)
- {
- m_numVertices=sizeX*sizeY;
- //Assuming dynamic vertex buffer, allocate maximum multiple of required size to allow rendering from
- //different parts of the buffer. 5-15-03: Disabled this since we use DISCARD mode instead to avoid Nvidia Runtime bug. -MW
- //m_numVertices=(65536 / (sizeX*sizeY))*sizeX*sizeY;
- SEA_PATCH_VERTEX* pVertices;
- Setting *setting=&m_settings[m_tod];
- HRESULT hr;
- //default setting for a dynamic vertex buffer
- D3DPOOL pool = D3DPOOL_DEFAULT;
- DWORD usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
- DWORD fvf = WATER_MESH_FVF;
- if (doStatic)
- { //change settings for a static vertex buffer
- pool = D3DPOOL_MANAGED;
- usage = D3DUSAGE_WRITEONLY;
- fvf=0;// DX8 Docs confusing on this. Say no FVF for vertex shaders. Else DX8_FVF_XYZDUV1;
- m_numVertices=sizeX*sizeY;
- }
- if (m_vertexBufferD3D == NULL)
- { // Create vertex buffer
- if (FAILED(hr=m_pDev->CreateVertexBuffer
- (
- m_numVertices*vertexSize,
- usage,
- fvf,
- pool,
- &m_vertexBufferD3D
- )))
- return hr;
- }
- m_vertexBufferD3DOffset=0;
- if (!doStatic)
- return S_OK; //only create the buffer, other code will fill it.
- // load results into buffer
- if (FAILED(hr=m_vertexBufferD3D->Lock
- (
- 0,
- m_numVertices*sizeof(SEA_PATCH_VERTEX),
- (BYTE**)&pVertices,
- 0//D3DLOCK_DISCARD
- )))
- return hr;
- Int x,z;
- for (z=0; z<sizeY; z++)
- {
- for (x=0; x<sizeX; x++)
- {
- pVertices->x=(float)x;
- pVertices->y=m_level;
- pVertices->z=(float)z;
- pVertices->tu=(float)x*PATCH_UV_SCALE;
- pVertices->tv=(float)z*PATCH_UV_SCALE;
- pVertices->c=setting->transparentWaterDiffuse; //vertex alpha/color
- pVertices++;
- }
- }
- if (FAILED(hr=m_vertexBufferD3D->Unlock())) return hr;
- return S_OK;
- }
- //-------------------------------------------------------------------------------------------------
- /** Create and fill a D3D index buffer with water surface strip indices */
- //-------------------------------------------------------------------------------------------------
- HRESULT WaterRenderObjClass::generateIndexBuffer(Int sizeX, Int sizeY)
- {
- HRESULT hr;
- //Will need SizeY-1 strips, each of length SizeX*2 (2 indices per strip segment).
- //Will also need 2 extra indices to connect each strip to next one (except last strip)
- //Total index buffer size = (SizeY-1)*(SizeX*2+2) - 2 (drop the extra 2 indices from last strip)
- m_numIndices=(sizeY-1)*(sizeX*2+2) - 2;
- //old way
- // Create index buffer
- WORD* pIndices;
- if (FAILED(hr=m_pDev->CreateIndexBuffer
- (
- (m_numIndices+2)*sizeof(WORD),
- D3DUSAGE_WRITEONLY,
- D3DFMT_INDEX16,
- D3DPOOL_MANAGED,
- &m_indexBufferD3D
- )))
- return hr;
- if (FAILED(hr=m_indexBufferD3D->Lock
- (
- 0,
- m_numIndices*sizeof(WORD),
- (BYTE**)&pIndices,
- 0
- )))
- return hr;
- Int i,j,k;
- for (i=0,j=0,k=0; i<m_numIndices; j++)
- {
- for (;k<(sizeX*(j+1)); k++,i+=2)
- {
- pIndices[i]=(UnsignedShort) k+sizeX;
- pIndices[i+1]=(UnsignedShort) k;
- }
- //Generate 4 degenerate triangle to connect current strip to next strip/row of map
- //To do this, we just repeat the last index of first strip and first index of new strip.
- //Any triangles with repeated vertices will be skipped during rendering.
- if (i<m_numIndices) //check if there is at least 1 more strip to go
- {
- pIndices[i]=k-1;
- pIndices[i+1]=k+sizeX;
- i+=2;
- }
- }
- /*Old way
- Int step=1;
- Int psize=(size-1)/step;
- m_numIndices=psize*((psize+1)*2)+(psize*2)-2;
- Int x,z,s_toggle=1;
- for (z=step; z<size; z+=step)
- {
- if (s_toggle)
- {
- for (x=0; x<(size-step); x+=step)
- {
- *pIndices++=(WORD)((z-0)*size+(x));
- *pIndices++=(WORD)((z-step)*size+(x));
- }
- *pIndices++=(WORD)((z-0)*size+(size-1));
- *pIndices++=(WORD)((z-step)*size+(size-1));
- // insert additional degenerate to start next row
- *pIndices++=pIndices[-2];
- *pIndices++=pIndices[-1];
- }
- else
- {
- *pIndices++=(WORD)((z-step)*size+(size-1));
- *pIndices++=(WORD)((z-0)*size+(size-1));
- for (x=size-1; x>0; x-=step)
- {
- *pIndices++=(WORD)((z-step)*size+(x-step));
- *pIndices++=(WORD)((z-0)*size+(x-step));
- }
- // insert additional degenerate to start next row
- *pIndices++=pIndices[-1];
- *pIndices++=pIndices[-1];
- }
- s_toggle=!s_toggle;
- }
- */
- if (FAILED(hr=m_indexBufferD3D->Unlock())) return hr;
- return S_OK;
- }
- //-------------------------------------------------------------------------------------------------
- /** Releases all w3d assets, to prepare for Reset device call. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::ReleaseResources(void)
- {
- REF_PTR_RELEASE(m_indexBuffer);
- REF_PTR_RELEASE(m_pReflectionTexture);
- SAFE_RELEASE(m_vertexBufferD3D);
- SAFE_RELEASE(m_indexBufferD3D);
- if (m_waterTrackSystem)
- m_waterTrackSystem->ReleaseResources();
- if (m_dwWavePixelShader)
- m_pDev->DeletePixelShader(m_dwWavePixelShader);
- if (m_dwWaveVertexShader)
- m_pDev->DeleteVertexShader(m_dwWaveVertexShader);
-
- if (m_waterPixelShader)
- m_pDev->DeletePixelShader(m_waterPixelShader);
- if (m_trapezoidWaterPixelShader)
- m_pDev->DeletePixelShader(m_trapezoidWaterPixelShader);
- if (m_riverWaterPixelShader)
- m_pDev->DeletePixelShader(m_riverWaterPixelShader);
- m_dwWavePixelShader=0;
- m_dwWaveVertexShader=0;
- m_waterPixelShader = 0;
- m_trapezoidWaterPixelShader=0;
- m_riverWaterPixelShader=0;
- }
- //-------------------------------------------------------------------------------------------------
- /** (Re)allocates all W3D assets after a reset.. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::ReAcquireResources(void)
- {
- HRESULT hr;
- m_indexBuffer=NEW_REF(DX8IndexBufferClass,(6));
- // Fill up the IB
- {
- DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexBuffer);
- UnsignedShort *ib=lockIdxBuffer.Get_Index_Array();
- //quad of 2 triangles:
- // 3-----2
- // | /|
- // | / |
- // |/ |
- // 0-----1
- ib[0]=3;
- ib[1]=0;
- ib[2]=2;
- ib[3]=2;
- ib[4]=0;
- ib[5]=1;
- }
- m_pDev=DX8Wrapper::_Get_D3D_Device8();
- //We're using the same grid for either 3D Water Mesh or Pixel/Vertex shader. Just
- //allocate the right size depending on usage
- if (m_meshData)
- {
- //Create new grid data
- if (FAILED(generateIndexBuffer(m_gridCellsX+1,m_gridCellsY+1)))
- return;
- if (FAILED(generateVertexBuffer(m_gridCellsX+1,m_gridCellsY+1,sizeof(MaterMeshVertexFormat),false)))
- return;
- }
- else
- if (m_waterType == WATER_TYPE_2_PVSHADER)
- { //pixel/vertex shader based water assets.
- if (FAILED(hr=generateIndexBuffer(PATCH_SIZE,PATCH_SIZE)))
- return;
- if (FAILED(hr=generateVertexBuffer(PATCH_SIZE,PATCH_SIZE,sizeof(SEA_PATCH_VERTEX),true)))
- return;
- //shader decleration
- DWORD Declaration[]=
- {
- (D3DVSD_STREAM(0)),
- (D3DVSD_REG(0, D3DVSDT_FLOAT3)), // Position
- (D3DVSD_REG(1, D3DVSDT_D3DCOLOR)), // Diffuse
- (D3DVSD_REG(2, D3DVSDT_FLOAT2)), // Bump map texture
- (D3DVSD_END())
- };
- hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\wave.pso", &Declaration[0], 0, false, &m_dwWavePixelShader);
- if (FAILED(hr))
- return;
- hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\wave.vso", &Declaration[0], 0, true, &m_dwWaveVertexShader);
- if (FAILED(hr))
- return;
- // Create reflection texture
- m_pReflectionTexture = DX8Wrapper::Create_Render_Target (SEA_REFLECTION_SIZE, SEA_REFLECTION_SIZE);
- }
- if (m_waterTrackSystem)
- m_waterTrackSystem->ReAcquireResources();
- if (W3DShaderManager::getChipset() >= DC_GENERIC_PIXEL_SHADER_1_1)
- {
- ID3DXBuffer *compiledShader;
- char *shader =
- "ps.1.1\n \
- tex t0 \n\
- tex t1 \n\
- tex t2 \n\
- tex t3\n\
- mul r0,v0,t0 ; blend vertex color into t0. \n\
- mul r1, t1, t2 ; mul\n\
- add r0.rgb, r0, t3\n\
- +mul r0.a, r0, t3\n\
- add r0.rgb, r0, r1\n";
- hr = D3DXAssembleShader( shader, strlen(shader), 0, NULL, &compiledShader, NULL);
- if (hr==0) {
- hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader((DWORD*)compiledShader->GetBufferPointer(), &m_riverWaterPixelShader);
- compiledShader->Release();
- }
- shader =
- "ps.1.1\n \
- tex t0 \n\
- tex t1 \n\
- texbem t2, t1 ; use t1 as env map adjustment on t2.\n\
- mul r0,v0,t0 ; blend vertex color into t0. \n\
- mul r1.rgb,t2,c0 ; reduce t2 (environment mapped reflection) by constant\n\
- add r0.rgb, r0, r1";
- hr = D3DXAssembleShader( shader, strlen(shader), 0, NULL, &compiledShader, NULL);
- if (hr==0) {
- hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader((DWORD*)compiledShader->GetBufferPointer(), &m_waterPixelShader);
- compiledShader->Release();
- }
- shader =
- "ps.1.1\n \
- tex t0 \n\
- tex t1 \n\
- tex t2 \n\
- tex t3 ; get black shroud \n\
- mul r0,v0,t0 ; blend vertex color and alpha into base texture. \n\
- mad r0.rgb, t1, t2, r0 ; blend sparkles and noise \n\
- mul r0.rgb, r0, t3 ; blend in black shroud \n\
- ;\n";
- hr = D3DXAssembleShader( shader, strlen(shader), 0, NULL, &compiledShader, NULL);
- if (hr==0) {
- hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader((DWORD*)compiledShader->GetBufferPointer(), &m_trapezoidWaterPixelShader);
- compiledShader->Release();
- }
- }
- }
- void WaterRenderObjClass::load(void)
- {
- if (m_waterTrackSystem)
- m_waterTrackSystem->loadTracks();
- }
- //-------------------------------------------------------------------------------------------------
- /** Initializes water with dimensions and parent scene.
- * During rendering, we will render a water surface of given dimensions
- * and reflect the parent scene in its surface. For now, waters are
- * forced to be rectangles. */
- //-------------------------------------------------------------------------------------------------
- Int WaterRenderObjClass::init(Real waterLevel, Real dx, Real dy, SceneClass *parentScene, WaterType type)
- {
- m_iBumpFrame=0;
- m_fBumpScale=SEA_BUMP_SCALE;
- m_dx=dx;
- m_dy=dy;
- m_level=waterLevel;
- m_LastUpdateTime=timeGetTime();
- m_uScrollPerMs=0.001f;
- m_vScrollPerMs=0.001f;
- m_uOffset=0;
- m_vOffset=0;
- m_parentScene=parentScene;
- m_waterType = type;
- /// Hack for now
- //m_waterType = WATER_TYPE_0_TRANSLUCENT;
- ///@todo: calculate a real normal/distance for arbitrary planes.
- m_planeNormal=Vector3(0,0,1); //water plane normal
- m_planeDistance=m_level; //water plane distance(always at zero for now)
- m_meshLight=NEW_REF(LightClass,(LightClass::DIRECTIONAL));
- m_meshLight->Set_Ambient(Vector3(0.1f,0.1f,0.1f));
- m_meshLight->Set_Diffuse(Vector3(1.0f,1.0f,1.0f));
- m_meshLight->Set_Specular(Vector3(1.0f,1.0f,1.0f));
- m_meshLight->Set_Position(Vector3(1000,1000,1000));
- //testLight->Set_Spot_Direction(Vector3(TheGlobalData->m_terrainLightX,TheGlobalData->m_terrainLightY,TheGlobalData->m_terrainLightZ));
- m_meshLight->Set_Spot_Direction(Vector3(-0.57f,-0.57f,-0.57f));
- //Setup material for 3D Mesh water.
- m_meshVertexMaterialClass=NEW_REF(VertexMaterialClass,());
- m_meshVertexMaterialClass->Set_Shininess(20.0);
- m_meshVertexMaterialClass->Set_Ambient(1.0f,1.0f,1.0f);
- m_meshVertexMaterialClass->Set_Diffuse(1.0f,1.0f,1.0f);
- m_meshVertexMaterialClass->Set_Specular(0.5,0.5,0.5);
- m_meshVertexMaterialClass->Set_Opacity(WATER_MESH_OPACITY);
- m_meshVertexMaterialClass->Set_Lighting(true);
- //
- // assign the data from the WaterSettings[] global to the data for this
- // render object (we at present only have one water plane)
- //
- loadSetting( &m_settings[ TIME_OF_DAY_MORNING ], TIME_OF_DAY_MORNING );
- loadSetting( &m_settings[ TIME_OF_DAY_AFTERNOON ], TIME_OF_DAY_AFTERNOON );
- loadSetting( &m_settings[ TIME_OF_DAY_EVENING ], TIME_OF_DAY_EVENING );
- loadSetting( &m_settings[ TIME_OF_DAY_NIGHT ], TIME_OF_DAY_NIGHT );
- Set_Sort_Level(2); //force water to be drawn after all other non translucent objects in scene.
- Set_Force_Visible(TRUE); //water is always visible since it's a composite object made of multiple planes all over the map.
- ReAcquireResources();
- if (type == WATER_TYPE_2_PVSHADER || (W3DShaderManager::getChipset() >= DC_GENERIC_PIXEL_SHADER_1_1))
- { //geforce3 specific water requires some extra D3D assets
- m_pDev=DX8Wrapper::_Get_D3D_Device8();
- //save previous thumbnail mode
- WW3D::TextureThumbnailModeEnum tmMode=WW3D::Get_Texture_Thumbnail_Mode ();
- WW3D::Set_Texture_Thumbnail_Mode(WW3D::TEXTURE_THUMBNAIL_MODE_OFF);
- //load bump map textures off disk
- TextureClass *pBumpSource; //temporary textures in a format W3D understands
- TextureClass *pBumpSource2; //temporary textures in a format W3D understands
- Int i;
- i=NUM_BUMP_FRAMES;
- while (i--)
- {
- char bump_name[128];
- sprintf(bump_name,"caust%.2d.tga",i);
- pBumpSource=WW3DAssetManager::Get_Instance()->Get_Texture(bump_name);
- sprintf(bump_name,"caustS%.2d.tga",i);
- pBumpSource2=WW3DAssetManager::Get_Instance()->Get_Texture(bump_name);
- initBumpMap(m_pBumpTexture+i, pBumpSource);
- initBumpMap(m_pBumpTexture2+i, pBumpSource2);
- WW3DAssetManager::Get_Instance()->Release_Texture(pBumpSource);
- WW3DAssetManager::Get_Instance()->Release_Texture(pBumpSource2);
- REF_PTR_RELEASE(pBumpSource);
- REF_PTR_RELEASE(pBumpSource2);
- }
- //restore previous thumpnail mode
- WW3D::Set_Texture_Thumbnail_Mode(tmMode);
- }
- //Setup material for regular water
- m_vertexMaterialClass=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
-
- m_shaderClass = zFillAlphaShader;//ShaderClass::_PresetAlphaShader;ShaderClass::_PresetOpaqueShader;//detailOpaqueShader;
- m_shaderClass.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE); //water should be visible from both sides
- //Assets used for all types of water
- m_alphaClippingTexture=WW3DAssetManager::Get_Instance()->Get_Texture(SKYBODY_TEXTURE);
- #ifdef CLIP_GEOMETRY_TO_PLANE
- m_alphaClippingTexture=WW3DAssetManager::Get_Instance()->Get_Texture("alphaclip.tga");
- #endif
- m_skyBox = ((W3DAssetManager*)W3DAssetManager::Get_Instance())->Create_Render_Obj( "new_skybox", TheGlobalData->m_skyBoxScale, 0);
- //Enable clamping on all textures used by the skybox (to reduce corner seams).
- if (m_skyBox && m_skyBox->Class_ID() == RenderObjClass::CLASSID_MESH)
- {
- MeshClass *mesh=(MeshClass*) m_skyBox;
- MaterialInfoClass *material = mesh->Get_Material_Info();
- for (Int i=0; i<material->Texture_Count(); i++)
- {
- if (material->Peek_Texture(i))
- {
- material->Peek_Texture(i)->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- material->Peek_Texture(i)->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- }
- }
- }
- m_riverTexture=WW3DAssetManager::Get_Instance()->Get_Texture("TWWater01.tga");
-
- //For some reason setting a NULL texture does not result in 0xffffffff for pixel shaders so using explicit "white" texture.
- m_whiteTexture=MSGNEW("TextureClass") TextureClass(1,1,WW3D_FORMAT_A4R4G4B4,TextureClass::MIP_LEVELS_1);
- SurfaceClass *surface=m_whiteTexture->Get_Surface_Level();
- surface->DrawPixel(0,0,0xffffffff);
- REF_PTR_RELEASE(surface);
- m_waterNoiseTexture=WW3DAssetManager::Get_Instance()->Get_Texture("Noise0000.tga");
- m_riverAlphaEdge=WW3DAssetManager::Get_Instance()->Get_Texture("TWAlphaEdge.tga");
- m_waterSparklesTexture=WW3DAssetManager::Get_Instance()->Get_Texture("WaterSurfaceBubbles.tga");
- #ifdef DRAW_WATER_WAKES
- m_waterTrackSystem = NEW WaterTracksRenderSystem;
- m_waterTrackSystem->init();
- #endif
- return 0;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::reset( void )
- {
- // for vertex animated water mesh reset the values
- if( m_meshData)
- {
- Int i, j;
- WaterMeshData *pData;
- Int mx = m_gridCellsX + 1;
- Int my = m_gridCellsY + 1;
- // go through each mesh point and adjust the height according to the velocity
- for( j = 0, pData = m_meshData; j < (my + 2); j++ )
- {
- for( i = 0; i < (mx + 2); i++ )
- {
- // areset grid values for this cell
- pData->velocity = 0.0f;
- pData->height = 0.0f;
- pData->preferredHeight = 0.0f;
- pData->status = WaterRenderObjClass::AT_REST;
- // on to the next one
- pData++;
- } // end for i
- } // end for j
- // mesh data is no longer in motion
- m_meshInMotion = FALSE;
- } // end if, water type 3
- if (m_waterTrackSystem)
- m_waterTrackSystem->reset();
- }
- void WaterRenderObjClass::enableWaterGrid(Bool state)
- {
- m_doWaterGrid = state;
- m_drawingRiver = false;
- m_disableRiver = false;
- if (state && m_meshData == NULL)
- { //water type has changed, must allocate necessary assets for new water.
- //contains the current deformed water surface z(height) values. With 1 vertex invisible border
- //around surface to speed up normal calculations.
- m_meshDataSize = (m_gridCellsX+1+2)*(m_gridCellsY+1+2);
- m_meshData=NEW WaterMeshData[ m_meshDataSize ];
- memset(m_meshData,0,sizeof(WaterMeshData)*(m_gridCellsX+1+2)*(m_gridCellsY+1+2));
- reset();
- //Release existing grid data
- SAFE_RELEASE(m_vertexBufferD3D);
- SAFE_RELEASE(m_indexBufferD3D);
- //Create new grid data
- if (FAILED(generateIndexBuffer(m_gridCellsX+1,m_gridCellsY+1)))
- return;
- if (FAILED(generateVertexBuffer(m_gridCellsX+1,m_gridCellsY+1,sizeof(MaterMeshVertexFormat),false)))
- return;
- }
- }
- // ------------------------------------------------------------------------------------------------
- /** Update phase for water if we need it. This called once per client frame reguardless
- * of how fast the logic framerate is running */
- // ------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::update( void )
- {
- static UnsignedInt lastLogicFrame = 0;
- UnsignedInt currLogicFrame = 0;
-
- if( TheGameLogic )
- currLogicFrame = TheGameLogic->getFrame();
- m_riverVOrigin += 0.002f;
- m_riverXOffset += (Real)(0.0125*33/5000);
- m_riverYOffset += (Real)(2*0.0125*33/5000);
- if (m_riverXOffset > 1) m_riverXOffset -= 1;
- if (m_riverYOffset > 1) m_riverYOffset -= 1;
- if (m_riverXOffset < -1) m_riverXOffset += 1;
- if (m_riverYOffset < -1) m_riverYOffset += 1;
- m_iBumpFrame++;
- if (m_iBumpFrame >= NUM_BUMP_FRAMES) {
- m_iBumpFrame = 0;
- }
- // we only process some things if the logic frame has changed
- if( lastLogicFrame != currLogicFrame )
- {
- // for vertex animated water we need to update the vector field
- if( m_doWaterGrid && m_meshInMotion == TRUE )
- {
- const Real PREFERRED_HEIGHT_FUDGE = 1.0f; ///< this is close enough to at rest
- const Real AT_REST_VELOCITY_FUDGE = 1.0f; ///< when we're close enought to at rest height and velocity we will stop
- const Real WATER_DAMPENING = 0.93f; ///< use with up force of 15.0
- Int i, j;
- Int mx = m_gridCellsX+1;
- Int my = m_gridCellsY+1;
- WaterMeshData *pData;
- //
- // we will mark the mesh as clean now ... if any of the fields are still in motion
- // they will continue to mark the mesh as dirty so processing continues next frame
- //
- m_meshInMotion = FALSE;
- // go through each mesh point and adjust the height according to the velocity
- for( j = 0, pData = m_meshData; j < (my + 2); j++ )
- {
- for( i = 0; i < (mx + 2); i++ )
- {
- // only pay attention to mesh points that are in motion
- if( BitTest( pData->status, WaterRenderObjClass::IN_MOTION ) )
- {
- // DAMPENING to slow the changes down
- pData->velocity *= WATER_DAMPENING;
- // if the height here is below our preferred height, we want to add upward force to counteract it
- if( pData->height < pData->preferredHeight )
- pData->velocity -= TheGlobalData->m_gravity * 3.0f;
- else
- pData->velocity += TheGlobalData->m_gravity * 3.0f;
- // adjust the height at this grid location according to the current velocity
- pData->height = pData->height + pData->velocity;
- //
- // if we are close enough to our preferred height and our velocity is small enough
- // this will be our resting location
- //
- if( fabs( pData->height - pData->preferredHeight ) < PREFERRED_HEIGHT_FUDGE &&
- fabs( pData->velocity ) < AT_REST_VELOCITY_FUDGE )
- {
- BitClear( pData->status, WaterRenderObjClass::IN_MOTION );
- pData->height = pData->preferredHeight;
- pData->velocity = 0.0f;
- } // end if
- else
- {
- // there is still motion in the mesh, we need to process next frame
- m_meshInMotion = TRUE;
- } // end else
- } // end if
- // on to the next one
- pData++;
- } // end for i
- } // end for j
- } // end if
- // mark the last logic frame we processed on
- lastLogicFrame = currLogicFrame;
- } // end if, a logic frame has passed
- } // end update
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::replaceSkyboxTexture(const AsciiString& oldTexName, const AsciiString& newTextName)
- {
- W3DAssetManager* assetManager = ((W3DAssetManager*)W3DAssetManager::Get_Instance());
- assetManager->replacePrototypeTexture(m_skyBox, oldTexName.str(), newTextName.str());
- //Enable clamping on all textures used by the skybox (to reduce corner seams).
- if (m_skyBox && m_skyBox->Class_ID() == RenderObjClass::CLASSID_MESH)
- {
- MeshClass *mesh=(MeshClass*) m_skyBox;
- MaterialInfoClass *material = mesh->Get_Material_Info();
- for (Int i=0; i<material->Texture_Count(); i++)
- {
- if (material->Peek_Texture(i))
- {
- material->Peek_Texture(i)->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- material->Peek_Texture(i)->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- }
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Adjusts various water/sky rendering settings that depend on time of day. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::setTimeOfDay(TimeOfDay tod)
- {
- m_tod=tod;
- if (m_waterType == WATER_TYPE_2_PVSHADER)
- generateVertexBuffer(PATCH_SIZE,PATCH_SIZE,sizeof(SEA_PATCH_VERTEX),true); //update the water mesh with new lighting/alpha
- }
- //-------------------------------------------------------------------------------------------------
- /**Copies GDF settings dealing with a particular time of day into our own
- * structures. Also allocates any required W3D assets (textures). */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::loadSetting( Setting *setting, TimeOfDay timeOfDay )
- {
- SurfaceClass::SurfaceDescription surfaceDesc;
- // sanity
- DEBUG_ASSERTCRASH( setting, ("WaterRenderObjClass::loadSetting, NULL setting\n") );
-
- // textures
- setting->skyTexture = WW3DAssetManager::Get_Instance()->Get_Texture( WaterSettings[ timeOfDay ].m_skyTextureFile.str() );
- setting->waterTexture = WW3DAssetManager::Get_Instance()->Get_Texture( WaterSettings[ timeOfDay ].m_waterTextureFile.str() );
- // texelss per unit
- setting->skyTexelsPerUnit = WaterSettings[ timeOfDay ].m_skyTexelsPerUnit;
- setting->waterTexture->Get_Level_Description( surfaceDesc, 0 );
- setting->skyTexelsPerUnit /= (Real)surfaceDesc.Width;
- // water repeat
- setting->waterRepeatCount = WaterSettings[ timeOfDay ].m_waterRepeatCount;
- // U and V scroll per ms
- setting->uScrollPerMs = WaterSettings[ timeOfDay ].m_uScrollPerMs;
- setting->vScrollPerMs = WaterSettings[ timeOfDay ].m_vScrollPerMs;
- //
- // vertex colors
- //
- // bottom left
- setting->vertex00Diffuse = (WaterSettings[ timeOfDay ].m_vertex00Diffuse.red << 16) |
- (WaterSettings[ timeOfDay ].m_vertex00Diffuse.green << 8) |
- WaterSettings[ timeOfDay ].m_vertex00Diffuse.blue;
- // top left
- setting->vertex01Diffuse = (WaterSettings[ timeOfDay ].m_vertex01Diffuse.red << 16) |
- (WaterSettings[ timeOfDay ].m_vertex01Diffuse.green << 8) |
- WaterSettings[ timeOfDay ].m_vertex01Diffuse.blue;
- // bottom right
- setting->vertex10Diffuse = (WaterSettings[ timeOfDay ].m_vertex10Diffuse.red << 16) |
- (WaterSettings[ timeOfDay ].m_vertex10Diffuse.green << 8) |
- WaterSettings[ timeOfDay ].m_vertex10Diffuse.blue;
- // top right
- setting->vertex11Diffuse = (WaterSettings[ timeOfDay ].m_vertex11Diffuse.red << 16) |
- (WaterSettings[ timeOfDay ].m_vertex11Diffuse.green << 8) |
- WaterSettings[ timeOfDay ].m_vertex11Diffuse.blue;
- // diffuse water color
- setting->waterDiffuse = (WaterSettings[ timeOfDay ].m_waterDiffuseColor.alpha << 24) |
- (WaterSettings[ timeOfDay ].m_waterDiffuseColor.red << 16) |
- (WaterSettings[ timeOfDay ].m_waterDiffuseColor.green << 8) |
- WaterSettings[ timeOfDay ].m_waterDiffuseColor.blue;
- // transparent water color
- setting->transparentWaterDiffuse = (WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.alpha << 24) |
- (WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.red << 16) |
- (WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.green << 8) |
- WaterSettings[ timeOfDay ].m_transparentWaterDiffuse.blue;
- }
- //-------------------------------------------------------------------------------------------------
- /** Our water may use effects that require run-time rendered textures. These
- * textures need to be updated before we start rendering to the main screen
- * render target because D3D doesn't multiple render targets. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::updateRenderTargetTextures(CameraClass *cam)
- {
- if (m_waterType == WATER_TYPE_2_PVSHADER && getClippedWaterPlane(cam, NULL) &&
- TheTerrainRenderObject && TheTerrainRenderObject->getMap())
- renderMirror(cam); //generate texture containing reflected scene
- }
- //-------------------------------------------------------------------------------------------------
- /** Renders the reflected scene into an offscreen texture. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::renderMirror(CameraClass *cam)
- {
- #ifdef EXTENDED_STATS
- if (DX8Wrapper::stats.m_disableWater) {
- return;
- }
- #endif
- Matrix3D OldCameraMatrix=cam->Get_Transform();
- Matrix4 FullMatrix4(cam->Get_Transform()); //copy 3x4 matrix into a 4x4
- Vector3 WaterNormal(0,0,1); //normal of plane used for reflection
- Vector4 WaterPlane(WaterNormal.X,WaterNormal.Y,WaterNormal.Z,m_level);
- Vector3 rRight,rUp,rN,rPos; //orientation and translation vectors of camera
- Matrix4 FullMatrix(FullMatrix4.Transpose()); //swap rows/columns
- //reflect camera right vector
- Real axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[0],WaterNormal);
- rRight = (Vector3&)FullMatrix[0] - (2.0f*axis_distance*WaterNormal);
- //reflect camera up vector
- axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[1],WaterNormal);
- rUp = (Vector3&)FullMatrix[1] - (2.0f*axis_distance*WaterNormal);
- //reflect camera n vector
- axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[2],WaterNormal);
- rN = (Vector3&)FullMatrix[2] - (2.0f*axis_distance*WaterNormal);
- //reflect camera position
- axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[3],WaterNormal); //distance cam to origin
- axis_distance -= WaterPlane.W; // subtract mirror plane distance to get distance camera to plane
- rPos = (Vector3&)FullMatrix[3] - (2.0f*axis_distance*WaterNormal);
- //generate a new camera matrix from reflected vectors
- Matrix3D reflectedTransform(rRight,rUp,rN,rPos);
- DX8Wrapper::Set_Render_Target(m_pReflectionTexture);
- // Clear the backbuffer
- WW3D::Begin_Render(false,true,Vector3(0.0f,0.0f,0.0f)); //clearing only z-buffer since background always filled with clouds
- cam->Set_Transform( reflectedTransform );
- //Force reflected image to be drawn into full texture size - not a viewport inside texture.
- Vector2 vMin,vMax,vOldMax,vOldMin;
- cam->Get_Viewport(vOldMin,vOldMax);
- vMax.X=vMax.Y=1.0f;
- vMin.X=vMin.Y=0.0f;
- cam->Set_Viewport(vMin,vMax);
- cam->Apply(); //force an update of all the camera dependent parameters like frustum clip planes
- //flip the winding order of polygons to draw the reflected back sides.
- ShaderClass::Invert_Backface_Culling(true);
- // Render the scene
- renderSky();
- if (m_tod == TIME_OF_DAY_NIGHT)
- renderSkyBody(&reflectedTransform);
- WW3D::Render(m_parentScene,cam);
- cam->Set_Transform(OldCameraMatrix); //restore original non-reflected matrix
- cam->Set_Viewport(vOldMin,vOldMax);
- cam->Apply(); //force an update of all the camera dependent parameters like frustum clip planes
- ShaderClass::Invert_Backface_Culling(false);
- WW3D::End_Render(false);
- // Change the rendertarget back to the main backbuffer
- DX8Wrapper::Set_Render_Target((IDirect3DSurface8 *)NULL);
- }
- //-------------------------------------------------------------------------------------------------
- /** Renders (draws) the water.
- * Algorithm:
- * Draw reflected scene.
- * Draw reflected sky layer(s) and bodies.
- * Clear Zbuffer
- * Fill Zbuffer by drawing water surface (allows proper sorting into regular scene).
- * Draw non-reflected scene (done in regular app render loop).
- *
- * This algorithm doesn't apply to translucent water, which is rendered into a
- * texture and rendered at end of scene. */
- //-------------------------------------------------------------------------------------------------
- //DECLARE_PERF_TIMER(Water)
- void WaterRenderObjClass::Render(RenderInfoClass & rinfo)
- {
- //USE_PERF_TIMER(Water)
- if (TheTerrainRenderObject && !TheTerrainRenderObject->getMap())
- return; //no map has been loaded yet.
- if (((RTS3DScene *)rinfo.Camera.Get_User_Data())->getCustomPassMode() == SCENE_PASS_ALPHA_MASK ||
- ((SceneClass *)rinfo.Camera.Get_User_Data())->Get_Extra_Pass_Polygon_Mode() == SceneClass::EXTRA_PASS_CLEAR_LINE)
- return; //water is not drawn in wireframe or custom scene passes
- #ifdef EXTENDED_STATS
- if (DX8Wrapper::stats.m_disableWater) {
- return;
- }
- #endif
- if (ShaderClass::Is_Backface_Culling_Inverted())
- return; //the water object will not reflect in itself, so don't do anything if rendering a mirror.
- //this water type needs to rendered after the rest of scene, so buffer it up for later
- // If static sort lists are enabled and this mesh has a sort level, put it on the list instead
- // of rendering it.
- unsigned int sort_level = (unsigned int)Get_Sort_Level();
- if (WW3D::Are_Static_Sort_Lists_Enabled() && sort_level != SORT_LEVEL_NONE)
- {
- WW3D::Add_To_Static_Sort_List(this, sort_level);
- return;
- }
- switch(m_waterType)
- {
- case WATER_TYPE_0_TRANSLUCENT:
- case WATER_TYPE_3_GRIDMESH:
- //Draw the water surface as a bunch of alpha blended tiles covering areas where water is visible
- renderWater();
- if (!m_drawingRiver || m_disableRiver) {
- renderWaterMesh(); //Draw water surface as 3D deforming mesh if it's enabled on this map.
- }
- break;
- case WATER_TYPE_2_PVSHADER:
- //Pixel/Vertex Shader based water which uses an off-screen rendered reflection texture
- drawSea(rinfo); //draw water surface
- break;
- case WATER_TYPE_1_FB_REFLECTION:
- {
- //Normal frame buffer reflection water type. Non translucent. Legacy code we're not using anymore.
- Matrix3D OldCameraMatrix=rinfo.Camera.Get_Transform();
- Matrix4 FullMatrix4(rinfo.Camera.Get_Transform()); //copy 3x4 matrix into a 4x4
- Vector3 WaterNormal(0,0,1); //normal of plane used for reflection
- Vector4 WaterPlane(WaterNormal.X,WaterNormal.Y,WaterNormal.Z,m_level); //assume distance to origin 0
- Vector3 rRight,rUp,rN,rPos; //orientation and translation vectors of camera
- Matrix4 FullMatrix(FullMatrix4.Transpose()); //swap rows/columns
- //reflect camera right vector
- Real axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[0],WaterNormal);
- rRight = (Vector3&)FullMatrix[0] - (2.0f*axis_distance*WaterNormal);
- //reflect camera up vector
- axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[1],WaterNormal);
- rUp = (Vector3&)FullMatrix[1] - (2.0f*axis_distance*WaterNormal);
- //reflect camera n vector
- axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[2],WaterNormal);
- rN = (Vector3&)FullMatrix[2] - (2.0f*axis_distance*WaterNormal);
- //reflect camera position
- axis_distance=Vector3::Dot_Product((Vector3&)FullMatrix[3],WaterNormal); //distance cam to origin
- axis_distance -= WaterPlane.W; // subtract mirror plane distance to get distance camera to plane
- rPos = (Vector3&)FullMatrix[3] - (2.0f*axis_distance*WaterNormal);
- //generate a new camera matrix from reflected vectors
- Matrix3D reflectedTransform(rRight,rUp,rN,rPos);
- //flip the winding order of polygons to draw the reflected back sides.
- ShaderClass::Invert_Backface_Culling(true);
- #ifdef CLIP_GEOMETRY_TO_PLANE
- // Set a clip plane, so that only objects above the water are reflected
- WaterPlane.W *= -1.0f; //flip sign of plane distance for D3D use.
- // DX8Wrapper::Set_DX8_Clip_Plane( 0, &WaterPlane.X );
- // DX8Wrapper::Set_DX8_Render_State(D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 ); //turn on first clip plane
- // Alternate Clipping Method using alpha testing hack!
- /**************************************************************************************/
- D3DXMATRIX inv;
- D3DXMATRIX clipMatrix;
- Real det;
- Matrix4 curView;
- //get current view matrix
- DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
- //get inverse of view matrix(= view to world matrix)
- D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
- //create clipping matrix by inserting our plane equation into the 1st column
- D3DXMatrixIdentity(&clipMatrix);
- clipMatrix(0,0)=WaterNormal.X;
- clipMatrix(1,0)=WaterNormal.Y;
- clipMatrix(2,0)=WaterNormal.Z;
- clipMatrix(3,0)=WaterPlane.W+0.5f;
- inv *=clipMatrix;
- // Change texture wrapping mode to 'clamp' for texture stage 1
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
- // Use CameraSpace vertices as input to matrix and use texture wrap mode from stage 1
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION|1);
- // Two output coordinates are used.
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
- // Set texture generation matrix for stage 1
- DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, *((Matrix4*)&inv));
- // Disable bilinear filtering
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
- // Pass stage 0 texture data untouched(by modulating with white)
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //stage 1 texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); //previous stage texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); //module with white => does nothing
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); //stage 1 texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT ); //previous stage texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); //modulate with clipping texture
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAREF,0x00);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHAFUNC,D3DCMP_NOTEQUAL); //pass pixels who's alpha is not zero
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, true); //test pixels if transparent(clipped) before rendering.
- // Set clipping texture
- m_alphaClippingTexture->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- m_alphaClippingTexture->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- m_alphaClippingTexture->Set_Min_Filter(TextureClass::FILTER_TYPE_NONE);
- m_alphaClippingTexture->Set_Mag_Filter(TextureClass::FILTER_TYPE_NONE);
- m_alphaClippingTexture->Set_Mip_Mapping(TextureClass::FILTER_TYPE_NONE);
- DX8Wrapper::Set_Texture(0,m_alphaClippingTexture);
- //TODO: Will have to make sure that the shader system is not resetting my stage 1 setup
- //while rendering the scene
- /*************************************************************************************/
- #endif
- #if 0 // No longer do simple rendering.
- if (TheGlobalData->m_useWaterPlane)
- {
- //@todo : Would it be better to create a new camera or change the transform of the
- //existing one?
- rinfo.Camera.Set_Transform( reflectedTransform );
- rinfo.Camera.Apply(); //force an update of all the camera dependent parameters like frustum clip planes
- if(m_useCloudLayer)
- {
- if (TheGlobalData && TheGlobalData->m_drawEntireTerrain)
- m_skyBox->Render(rinfo);
- else
- {
- renderSky();
- if (m_tod == TIME_OF_DAY_NIGHT)
- renderSkyBody(&reflectedTransform);
- }
- }
- WW3D::Render(m_parentScene,&rinfo.Camera);
- rinfo.Camera.Set_Transform(OldCameraMatrix); //restore original non-reflected matrix
- rinfo.Camera.Apply(); //force an update of all the camera dependent parameters like frustum clip planes
- //clear the z-buffer to remove changes made by objects inside mirror
- DX8Wrapper::Clear(false,true,Vector3(0.1f,0.1f,0.1f));
- }
- #endif
- #ifdef CLIP_GEOMETRY_TO_PLANE
- //restore default culling mode
- // DX8Wrapper::Set_DX8_Render_State(D3DRS_CLIPPLANEENABLE, 0 ); //turn off first clip plane
- //disable texture coordinate generation
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, false); //disable alpha testing
- #endif
- ShaderClass::Invert_Backface_Culling(false); //return culling back to normal
- ShaderClass::Invalidate(); //reset shading system so it forces full state set.
- renderWater();
- } //WATER_TYPE_1
- default:
- break;
- }//switch
- if (TheGlobalData && TheGlobalData->m_drawSkyBox)
- { //center skybox around camera
- Vector3 pos=rinfo.Camera.Get_Position();
- pos.Z = TheGlobalData->m_skyBoxPositionZ;
- m_skyBox->Set_Position(pos);
- m_skyBox->Render(rinfo);
- }
- //Clean up after any pixel shaders.
- //Force render state apply so that the "NULL" texture gets applied to D3D, thus releasing shroud reference count.
- DX8Wrapper::Apply_Render_State_Changes();
- DX8Wrapper::Invalidate_Cached_Render_States();
- if (m_waterTrackSystem)
- m_waterTrackSystem->flush(rinfo);
- // renderWaterMesh();
- // renderWaterWave();
- }
- //-------------------------------------------------------------------------------------------------
- /** Clips the water plane to the current camera frustum and returns a bounding
- * box enclosing the clipped plane. Returns false if water plane is not visible. */
- //-------------------------------------------------------------------------------------------------
- Bool WaterRenderObjClass::getClippedWaterPlane(CameraClass *cam, AABoxClass *box)
- {
- const FrustumClass & frustum = cam->Get_Frustum();
- ClipPolyClass ClippedPoly0;
- ClipPolyClass ClippedPoly1;
- ///@todo: generate proper sized polygon
- ClippedPoly0.Reset();
- ClippedPoly0.Add_Vertex(Vector3(0,0,m_level));
- ClippedPoly0.Add_Vertex(Vector3(0,m_dy,m_level));
- ClippedPoly0.Add_Vertex(Vector3(m_dx,m_dy,m_level));
- ClippedPoly0.Add_Vertex(Vector3(m_dx,0,m_level));
- //clip against all 6 frustum planes
- ClippedPoly0.Clip(frustum.Planes[0],ClippedPoly1);
- ClippedPoly1.Clip(frustum.Planes[1],ClippedPoly0);
- ClippedPoly0.Clip(frustum.Planes[2],ClippedPoly1);
- ClippedPoly1.Clip(frustum.Planes[3],ClippedPoly0);
- ClippedPoly0.Clip(frustum.Planes[4],ClippedPoly1);
- ClippedPoly1.Clip(frustum.Planes[5],ClippedPoly0);
- Int final_vcount = ClippedPoly0.Verts.Count();
- //make sure the polygon is visible
- if (final_vcount >= 3)
- {
- //find axis aligned bounding box around visible polygon
- if (box)
- box->Init(&(ClippedPoly0.Verts[0]),final_vcount);
- return TRUE;
- }
- return FALSE; //water plane is not visible
- }
- //-------------------------------------------------------------------------------------------------
- /** Draws the water surface using a custom D3D vertex/pixel shader and a
- * reflection texture. Only tested to work on GeForce3. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::drawSea(RenderInfoClass & rinfo)
- {
- AABoxClass seaBox;
- if (!getClippedWaterPlane(&rinfo.Camera,&seaBox))
- return; //the sea is not visible
- D3DXMATRIX matProj, matView, matWW3D;
- //create a transform which will flip the y and z coordinates to fit our system
- memset(&matWW3D,0,sizeof(D3DMATRIX));
- matWW3D._11=1.0f;
- matWW3D._32=1.0f;
- matWW3D._23=1.0f;
- matWW3D._44=1.0f;
- Matrix3D tm(Transform);
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
- DX8Wrapper::Set_Texture(0,NULL); //we'll be setting our own textures, so reset W3D
- DX8Wrapper::Set_Texture(1,NULL); //we'll be setting our own textures, so reset W3D
- DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
- Vector3 camTran;
- rinfo.Camera.Get_Transform().Get_Translation(&camTran);
- DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, *(Matrix4*)&matView);
- DX8Wrapper::_Get_DX8_Transform(D3DTS_PROJECTION, *(Matrix4*)&matProj);
- //default setup from Kenny's demo
- m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
- m_pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
- m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
- m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
- m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
- m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
- m_pDev->SetTextureStageState( 2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- m_pDev->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|2);
- m_pDev->SetTextureStageState( 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- m_pDev->SetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|3);
- // m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- // m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- // m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT );
- // m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_POINT );
- // m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_POINT );
- // m_pDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE );
- //end of default setup
- m_pDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- m_pDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
- m_pDev->SetRenderState( D3DRS_WRAP0, D3DWRAP_U | D3DWRAP_V);
- m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
- m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
- m_pDev->SetTexture( 0, m_pBumpTexture[m_iBumpFrame]);
- #ifdef MIPMAP_BUMP_TEXTURE
- m_pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT );
- m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- #endif
- m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT00, F2DW(m_fBumpScale) );
- m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT01, F2DW(0.0f) );
- m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT10, F2DW(0.0f) );
- m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVMAT11, F2DW(m_fBumpScale) );
- m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVLSCALE, F2DW(1.0f) );
- m_pDev->SetTextureStageState( 1, D3DTSS_BUMPENVLOFFSET, F2DW(0.0f) );
- m_pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- m_pDev->SetRenderState(D3DRS_ZWRITEENABLE , FALSE);
- D3DXMATRIX mat;
- memset(&mat,0,sizeof(D3DXMATRIX));
- mat._11 = 0.5f; mat._12 = -0.5f; mat._13 = 0.5f; mat._14=0.5f;
- mat._21 = 0.5f; mat._22 = 0.5f; mat._23 = 0.0f; mat._24=0.0f;
- mat._31 = 0.0f; mat._32 = 0.0f; mat._33 = 0.0f; mat._34=1.0f;
- mat._41 = 0.0f; mat._42 = 0.0f; mat._43 = 0.0f; mat._44=1.0f;
- m_pDev->SetVertexShaderConstant(CV_TEXPROJ_0, &mat, 4);
- // Setup constants
- m_pDev->SetVertexShaderConstant(CV_ZERO, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1);
- m_pDev->SetVertexShaderConstant(CV_ONE, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);
- m_pDev->SetVertexShader(m_dwWaveVertexShader);
- m_pDev->SetPixelShader(m_dwWavePixelShader);
- // Make reflection brighter to compensate for darker coloring on sea floor
- // m_pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
- // m_pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );
- m_pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- m_pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
- m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , TRUE);
- m_pDev->SetTexture( 1, m_pReflectionTexture->Peek_DX8_Texture());
- // m_pDev->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);//LORENZEN
- Int patchX,patchY,startX,startY;
- D3DXMATRIX patchMatrix;
- memset(&patchMatrix,0,sizeof(D3DXMATRIX));
- patchMatrix._11=PATCH_SCALE;
- patchMatrix._22=1.0f;
- patchMatrix._33=PATCH_SCALE;
- patchMatrix._44=1.0f;
- m_pDev->SetStreamSource(0,m_vertexBufferD3D,sizeof(WaterRenderObjClass::SEA_PATCH_VERTEX));
- m_pDev->SetIndices(m_indexBufferD3D,0);
- 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++)
- {
- 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++)
- {
- D3DXMATRIX matWorldViewProj, matTemp, matTempWorld;
- patchMatrix._41=(float)(patchX*PATCH_WIDTH*PATCH_SCALE );
- patchMatrix._43=(float)(patchY*PATCH_WIDTH*PATCH_SCALE );
- //convert the default D3D coordinate system into ours
- D3DXMatrixMultiply(&matTempWorld, &patchMatrix, &matWW3D);
- D3DXMatrixMultiply(&matTemp, &matTempWorld, &matView);
- D3DXMatrixMultiply(&matWorldViewProj, &matTemp, &matProj);
- //matrices must be transposed before loading into vertex shader registers
- D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
- m_pDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj, 4); //pass transform matrix into shader
- m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,m_numVertices,0,m_numIndices);
- }
- }
- // m_pDev->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
- m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , FALSE);
- m_pDev->SetTexture( 0, NULL); //release reference to bump texture
- m_pDev->SetTexture( 1, NULL); //release reference to reflection texture
- m_pDev->SetTexture( 2, NULL); //release reference to reflection texture
- m_pDev->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- m_pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
- m_pDev->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- m_pDev->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
- m_pDev->SetRenderState(D3DRS_ZWRITEENABLE , TRUE);
- m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- m_pDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
- m_pDev->SetRenderState( D3DRS_WRAP0, 0); //turn off texture wrapping
- m_pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
- m_pDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- //Restore old transforms
- DX8Wrapper::_Set_DX8_Transform(D3DTS_VIEW, *(Matrix4*)&matView);
- DX8Wrapper::_Set_DX8_Transform(D3DTS_PROJECTION, *(Matrix4*)&matProj);
- m_pDev->SetPixelShader(0); //turn off pixel shader
- m_pDev->SetVertexShader(DX8_FVF_XYZDUV1); //turn off custom vertex shader
- DX8Wrapper::Invalidate_Cached_Render_States();
- if (TheTerrainRenderObject->getShroud())
- {
- //do second pass to apply the shroud on water plane
- W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
- W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
- m_pDev->SetStreamSource(0,m_vertexBufferD3D,sizeof(WaterRenderObjClass::SEA_PATCH_VERTEX));
- m_pDev->SetIndices(m_indexBufferD3D,0);
- 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++)
- {
- 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++)
- {
- D3DXMATRIX matTemp;
- patchMatrix._41=(float)(patchX*PATCH_WIDTH*PATCH_SCALE);
- patchMatrix._43=(float)(patchY*PATCH_WIDTH*PATCH_SCALE);
- D3DXMatrixMultiply(&matTemp, &patchMatrix, &matWW3D);
- DX8Wrapper::_Set_DX8_Transform(D3DTS_WORLD, *(Matrix4*)&matTemp);
- m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,m_numVertices,0,m_numIndices);
- }
- }
- W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
- }
- }
- #define FEATHER_LAYER_COUNT (5.0f)
- #define FEATHER_THICKNESS (4.0f)
- //-------------------------------------------------------------------------------------------------
- /** Renders (draws) the water surface.*/
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::renderWater(void)
- {
- for (PolygonTrigger *pTrig=PolygonTrigger::getFirstPolygonTrigger(); pTrig; pTrig = pTrig->getNext()) {
- if (pTrig->isWaterArea()) {
- if (pTrig->getNumPoints()>2) {
- if (pTrig->isRiver()) {
- drawRiverWater(pTrig);
- continue;
- }
- Int k;
- for (k=1; k<pTrig->getNumPoints()-1; k=k+2) {
- ICoord3D pt3 = *pTrig->getPoint(0);
- ICoord3D pt2 = *pTrig->getPoint(k);
- ICoord3D pt1 = *pTrig->getPoint(k+1);
- ICoord3D pt0 = *pTrig->getPoint(k+1);
- if (k+2<pTrig->getNumPoints()) {
- pt0 = *pTrig->getPoint(k+2);
- }
- Vector3 points[4];
- points[0].Set(pt0.x, pt0.y, pt0.z);
- points[1].Set(pt1.x, pt1.y, pt1.z);
- points[2].Set(pt2.x, pt2.y, pt2.z);
- points[3].Set(pt3.x, pt3.y, pt3.z);
- if ( TheGlobalData->m_featherWater )
- {
- for (int r = 0; r < TheGlobalData->m_featherWater; ++r)
- {
- drawTrapezoidWater(points);
- points[0].Z += (FEATHER_THICKNESS/TheGlobalData->m_featherWater);
- }
- }
- else
- drawTrapezoidWater(points);
- }
- }
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Renders (draws) the sky plane. Will apply current time-of-day settings including
- * some simple UV scrolling animation. */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::renderSky(void)
- {
- Int timeNow,timeDiff;
- Real fu,fv;
- Setting *setting=&m_settings[m_tod];
- timeNow=timeGetTime();
- timeDiff=timeNow-m_LastUpdateTime;
- m_LastUpdateTime=timeNow;
- m_uOffset += timeDiff * setting->uScrollPerMs * setting->skyTexelsPerUnit;
- m_vOffset += timeDiff * setting->vScrollPerMs * setting->skyTexelsPerUnit;
- //clamp uv coordinate into 0,1 range
- m_uOffset = m_uOffset - (Real)((Int) m_uOffset);
- m_vOffset = m_vOffset - (Real)((Int) m_vOffset);
- fu= m_uOffset + (SKYPLANE_SIZE * 2) * setting->skyTexelsPerUnit;
- fv= m_vOffset + (SKYPLANE_SIZE * 2) * setting->skyTexelsPerUnit;
- VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
- DX8Wrapper::Set_Material(vmat);
- REF_PTR_RELEASE(vmat);
- ShaderClass m_shader2=ShaderClass::_PresetOpaqueShader;
- m_shader2.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
- m_shader2.Set_Depth_Compare(ShaderClass::PASS_ALWAYS); //no need to check against z-buffer, sky always rendered first.
- m_shader2.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); //sky is always behind everything so no need to update z-buffer
- DX8Wrapper::Set_Shader(m_shader2);
- DX8Wrapper::Set_Texture(0,setting->skyTexture);
- //draw an infinite sky plane
- DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,4);
- {
- DynamicVBAccessClass::WriteLockClass lock(&vb_access);
- VertexFormatXYZNDUV2* verts=lock.Get_Formatted_Vertex_Array();
- if(verts)
- {
- verts[0].x=-SKYPLANE_SIZE;
- verts[0].y=SKYPLANE_SIZE;
- verts[0].z=SKYPLANE_HEIGHT;
- verts[0].u1=m_uOffset;
- verts[0].v1=fv;
- verts[0].diffuse=setting->vertex01Diffuse;
-
- verts[1].x=SKYPLANE_SIZE;
- verts[1].y=SKYPLANE_SIZE;
- verts[1].z=SKYPLANE_HEIGHT;
- verts[1].u1=fu;
- verts[1].v1=fv;
- verts[1].diffuse=setting->vertex11Diffuse;
-
- verts[2].x=SKYPLANE_SIZE;
- verts[2].y=-SKYPLANE_SIZE;
- verts[2].z=SKYPLANE_HEIGHT;
- verts[2].u1=fu;
- verts[2].v1=m_vOffset;
- verts[2].diffuse=setting->vertex10Diffuse;
-
- verts[3].x=-SKYPLANE_SIZE;
- verts[3].y=-SKYPLANE_SIZE;
- verts[3].z=SKYPLANE_HEIGHT;
- verts[3].u1=m_uOffset;
- verts[3].v1=m_vOffset;
- verts[3].diffuse=setting->vertex00Diffuse;
- }
- }
- DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
- DX8Wrapper::Set_Vertex_Buffer(vb_access);
- Matrix3D tm(1);
- tm.Set_Translation(Vector3(0,0,0));
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
- DX8Wrapper::Draw_Triangles( 0,2, 0, 4); //draw a quad, 2 triangles, 4 verts
- }
- //-------------------------------------------------------------------------------------------------
- /** Renders (draws) the sky body. Used for moon and sun. We rotate the image
- * so that it always faces the camera. This removes perspective and helps hide that
- * it's a flat image. */
- //-------------------------------------------------------------------------------------------------
- /// @todo: Add code to render properly sorted sun sky body.
- void WaterRenderObjClass::renderSkyBody(Matrix3D *mat)
- {
- Vector3 cPos;
- Vector3 pView,pRight,pUp,pPos(SKYBODY_X,SKYBODY_Y,SKYBODY_HEIGHT);
- mat->Get_Translation(&cPos);
- pView=cPos-pPos; //billboard to camera
- pView.Normalize(); //particle view direction
- Vector3 WorldUp(0,0,-1); ///@todo: hacked so only works for reflections across xy plane
- #ifdef ALLOW_TEMPORARIES
- Vector3 rotAxis=Vector3::Cross_Product(WorldUp,pView); //get axis of rotation.
- rotAxis.Normalize();
- #else
- Vector3 rotAxis;
- Vector3::Normalized_Cross_Product(WorldUp, pView, &rotAxis);
- #endif
- Real angle=Vector3::Dot_Product(WorldUp,pView);
- angle = acos(angle);
- Matrix3D tm(1);
- tm.Set(rotAxis,angle);
- tm.Adjust_Translation(Vector3(SKYBODY_X,SKYBODY_Y,SKYBODY_HEIGHT));
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
- VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
- DX8Wrapper::Set_Material(vmat);
- REF_PTR_RELEASE(vmat);
- ShaderClass m_shader2=ShaderClass::_PresetAlphaShader;
- m_shader2.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
- m_shader2.Set_Depth_Compare(ShaderClass::PASS_ALWAYS); //no need to check against z-buffer, sky always rendered first.
- m_shader2.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); //sky is always behind everything so no need to update z-buffer
- DX8Wrapper::Set_Shader(m_shader2);
- // DX8Wrapper::Set_Shader(ShaderClass::/*_PresetAdditiveShader*//*_PresetOpaqueShader*/_PresetAlphaShader);
- // DX8Wrapper::Set_Texture(0,setting->skyBodyTexture);
- DX8Wrapper::Set_Texture(0,m_alphaClippingTexture);
- //draw an infinite sky plane
- DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,4);
- {
- DynamicVBAccessClass::WriteLockClass lock(&vb_access);
- VertexFormatXYZNDUV2* verts=lock.Get_Formatted_Vertex_Array();
- if(verts)
- {
- verts[0].x=-SKYBODY_SIZE;
- verts[0].y=SKYBODY_SIZE;
- verts[0].z=0;
- verts[0].u2=0;
- verts[0].v2=1;
- verts[0].diffuse=0xffffffff;
-
- verts[1].x=SKYBODY_SIZE;
- verts[1].y=SKYBODY_SIZE;
- verts[1].z=0;
- verts[1].u2=1;
- verts[1].v2=1;
- verts[1].diffuse=0xffffffff;
-
- verts[2].x=SKYBODY_SIZE;
- verts[2].y=-SKYBODY_SIZE;
- verts[2].z=0;
- verts[2].u2=1;
- verts[2].v2=0;
- verts[2].diffuse=0xffffffff;
-
- verts[3].x=-SKYBODY_SIZE;
- verts[3].y=-SKYBODY_SIZE;
- verts[3].z=0;
- verts[3].u2=0;
- verts[3].v2=0;
- verts[3].diffuse=0xffffffff;
- }
- }
- DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
- DX8Wrapper::Set_Vertex_Buffer(vb_access);
- DX8Wrapper::Draw_Triangles( 0,2, 0, 4); //draw a quad, 2 triangles, 4 verts
- }
- //Defines for procedural water animation.
- #define WATER_FREQ (2.0*3.2831/4.0) //2pi (full cycle) cover 4 units
- #define WATER_AMP (1.0f)
- #define WATER_OFFSET (0.1f)
- //-------------------------------------------------------------------------------------------------
- /** Renders (draws) the water surface mesh geometry.
- * This is a work-in-progress! Do not use this code! */
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::renderWaterMesh(void)
- {
- if (!m_doWaterGrid)
- return; //the water grid is disabled.
- //According to Nvidia there's a D3D bug that happens if you don't start with a
- //new dynamic VB each frame - so we force a DISCARD by overflowing the counter.
- m_vertexBufferD3DOffset = 0xffff;
- Setting *setting=&m_settings[m_tod];
- WaterMeshData *pData;
- Int mx=m_gridCellsX+1;
- Int my=m_gridCellsY+1;
- Int i,j;
-
- Real cellSizeX=m_gridCellSize;
- Real cellSizeY=m_gridCellSize;
- // Real uScale2=5.0f*setting->waterRepeatCount/(128.0f)*cellSizeX/10.0f;
- // Real vScale2=5.0f*setting->waterRepeatCount/(128.0f)*cellSizeY/10.0f;
- //Old waterRepeatCount settings in INI were based on 128x128 water grid of cellsize=10
- //Scale values to correct size.
- Real uScale=setting->waterRepeatCount/(128.0f)*cellSizeX/10.0f*0.2f;
- Real vScale=setting->waterRepeatCount/(128.0f)*cellSizeY/10.0f*0.2f;
- Vector3 nx(cellSizeX*2.0f,0,0);
- Vector3 ny(0,cellSizeY*2.0f,0);
- Vector3 C;
- #ifdef DO_WATER_SIMULATION //Debug code used to create a dummy water animation
- //
- // Mark: If you re-enable this water simulation, you might want to consider moving
- // this code to the update() method of the water render object (Colin)
- //
- static Real PhasePerFrameX=0.1f;
- static Real PhasePerFrameY=0.1f;
- //update the mesh heights for this frame (update buffer is 2 samples wider/taller due to border)
- for (j=0,pData=m_meshData; j<(my+2); j++)
- {
- for (i=0; i<(mx+2); i++)
- {
- //*pData = WATER_AMP * sin(WATER_FREQ*(0.7f*i + 0.7f*j) - PhasePerFrame);
- 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));
- // *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));
- pData++;
- }
- }
- PhasePerFrameX -= 0.08f;
- PhasePerFrameY -= 0.1f;
- #endif
- MaterMeshVertexFormat *vb;
- if (m_vertexBufferD3DOffset < m_numVertices)
- { //we have room in current VB, append new verts
- if(m_vertexBufferD3D->Lock(m_vertexBufferD3DOffset*sizeof(MaterMeshVertexFormat),mx*my*sizeof(MaterMeshVertexFormat),(unsigned char**)&vb,D3DLOCK_NOOVERWRITE) != D3D_OK)
- return;
- }
- else
- { //ran out of room in last VB, request a substitute VB.
- if(m_vertexBufferD3D->Lock(0,mx*my*sizeof(MaterMeshVertexFormat),(unsigned char**)&vb,D3DLOCK_DISCARD) != D3D_OK)
- return;
- m_vertexBufferD3DOffset=0; //reset start of page to first vertex
- }
- Int diffuse;
- diffuse = setting->waterDiffuse&0x00ffffff;
- Int alpha = (setting->waterDiffuse & 0xff000000)>>24;
- // Reduce alpha for wave mesh
- alpha -= 0x20;
- diffuse |= alpha<<24;
- //I pulled some of these constants out of the loops for speed:
- Real uvCosScale=0.02*cos(3*m_riverVOrigin);
- Real sinOffset=25*m_riverVOrigin;
- Real originScale=m_riverVOrigin/vScale;
- Real bumpSizeDiv=cellSizeY/BUMP_SIZE;
- Real bumpSizeDiv2=0.3f*cellSizeY/BUMP_SIZE;
- //Data has a 1 vertex padding all around it so we don't need to special-case edges. Improves performance
- for (j=0,pData=m_meshData+mx+2+1; j<my; j++,pData+=2) //skip 2 horizontal border samples after each row
- {
- Real y=(float)j*cellSizeY;
- Real v1Offset=m_riverVOrigin+(float)j*vScale + uvCosScale*WWMath::Fast_Sin(sinOffset+y*PI/(8*MAP_XY_FACTOR));
- Real v2Offset=((float)j+originScale)*bumpSizeDiv + (float)j*bumpSizeDiv2;
- for (i=0; i<mx; i++)
- {
- //compute normal by looking at 4 vertex neightbors
- #ifdef USE_MESH_NORMALS
- nx.Z=(pData+1)->height - (pData-1)->height;
- ny.Z=(pData+mx+2)->height - (pData-mx-2)->height;
- // nx.Z=*(pData+1)-*(pData-1);
- // ny.Z=*(pData+mx+2)-*(pData-mx-2);
- Vector3::Cross_Product(nx,ny,&C);
- C.Normalize();
- vb->nx = C.X;
- vb->ny = C.X;
- vb->nz = C.X;
- #endif
- Real x = (float)i*cellSizeX;
- vb->x= x;
- vb->y= y;
- vb->z= pData->height;//WATER_OFFSET+WATER_AMP*(sin((float)i*WATER_FREQ+PhasePerFrame)+cos((float)j*WATER_FREQ+PhasePerFrame));
- vb->diffuse = diffuse;
- #ifdef SCROLL_UV
- // vb->diffuse=0x80ffffff;
- vb->u1=(float)i*uScale;
- vb->v1=v1Offset;
- //old slow version
- //vb->v1=m_riverVOrigin+(float)j*vScale + 0.02*cos(3*m_riverVOrigin)*sin(25*m_riverVOrigin+y*PI/(8*MAP_XY_FACTOR));
- // vb->u2=m_initialGridU2+(float)i*uScale2;
- // vb->v2=m_initialGridV2+(float)j*vScale2;
- #else
- vb->u1=(float)i*uScale;
- vb->v1=(float)j*vScale;
- #endif
- vb->u2=(float)(i)*cellSizeX/BUMP_SIZE;
- vb->v2=v2Offset;
- //old slow code
- //vb->v2=(float)(j+m_riverVOrigin/vScale )*cellSizeY/BUMP_SIZE+ 0.3f*(float)j*cellSizeY/BUMP_SIZE;
- vb++;
- pData++;
- }
- }
- m_vertexBufferD3D->Unlock();
- Matrix3D tm(Transform);
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
- DX8Wrapper::Set_Material(m_meshVertexMaterialClass);
- ShaderClass::CullModeType oldCullMode=m_shaderClass.Get_Cull_Mode();
- ShaderClass::DepthMaskType oldDepthMask=m_shaderClass.Get_Depth_Mask();
- m_shaderClass.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE); //disable writing to z-buffer to prevent particle clipping.
- m_shaderClass.Set_Cull_Mode(ShaderClass::CULL_MODE_ENABLE); //water should be visible from both sides
- DX8Wrapper::Set_Shader(m_shaderClass);
- #if 1
- setupFlatWaterShader();
- #else
- //DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
- DX8Wrapper::Set_Texture(0,setting->waterTexture);
- DX8Wrapper::Set_Texture(1,setting->waterTexture);
- DX8Wrapper::Set_Light(0,*m_meshLight);
- DX8Wrapper::Set_Light(1,NULL);
- DX8Wrapper::Set_Light(2,NULL);
- DX8Wrapper::Set_Light(3,NULL);
- /*
- DX8Wrapper::Set_DX8_Render_State(D3DRS_AMBIENT,0); //turn off scene ambient
- DX8Wrapper::Set_DX8_Render_State(D3DRS_SPECULARENABLE,TRUE);
- DX8Wrapper::Set_DX8_Render_State(D3DRS_LOCALVIEWER,TRUE);
- */
- DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
- #endif
- // m_pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_ALWAYS); //used to display grid under map.
- m_pDev->SetIndices(m_indexBufferD3D,m_vertexBufferD3DOffset);
- m_pDev->SetStreamSource(0,m_vertexBufferD3D,sizeof(MaterMeshVertexFormat));
- m_pDev->SetVertexShader(WATER_MESH_FVF);
- if (TheTerrainRenderObject->getShroud() && !m_trapezoidWaterPixelShader)
- { //we have a shroud to apply and can't do it inside the pixel shader.
- //so do it in stage1
- W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
- W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 1);
- //modulate with shroud texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //stage 1 texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); //previous stage texture
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
- DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
- //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
- //write to the zbuffer. Change to LESSEQUAL.
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
- m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,mx*my,0,m_numIndices-2);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
- W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
- }
- else
- m_pDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,mx*my,0,m_numIndices-2);
-
- Debug_Statistics::Record_DX8_Polys_And_Vertices(m_numIndices-2,mx*my,ShaderClass::_PresetOpaqueShader);
- // m_pDev->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
- if (m_trapezoidWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(NULL);
- m_vertexBufferD3DOffset += mx*my; //advance past vertices already in buffer
- DX8Wrapper::Set_Texture(0,NULL);
- DX8Wrapper::Set_Texture(1,NULL);
- ShaderClass::Invalidate();
- m_shaderClass.Set_Cull_Mode(oldCullMode); //water should be visible from both sides
- // restore shader to old mask
- m_shaderClass.Set_Depth_Mask(oldDepthMask);
- //W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
- }
- inline void WaterRenderObjClass::setGridVertexHeight(Int x, Int y, Real value)
- {
- DEBUG_ASSERTCRASH( x < (m_gridCellsX+1) && y < (m_gridCellsY+1), ("Invalid Water Mesh Coordinates\n") );
- if (m_meshData)
- {
- m_meshData[(y+1)*(m_gridCellsX+1+2)+x+1].height = value;
- }
- }
- void WaterRenderObjClass::setGridHeightClamps(Real minz, Real maxz)
- {
- m_minGridHeight = minz;
- m_maxGridHeight = maxz;
- }
- void WaterRenderObjClass::addVelocity( Real worldX, Real worldY,
- Real zVelocity, Real preferredHeight )
- {
- if( m_doWaterGrid)
- {
- Real gx,gy;
- Real minX,maxX,minY,maxY;
- Int x,y;
- WaterMeshData *meshPoint;
- m_disableRiver = true;
- //check if center falls within grid bounds
- if (worldToGridSpace(worldX, worldY, gx, gy))
- {
-
- //find extents of influence
- minX = floorf(gx - m_gridChangeMaxRange);
- if (minX < 0 )
- minX = 0; //clamp extent to fall within box
- maxX = ceilf(gx + m_gridChangeMaxRange);
- if (maxX > m_gridCellsX)
- maxX = m_gridCellsX; //clamp extent to fall within box
- minY = floorf(gy - m_gridChangeMaxRange);
- if (minY < 0 )
- minY = 0; //clamp extent to fall within box
- maxY = ceilf(gy + m_gridChangeMaxRange);
- if (maxY > m_gridCellsY)
- maxY = m_gridCellsY; //clamp extent to fall within box
- for (y=minY; y<=maxY; y++)
- {
- for (x=minX; x<=maxX; x++)
- {
- // get the mesh point that we're concerned with
- meshPoint = &m_meshData[ (y + 1) * (m_gridCellsX + 1 + 2) + x + 1 ];
- // we now have a new preferred height
- meshPoint->preferredHeight = preferredHeight;
- //
- // set the velocity of this point based on the distance from the center of the
- // "core" point for this call
- //
- meshPoint->velocity = meshPoint->velocity + zVelocity;
- // this point is now "in motion"
- BitSet( meshPoint->status, WaterRenderObjClass::IN_MOTION );
- }
- }
- //
- // the mesh data is now dirty, we need to pass through the velocity field
- // during an update phase to update the positions
- //
- m_meshInMotion = TRUE;
- }
- } // end if, water type is 3
- }
- void WaterRenderObjClass::changeGridHeight(Real wx, Real wy, Real delta)
- {
- Real gx,gy;
- Real *oldData;
- Real newData;
- Real distance;
- Real minX,maxX,minY,maxY;
- Int x,y;
-
- //check if center falls within grid bounds
- if (worldToGridSpace(wx, wy, gx, gy))
- { //find extents of influence
- minX = floorf(gx - m_gridChangeMaxRange);
- if (minX < 0 )
- minX = 0; //clamp extent to fall within box
- maxX = ceilf(gx + m_gridChangeMaxRange);
- if (maxX > m_gridCellsX)
- maxX = m_gridCellsX; //clamp extent to fall within box
- minY = floorf(gy - m_gridChangeMaxRange);
- if (minY < 0 )
- minY = 0; //clamp extent to fall within box
- maxY = ceilf(gy + m_gridChangeMaxRange);
- if (maxY > m_gridCellsY)
- maxY = m_gridCellsY; //clamp extent to fall within box
- for (y=minY; y<=maxY; y++)
- {
- for (x=minX; x<=maxX; x++)
- { oldData = &m_meshData[(y+1)*(m_gridCellsX+1+2)+x+1].height;
- distance = (gx - (Real)x)*(gx - (Real)x) + (gy - (Real)y)*(gy - (Real)y);
- distance = sqrt(distance);
- newData = *oldData + 1.0f/(m_gridChangeAtt0+m_gridChangeAtt1*distance+distance*distance*m_gridChangeAtt2)*delta;
- //Clamp to min/max values
- if (newData < m_minGridHeight)
- newData = m_minGridHeight;
- if (newData > m_maxGridHeight)
- newData = m_maxGridHeight;
- *oldData = newData;
- }
- }
- }
- }
- void WaterRenderObjClass::setGridChangeAttenuationFactors(Real a, Real b, Real c, Real range)
- {
- m_gridChangeAtt0 = a;
- m_gridChangeAtt1 = b;
- m_gridChangeAtt2 = c;
- m_gridChangeMaxRange = range/m_gridCellSize; //convert range to grid space
- }
- void WaterRenderObjClass::setGridTransform(Real angle, Real x, Real y, Real z)
- {
- m_gridDirectionX = Vector2(1.0f,0.0f);
- m_gridOrigin.X = x;
- m_gridOrigin.Y = y;
- Matrix3D xform(1);
- xform.Rotate_Z(angle);
- m_gridDirectionX.X = xform.Get_X_Vector().X;
- m_gridDirectionX.Y = xform.Get_X_Vector().Y;
- m_gridDirectionY.X = xform.Get_Y_Vector().X;
- m_gridDirectionY.Y = xform.Get_Y_Vector().Y;
- xform.Set_Translation(Vector3(x,y,z));
- Set_Transform(xform);
- }
- void WaterRenderObjClass::setGridTransform(const Matrix3D *transform )
- {
- if( transform )
- Set_Transform( *transform );
- }
- void WaterRenderObjClass::getGridTransform(Matrix3D *transform )
- {
- if( transform )
- *transform = Get_Transform();
- }
- void WaterRenderObjClass::setGridResolution(Real gridCellsX, Real gridCellsY, Real cellSize)
- {
- m_gridCellSize=cellSize;
- if (m_gridCellsX != gridCellsX || m_gridCellsY != m_gridCellsY)
- { //resolutoin has changed
- m_gridCellsX=gridCellsX;
- m_gridCellsY=gridCellsY;
- if (m_meshData)
- {
- delete [] m_meshData;//free previously allocated grid and allocate new size
- m_meshData = NULL; // must set to NULL so that we properly re-allocate
- m_meshDataSize = 0;
- Bool enable = m_doWaterGrid;
- enableWaterGrid(true); // allocates buffers.
- m_doWaterGrid = enable;
- }
- }
- }
- void WaterRenderObjClass::getGridResolution( Real *gridCellsX, Real *gridCellsY, Real *cellSize )
- {
- if( gridCellsX )
- *gridCellsX = m_gridCellsX;
- if( gridCellsY )
- *gridCellsY = m_gridCellsY;
- if( cellSize )
- *cellSize = m_gridCellSize;
- }
- static Real wobble(Real baseV, Real offset, Bool wobble)
- {
- if (!wobble) return 0;
- offset = sin(2*PI*baseV - 3*offset);
- return offset/22;
- }
- /**Utility function used to query water heights in a manner that works in both RTS and WB.*/
- Real WaterRenderObjClass::getWaterHeight(Real x, Real y)
- {
- const WaterHandle *waterHandle = NULL;
- Real waterZ = 0.0f;
- ICoord3D iLoc;
- iLoc.x = REAL_TO_INT_FLOOR( x + 0.5f );
- iLoc.y = REAL_TO_INT_FLOOR( y + 0.5f );
- iLoc.z = 0;
- for( PolygonTrigger *pTrig = PolygonTrigger::getFirstPolygonTrigger(); pTrig; pTrig = pTrig->getNext() )
- {
- if( !pTrig->isWaterArea() )
- continue;
- // See if point is in a water area
- if( pTrig->pointInTrigger( iLoc ) )
- {
- if( pTrig->getPoint( 0 )->z >= waterZ )
- {
- waterZ = pTrig->getPoint( 0 )->z;
- waterHandle = pTrig->getWaterHandle();
- } // end if
- } // end if
- } // end for
- if (waterHandle)
- return waterHandle->m_polygon->getPoint( 0 )->z;
- return INVALID_WATER_HEIGHT; //point not underwater
- }
- //-------------------------------------------------------------------------------------------------
- //Draw a many sided river polygon.
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::drawRiverWater(PolygonTrigger *pTrig)
- {
- DX8Wrapper::Invalidate_Cached_Render_States(); ///@todo: Figure out why rivers don't draw without reset of all states.
- Int rectangleCount = pTrig->getNumPoints()/2;
- rectangleCount--;
- Real bumpFactor = 5;
- static Bool doWobble = true;
- if (m_disableRiver) return;
- m_drawingRiver = true;
- //allocate 2 triangles per side with 3 indices per triangle
- DynamicIBAccessClass ib_access(BUFFER_TYPE_DYNAMIC_DX8,(rectangleCount+1)*2*3);
- {
- DynamicIBAccessClass::WriteLockClass lockib(&ib_access);
- UnsignedShort *curIb = lockib.Get_Index_Array();
- for (Int i=0; i<rectangleCount; i++)
- {
- //triangle 1
- curIb[0] = i*2;
- curIb[1] = i*2+1;
- curIb[2] = i*2+3;
- //triangle 2
- curIb[3] = i*2;
- curIb[4] = i*2+3;
- curIb[5] = i*2+2;
- curIb += 6; //skip the 6 indices we just added.
- }
- }
- Real shadeR, shadeG, shadeB;
- shadeR = TheGlobalData->m_terrainAmbient[0].red;
- shadeG = TheGlobalData->m_terrainAmbient[0].green;
- shadeB = TheGlobalData->m_terrainAmbient[0].blue;
- //Add in diffuse lighting from each terrain light
- for (Int lightIndex=0; lightIndex < TheGlobalData->m_numGlobalLights; lightIndex++)
- {
- if (-TheGlobalData->m_terrainLightPos[lightIndex].z > 0)
- { shadeR += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].red;
- shadeG += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].green;
- shadeB += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].blue;
- }
- }
- //Get water material colors
- Real waterShadeR = (m_settings[m_tod].waterDiffuse & 0xff) / 255.0f;
- Real waterShadeG = ((m_settings[m_tod].waterDiffuse >> 8) & 0xff) / 255.0f;
- Real waterShadeB = ((m_settings[m_tod].waterDiffuse >> 16) & 0xff) / 255.0f;
- shadeR=shadeR*waterShadeR*255.0f;
- shadeG=shadeG*waterShadeG*255.0f;
- shadeB=shadeB*waterShadeB*255.0f;
- Int diffuse=REAL_TO_INT(shadeB) | (REAL_TO_INT(shadeG) << 8) | (REAL_TO_INT(shadeR) << 16);
- //Keep diffuse from lighting calculations but substitute custom alpha
- diffuse |= m_settings[m_tod].waterDiffuse & 0xff000000; //copy alpha/opacity from ini setting
- Int innerNdx = pTrig->getRiverStart();
- Int outerNdx = innerNdx+1;
- Real endLen=0;
- Real totalLen=0;
- Int i;
- for (i=0; i<pTrig->getNumPoints()-1; i++) {
- ICoord3D innerPt = *pTrig->getPoint(i);
- ICoord3D outerPt = *pTrig->getPoint(i+1);
- Real dx = innerPt.x-outerPt.x;
- Real dy = innerPt.y-outerPt.y;
- Real curLen = sqrt(dx*dx+dy*dy);
- totalLen += curLen;
- if ( i==innerNdx) {
- endLen = curLen;
- }
- }
- bumpFactor = endLen/BUMP_SIZE;
- Real lengthOfRiver = (totalLen/2)-endLen;
- Real repeatCount = lengthOfRiver / (endLen);
- Real vScale=(Real)repeatCount/(Real)rectangleCount;
- #define HEIGHT_TO_USE (0.5f)
- if (innerNdx >= pTrig->getNumPoints()-1) return;
- //allocate 2 vertices per side
- DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,(rectangleCount+1)*2);
- {
- DynamicVBAccessClass::WriteLockClass lock(&vb_access);
- VertexFormatXYZNDUV2* vb=lock.Get_Formatted_Vertex_Array();
- Real constA=3*m_riverVOrigin;
- for (i=0; i<(pTrig->getNumPoints()/2); i++)
- {
- Real x,y;
- ICoord3D innerPt = *pTrig->getPoint(outerNdx);
- ICoord3D outerPt = *pTrig->getPoint(innerNdx);
- outerNdx++;
- innerNdx--;
- if (innerNdx<0) {
- innerNdx = pTrig->getNumPoints()-1;
- }
- if (outerNdx >= pTrig->getNumPoints()) {
- outerNdx = 0;
- }
- x=innerPt.x;
- y=innerPt.y;
- vb->x=x;
- vb->y=y;
- vb->z=innerPt.z;
- vb->diffuse= diffuse;
-
- Real wobbleConst=-m_riverVOrigin+vScale*(Real)i + WWMath::Fast_Sin(2*PI*(vScale*(Real)i) - constA)/22.0f;
- //old slower version
- //vb->v1=-m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
- vb->v1=wobbleConst;
- vb->u1=HEIGHT_TO_USE ;
- //old slower version
- //vb->v2 = -m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
- vb->v2=wobbleConst;
- vb->u2 = 1.0f;
- vb->nx = 0;
- vb->ny = 0;
- vb->nz = 1.0f;
- vb++;
- x=outerPt.x;
- y=outerPt.y;
- vb->x=x;
- vb->y=y;
- vb->z=outerPt.z;
- vb->diffuse= diffuse;
- //old slower version
- //vb->v1=-m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
- vb->v1=wobbleConst;
- vb->u1=0;
- //old slower version
- //vb->v2 = -m_riverVOrigin+vScale*(Real)i + wobble(vScale*i, m_riverVOrigin, doWobble);
- vb->v2 =wobbleConst;
- vb->u2 = 0;
- vb->nx = 0;
- vb->ny = 0;
- vb->nz = 1.0f;
- vb++;
- }
- }
- Matrix3D tm(1);
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
- DX8Wrapper::Set_Index_Buffer(ib_access,0);
- DX8Wrapper::Set_Vertex_Buffer(vb_access);
- DX8Wrapper::Set_Texture(0,m_riverTexture); //set to white
- setupJbaWaterShader();
- if (m_riverWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_riverWaterPixelShader);
- DWORD cull;
- DX8Wrapper::_Get_D3D_Device8()->GetRenderState(D3DRS_CULLMODE, &cull);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- if (wireframeForDebug) {
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
- }
- DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
- if (wireframeForDebug) {
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
- }
- if (m_riverWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(NULL);
- //do second pass to apply the shroud on water plane
- if (TheTerrainRenderObject->getShroud())
- {
- W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
- W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
- //write to the zbuffer. Change to LESSEQUAL.
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
- DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
- W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
- }
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, cull);
- }
- void WaterRenderObjClass::setupFlatWaterShader(void)
- {
- //Setup shroud to render in same pass as water
- if (m_trapezoidWaterPixelShader)
- { if (TheTerrainRenderObject->getShroud())
- {
- W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
- //Use stage 3 to apply the shroud
- W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 3);
- m_pDev->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
- m_pDev->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
- //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
- //write to the zbuffer. Change to LESSEQUAL.
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
- }
- else
- { //Assume no shroud, so stage 3 will be "NULL" texture but using actual white because
- //pixel shader on GF4 generates random colors with SetTexture(3,NULL).
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,m_whiteTexture->Peek_DX8_Texture());
- }
- }
- DX8Wrapper::Set_Texture(0,m_riverTexture);
- DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaShader);
- VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
- DX8Wrapper::Set_Material(vmat);
- REF_PTR_RELEASE(vmat);
- m_riverTexture->Set_Mag_Filter(TextureClass::FILTER_TYPE_BEST);
- m_riverTexture->Set_Min_Filter(TextureClass::FILTER_TYPE_BEST);
- m_riverTexture->Set_Mip_Mapping(TextureClass::FILTER_TYPE_BEST);
- DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
- DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_ADD );
- DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, 0);
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, 0);
-
- Bool doSparkles = true;
- if (m_trapezoidWaterPixelShader && doSparkles) {
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(1,m_waterSparklesTexture->Peek_DX8_Texture());
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(2,m_waterNoiseTexture->Peek_DX8_Texture());
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
-
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
- // Two output coordinates are used.
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
- DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
- D3DXMATRIX inv;
- float det;
- Matrix4 curView;
- DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
- D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
- D3DXMATRIX scale;
- D3DXMatrixScaling(&scale, NOISE_REPEAT_FACTOR, NOISE_REPEAT_FACTOR,1);
- D3DXMATRIX destMatrix = inv * scale;
- D3DXMatrixTranslation(&scale, m_riverVOrigin, m_riverVOrigin,0);
- destMatrix = destMatrix*scale;
- DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, *(Matrix4*)&destMatrix);
- }
- m_pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- m_pDev->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- if (m_trapezoidWaterPixelShader){
- DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(0, D3DXVECTOR4(REFLECTION_FACTOR, REFLECTION_FACTOR, REFLECTION_FACTOR, 1.0f), 1);
- DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_trapezoidWaterPixelShader);
- }
- }
- //-------------------------------------------------------------------------------------------------
- //Draw a 4 sided flat water area.
- //-------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::drawTrapezoidWater(Vector3 points[4])
- {
- Vector3 origin(points[0]);
- Vector3 uVec1(points[1]);
- Vector3 vVec1(points[3]);
- Vector3 uVec2(points[2]);
- Vector3 vVec2(points[2]);
- uVec2 -= vVec1;
- vVec2 -= uVec1;
- uVec1 -= origin;
- vVec1 -= origin;
- Int uCount = (uVec1.Length()+uVec2.Length()) / (8*MAP_XY_FACTOR);
- if (uCount<1) uCount = 1;
- Int vCount = (vVec1.Length()+vVec2.Length()) / (8*MAP_XY_FACTOR);
- if (vCount<1) vCount = 1;
- if (uCount>50) uCount = 50;
- if (vCount>50) vCount = 50;
- static Bool doWobble = true;
- Int rectangleCount = uCount*vCount;
- uCount++;
- vCount++;
- Int i, j;
- //allocate 2 triangles per side with 3 indices per triangle
- DynamicIBAccessClass ib_access(BUFFER_TYPE_DYNAMIC_DX8,(rectangleCount+1)*2*3);
- {
- DynamicIBAccessClass::WriteLockClass lockib(&ib_access);
- UnsignedShort *curIb = lockib.Get_Index_Array();
- for (j=0; j<vCount-1; j++)
- for (i=0; i<uCount-1; i++)
- {
- //triangle 1
- curIb[0] = (j)*uCount + i;
- curIb[1] = (j+1)*uCount + i+1;
- curIb[2] = (j+1)*uCount + i;
- //triangle 2
- curIb[3] = (j)*uCount + i;
- curIb[4] = (j)*uCount + i+1;
- curIb[5] = (j+1)*uCount + i+1;
- curIb += 6; //skip the 6 indices we just added.
- }
- }
- Real waterFactor=150;
- Real shadeR, shadeG, shadeB;
- shadeR = TheGlobalData->m_terrainAmbient[0].red;
- shadeG = TheGlobalData->m_terrainAmbient[0].green;
- shadeB = TheGlobalData->m_terrainAmbient[0].blue;
- //Add in diffuse lighting from each terrain light
- for (Int lightIndex=0; lightIndex < TheGlobalData->m_numGlobalLights; lightIndex++)
- {
- if (-TheGlobalData->m_terrainLightPos[lightIndex].z > 0)
- { shadeR += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].red;
- shadeG += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].green;
- shadeB += -TheGlobalData->m_terrainLightPos[lightIndex].z * TheGlobalData->m_terrainDiffuse[lightIndex].blue;
- }
- }
- //Get water material colors
- Real waterShadeR = (m_settings[m_tod].waterDiffuse & 0xff) / 255.0f;
- Real waterShadeG = ((m_settings[m_tod].waterDiffuse >> 8) & 0xff) / 255.0f;
- Real waterShadeB = ((m_settings[m_tod].waterDiffuse >> 16) & 0xff) / 255.0f;
- shadeR=shadeR*waterShadeR*255.0f;
- shadeG=shadeG*waterShadeG*255.0f;
- shadeB=shadeB*waterShadeB*255.0f;
- Int diffuse=REAL_TO_INT(shadeB) | (REAL_TO_INT(shadeG) << 8) | (REAL_TO_INT(shadeR) << 16);
- //Keep diffuse from lighting calculations but substitute custom alpha
- diffuse |= m_settings[m_tod].waterDiffuse & 0xff000000; //copy alpha/opacity from ini setting
- DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,(rectangleCount+1)*2);
- //#define WAVY_WATER
- //#define FEATHER_LAYER_COUNT (3) //LORENZEN
- //#define FEATHER_LAYER_THICKNESS (2.5f)
- //#define FEATHER_WATER
- //#ifdef WAVY_WATER // the NEW WATER a'la LORENZEN
- if ( TheGlobalData->m_featherWater )
- {
- DynamicVBAccessClass::WriteLockClass lock(&vb_access);
- VertexFormatXYZNDUV2* vb=lock.Get_Formatted_Vertex_Array();
- Real phase = 0;
- Real mapCoeff = PI/(4*MAP_XY_FACTOR);
- Real wave = 0;
- Real amplitude = 0.5f;
- //The first (high order) byte is the Alpha value for this patch
- // It needs to be set proportional to the number of feather layers
- // this comes from TheGlobalData->m_featherWater, which is a count of layers
- Int Alpha = 0;
- if ( TheGlobalData->m_featherWater == 5) Alpha = 80;
- if ( TheGlobalData->m_featherWater == 4) Alpha = 110;
- if ( TheGlobalData->m_featherWater == 3) Alpha = 140;
- if ( TheGlobalData->m_featherWater == 2) Alpha = 200;
- if ( TheGlobalData->m_featherWater == 1) Alpha = 255;
- //Keep diffuse from lighting calculations but substitute custom alpha
- Int customDiffuse = (diffuse & 0x00ffffff) | (Alpha<< 24);//(0x80 << 16)|(0x90 << 8)|0xa0;
- for (j=0; j<vCount; j++)
- {
- Real dv = j;
- dv /= (vCount-1);
- for (i=0; i<uCount; i++)
- {
- Real du = i;
- du /= (uCount-1);
- Vector3 vertex = origin;
- vertex += uVec1*du;
- vertex += vVec1*dv;
- vertex += (dv)*(du)*(vVec2-vVec1);
- vb->x=vertex.X;
- vb->y=vertex.Y;
- // common to all the waving effects
- phase = 25 * m_riverVOrigin + vertex.X * mapCoeff;
- wave = (sin(phase) - 1.0f) * amplitude;
- vb->z = (vertex.Z + wave);
- vb->diffuse = customDiffuse;
- vb->u1 = (vertex.X/waterFactor) + 0.02*cos(11*m_riverVOrigin)*wave;
- vb->v1 = (vertex.Y/waterFactor) + 0.02*cos(5*m_riverVOrigin)*wave;
- vb->u2 = vertex.X/BUMP_SIZE;
- vb->v2 = vertex.Y/BUMP_SIZE + 0.3f*vertex.X/BUMP_SIZE;
- vb->nx = 0;
- vb->ny = 0;
- vb->nz = 1.0f;
- vb++;
- }
- }
- }
- //#else // STILL THE OLD FLAT WATER
- else
- {
- DynamicVBAccessClass::WriteLockClass lock(&vb_access);
- VertexFormatXYZNDUV2* vb=lock.Get_Formatted_Vertex_Array();
- //Pulling some constants out of the inner loops to improve performance -MW
- Real constA=0.02*cos(11*m_riverVOrigin);
- Real constB=0.02*cos(5*m_riverVOrigin);
- Real constC=25*m_riverVOrigin;
- Real ooWaterFactor = 1.0f/waterFactor;
- const Real constD=PI/(4*MAP_XY_FACTOR);
- Real constE=1.0f/(Real)(vCount-1);
- Real constF=1.0f/(Real)(uCount-1);
- for (j=0; j<vCount; j++)
- {
- Real dv = (Real)j * constE;
- for (i=0; i<uCount; i++)
- {
- Real du = (Real)i * constF;
- Vector3 vertex = origin;
- vertex += uVec1*du;
- vertex += vVec1*dv;
- vertex += (dv)*(du)*(vVec2-vVec1);
- vb->x=vertex.X;
- vb->y=vertex.Y;
- vb->z=vertex.Z;
- vb->diffuse= diffuse;
- //Old slower version
- //vb->u1=(vertex.X/waterFactor) + 0.02*cos(11*m_riverVOrigin)*sin(25*m_riverVOrigin+vertex.X*PI/(4*MAP_XY_FACTOR));
- //vb->v1=(vertex.Y/waterFactor) + 0.02*cos(5*m_riverVOrigin)*sin(25*m_riverVOrigin+vertex.Y*PI/(4*MAP_XY_FACTOR));
- vb->u1=vertex.X*ooWaterFactor + constA*WWMath::Fast_Sin(constC+vertex.X*constD);
- vb->v1=vertex.Y*ooWaterFactor + constB*WWMath::Fast_Sin(constC+vertex.Y*constD);
- vb->u2 = vertex.X/BUMP_SIZE;
- //Old slower version
- //vb->v2 = vertex.Y/BUMP_SIZE + 0.3f*vertex.X/BUMP_SIZE;
- vb->v2 = (vertex.Y+0.3f*vertex.X)/BUMP_SIZE;
- vb->nx = 0;
- vb->ny = 0;
- vb->nz = 1.0f;
- vb++;
- }
- }
- }
- //#endif // OLD VS NEW WATER
- Matrix3D tm(1);
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
- DX8Wrapper::Set_Index_Buffer(ib_access,0);
- DX8Wrapper::Set_Vertex_Buffer(vb_access);
- setupFlatWaterShader();// lorenzen sez use the alpha shader
- //If video card supports it and it's enabled, feather the water edge using destination alpha
- if (DX8Wrapper::getBackBufferFormat() == WW3D_FORMAT_A8R8G8B8 && TheGlobalData->m_showSoftWaterEdge && TheWaterTransparency->m_transparentWaterDepth !=0)
- { DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA );
- DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA );
- }
- DWORD cull;
- DX8Wrapper::_Get_D3D_Device8()->GetRenderState(D3DRS_CULLMODE, &cull);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- //#ifdef FEATHER_WATER // the NEW WATER a'la LORENZEN
- // int layer = 0;//LORENZEN
- // for (layer = 0; layer < FEATHER_LAYER_COUNT; ++layer)//LORENZEN
- //#endif // FEATHER_WATER
- {
- //#ifdef WAVY_WATER // the NEW WATER a'la LORENZEN
- //increment the depth of the water's surface for every vert in the buffer
- //#ifdef FEATHER_WATER
- // VertexFormatXYZNDUV2 *vertBuf = vertexBufferStart;
- // while (vertBuf < vertexBufferStart + vCount * uCount)
- // {
- // vertBuf->z *= FEATHER_LAYER_THICKNESS;
- // ++vertBuf;
- // }
- //#endif // FEATHER_WATER
- //#endif //WAVY_WATER
- DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);//lorenzen thinks this is where to itereate the soft shoreline effect
- }
- if (false) {
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
- m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , false);
- DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
- m_pDev->SetRenderState(D3DRS_ALPHABLENDENABLE , true);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
- }
- if (m_riverWaterPixelShader) DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(NULL);
- //Restore alpha blend to default values since we may have changed them to feather edges.
- DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
- if (TheTerrainRenderObject->getShroud())
- {
- if (m_trapezoidWaterPixelShader)
- { //shroud was applied in stage3 of main pass so just need to restore state here.
- W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
- DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,NULL); //free possible reference to shroud texture
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
- }
- else
- { //do second pass to apply the shroud on water plane for cards that can't do it in main pass.
- W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
- W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
- //write to the zbuffer. Change to LESSEQUAL.
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
- DX8Wrapper::Draw_Triangles( 0,rectangleCount*2, 0, (rectangleCount+1)*2);
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
- W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
- }
- }
- DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_CULLMODE, cull);
- }
- //-------------------------------------------------------------------------------------------------
- //debug version where moon rotates with the camera (always upright on screen)
- //-------------------------------------------------------------------------------------------------
- #if 0
- void WaterRenderObjClass::renderSkyBody(Matrix3D *mat)
- {
- Vector3 vRight,vUp,V0,V1,V2,V3;
- mat->Get_X_Vector(&vRight);
- mat->Get_Y_Vector(&vUp);
- //calculate offsets from quad center to each of the 4 corners
- // 0-----1
- // | /|
- // | / |
- // |/ |
- // 3-----2
- V0=-vRight+vUp;
- V2=vRight+vUp;
- V2=vRight-vUp;
- V3=-vRight-vUp;
- VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
- DX8Wrapper::Set_Material(vmat);
- REF_PTR_RELEASE(vmat);
- DX8Wrapper::Set_Shader(ShaderClass::/*_PresetAdditiveShader*//*_PresetOpaqueShader*/_PresetAlphaShader);
- // DX8Wrapper::Set_Texture(0,setting->skyBodyTexture);
- DX8Wrapper::Set_Texture(0,m_alphaClippingTexture);
- //draw an infinite sky plane
- DynamicVBAccessClass vb_access(BUFFER_TYPE_DYNAMIC_DX8,4);
- {
- DynamicVBAccessClass::WriteLockClass lock(&vb_access);
- VertexFormatXYZNDUV2* verts=lock.Get_Formatted_Vertex_Array();
- if(verts)
- {
- verts[0].x=SKYBODY_SIZE*V0.X;
- verts[0].y=SKYBODY_SIZE*V0.Y;
- verts[0].z=SKYBODY_SIZE*V0.Z;
- verts[0].u2=0;
- verts[0].v2=1;
- verts[0].diffuse=0xffffffff;
-
- verts[1].x=SKYBODY_SIZE*V1.X;
- verts[1].y=SKYBODY_SIZE*V1.Y;
- verts[1].z=SKYBODY_SIZE*V1.Z;
- verts[1].u2=1;
- verts[1].v2=1;
- verts[1].diffuse=0xffffffff;
-
- verts[2].x=SKYBODY_SIZE*V2.X;
- verts[2].y=SKYBODY_SIZE*V2.Y;
- verts[2].z=SKYBODY_SIZE*V2.Z;
- verts[2].u2=1;
- verts[2].v2=0;
- verts[2].diffuse=0xffffffff;
-
- verts[3].x=SKYBODY_SIZE*V3.X;
- verts[3].y=SKYBODY_SIZE*V3.Y;
- verts[3].z=SKYBODY_SIZE*V3.Z;
- verts[3].u2=0;
- verts[3].v2=0;
- verts[3].diffuse=0xffffffff;
- }
- }
- DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
- DX8Wrapper::Set_Vertex_Buffer(vb_access);
- Matrix3D tm(1);
- //set postion of skybody in world
- // tm.Set_Translation(Vector3(40,0,0));
- DX8Wrapper::Set_Transform(D3DTS_WORLD,tm);
- DX8Wrapper::Draw_Triangles( 0,2, 0, 4); //draw a quad, 2 triangles, 4 verts
- }
- #endif
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::crc( Xfer *xfer )
- {
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // grid cells x
- Int cellsX = m_gridCellsX;
- xfer->xferInt( &cellsX );
- if( cellsX != m_gridCellsX )
- {
- DEBUG_CRASH(( "WaterRenderObjClass::xfer - cells X mismatch\n" ));
- throw SC_INVALID_DATA;
- } // end if
-
- // grid cells Y
- Int cellsY = m_gridCellsY;
- xfer->xferInt( &cellsY );
- if( cellsY != m_gridCellsY )
- {
-
- DEBUG_CRASH(( "WaterRenderObjClass::xfer - cells Y mismatch\n" ));
- throw SC_INVALID_DATA;
- } // end if
- // xfer each of the mesh data points
- for( Int i = 0; i < m_meshDataSize; ++i )
- {
- // height
- xfer->xferReal( &m_meshData[ i ].height );
- // velocity
- xfer->xferReal( &m_meshData[ i ].velocity );
- // status
- xfer->xferUnsignedByte( &m_meshData[ i ].status );
- // preferred height
- xfer->xferUnsignedByte( &m_meshData[ i ].preferredHeight );
- } // end for, i
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void WaterRenderObjClass::loadPostProcess( void )
- {
- } // end loadPostProcess
|