| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************/
- WaterClass Water;
- WaterMtrl *WaterMtrlLast;
- WaterMtrlPtr WaterMtrlNull;
- DEFINE_CACHE(WaterMtrl, WaterMtrls, WaterMtrlPtr, "Water Material");
- /******************************************************************************/
- // WATER PARAMETERS
- /******************************************************************************/
- WaterMtrl::WaterMtrl()
- {
- density =0.3f;
- density_add =0.45f;
- density_underwater =0.02f;
- density_underwater_add=0.6f;
- scale_color =200;
- scale_normal =10;
- scale_bump =100;
- rough =1;
- reflect_tex =0.1f;
- reflect_world =0.18f;
- refract =0.10f;
- refract_reflection =0.06f;
- refract_underwater =0.01f;
- specular =1.5f;
- wave_scale =0.25f;
- fresnel_pow =5.5f;
- fresnel_rough =4;
- fresnel_color .set(0.10f, 0.10f, 0.10f);
- color .set(0.42f, 0.50f, 0.58f);
- color_underwater0.set(0.26f, 0.35f, 0.42f);
- color_underwater1.set(0.10f, 0.20f, 0.30f);
- }
- WaterMtrl& WaterMtrl:: normalMap(C ImagePtr &image) {T. _normal_map=image; return T;}
- WaterMtrl& WaterMtrl::reflectionMap(C ImagePtr &image) {T._reflection_map=image; return T;}
- WaterMtrl& WaterMtrl:: colorMap(C ImagePtr &image)
- {
- T._color_map=image;
- _bump=null;
- if(image && image->is())
- {
- #if DX9
- if(D.validUsage(D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, image->hwType())) // if can use existing format
- {
- #endif
- _bump=image;
- #if DX9
- }else
- if(this==&Water) // check if can convert to supported format (this can be donly only for 'Water')
- {
- IMAGE_TYPE type=IMAGE_NONE;
- if(D.validUsage(D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, IMAGE_L8 ))type=IMAGE_L8 ;else
- if(D.validUsage(D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, IMAGE_A8 ))type=IMAGE_A8 ;else
- if(D.validUsage(D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, IMAGE_F32))type=IMAGE_F32;
- if(type)
- {
- Image temp, *src=image(); if(src->compressed())if(src->copyTry(temp, -1, -1, -1, IMAGE_A8, IMAGE_SOFT, 1))src=&temp;
- if(!src->compressed() && Water._bump_temp.createTry(src->w(), src->h(), 1, type, IMAGE_2D, 1, false))
- if( src->lock(LOCK_READ))
- {
- if(Water._bump_temp.lock(LOCK_WRITE))
- {
- if(Water._bump_temp.hwType()==IMAGE_L8 || Water._bump_temp.hwType()==IMAGE_A8)
- {
- REPD(y, Water._bump_temp.h())
- REPD(x, Water._bump_temp.w())Water._bump_temp.pixB(x, y)=src->color(x, y).a;
- }else
- if(Water._bump_temp.hwType()==IMAGE_F32)
- {
- REPD(y, Water._bump_temp.h())
- REPD(x, Water._bump_temp.w())Water._bump_temp.pixF(x, y)=src->colorF(x, y).w;
- }
- _bump=&Water._bump_temp.unlock().updateMipMaps(FILTER_BEST, false);
- }
- src->unlock();
- }
- }
- }
- #endif
- }
- if(!_bump || _bump==image)Water._bump_temp.del();
- return T;
- }
- WaterMtrl& WaterMtrl::reset()
- {
- T=WaterMtrl();
- return validate();
- }
- WaterMtrl& WaterMtrl::validate()
- {
- if(WaterMtrlLast==this)WaterMtrlLast=null;
- return T;
- }
- void WaterMtrl::set()
- {
- // Col[1], Col[2], Det[0] reserved for 'setImages'
- Sh.h_ImageCol[0]->set( _color_map());
- Sh.h_ImageNrm[0]->set( _normal_map());
- #if DX9
- Sh.h_ImageNrm[1]->set( _bump ());
- #endif
- Sh.h_ImageRfl[0]->set(_reflection_map());
- if(WaterMtrlLast!=this)
- {
- WaterMtrlLast=this;
- #if DX9
- if(_bump)SPSet("WaterBumpDot", (_bump->hwType()==IMAGE_L8 || _bump->hwType()==IMAGE_F32) ? Vec4(1, 0, 0, 0) : Vec4(0, 0, 0, 1));
- #endif
- // TODO: optimize (struct Water)
- SPSet("WaterScaleDif" , scale_color );
- SPSet("WaterScaleNrm" , scale_normal );
- SPSet("WaterScaleBump" , scale_bump );
- SPSet("WaterRfr" , refract );
- SPSet("WaterRgh_2" , rough*0.5f );
- SPSet("WaterRflFake" , reflect_tex );
- SPSet("WaterSpc" , specular );
- SPSet("WaterWave" , wave_scale );
- SPSet("WaterFresnelPow" , fresnel_pow );
- SPSet("WaterFresnelRough", fresnel_rough);
- SPSet("WaterFresnelColor", fresnel_color);
- SPSet("WaterCol" , color );
- SPSet("WaterDns" , Vec2(Mid(density, 0.0f, 1-EPS_GPU), density_add)); // avoid 1 in case "Pow(1-density, ..)" in shader would cause NaN or slow-downs
- if(Renderer._mirror_rt)
- {
- SPSet("WaterRfl" , reflect_world );
- SPSet("WaterRfrRfl", refract_reflection);
- }else
- {
- SPSet("WaterRfl" , 0);
- SPSet("WaterRfrRfl", 0);
- }
- }
- MaterialClear();
- }
- /******************************************************************************/
- Bool WaterMtrl::save(File &f, CChar *path)C
- {
- f.cmpUIntV(0); // version
- f<<density<<density_add<<density_underwater<<density_underwater_add<<scale_color<<scale_normal<<scale_bump<<rough<<reflect_tex<<reflect_world<<refract<<refract_reflection<<refract_underwater<<specular<<wave_scale<<fresnel_pow<<fresnel_rough;
- f<<fresnel_color<<color<<color_underwater0<<color_underwater1;
- f._putStr( _color_map.name(path));
- f._putStr( _normal_map.name(path));
- f._putStr(_reflection_map.name(path));
- return f.ok();
- }
- Bool WaterMtrl::load(File &f, CChar *path)
- {
- switch(f.decUIntV()) // version
- {
- case 0:
- {
- f>>density>>density_add>>density_underwater>>density_underwater_add>>scale_color>>scale_normal>>scale_bump>>rough>>reflect_tex>>reflect_world>>refract>>refract_reflection>>refract_underwater>>specular>>wave_scale>>fresnel_pow>>fresnel_rough;
- f>>fresnel_color>>color>>color_underwater0>>color_underwater1;
- colorMap(ImagePtr().require(f._getStr(), path));
- normalMap(ImagePtr().require(f._getStr(), path));
- reflectionMap(ImagePtr().require(f._getStr(), path));
- if(f.ok())return true;
- }break;
- }
- reset(); return false;
- }
- Bool WaterMtrl::save(C Str &name)C
- {
- File f; if(f.writeTry(name)){if(save(f, _GetPath(name)) && f.flush())return true; f.del(); FDelFile(name);}
- return false;
- }
- Bool WaterMtrl::load(C Str &name)
- {
- File f; if(f.readTry(name))return load(f, _GetPath(name));
- reset(); return false;
- }
- /******************************************************************************/
- // WATER PLANE
- /******************************************************************************/
- WaterClass::WaterClass()
- {
- draw =false;
- reflection_allow =!MOBILE;
- reflection_shadows =false;
- reflection_resolution=2;
- plane.normal.y =1;
- _max_1_light =true;
- _draw_plane_surface =false;
- _use_secondary_rt =false;
- _began =false;
- _swapped_ds =false;
- _reflect_renderer =RT_SIMPLE;
- }
- void WaterClass::del()
- {
- _mshr .del();
- _bump_temp.del();
- }
- void WaterClass::create()
- {
- del();
- // create mesh
- MeshBase mshb; mshb.createPlane(80, 130).scaleMove(Vec(1, -1, 1), Vec(0, 1, 0));
- REPA(mshb.vtx)
- {
- Vec &pos=mshb.vtx.pos(i);
- if( pos.x<=EPS || pos.x>=1-EPS
- || pos.y<=EPS || pos.y>=1-EPS)pos.xy=(pos.xy-0.5f)*6+0.5f;
- }
- _mshr.create(mshb);
- }
- /******************************************************************************/
- WaterClass& WaterClass::reflectionRenderer(RENDER_TYPE type)
- {
- Clamp(type, RENDER_TYPE(0), RENDER_TYPE(RT_NUM-1));
- if(type==RT_DEFERRED && D.deferredUnavailable())return T;
- if(type!=_reflect_renderer)
- {
- _reflect_renderer=type;
- if(type==RT_DEFERRED && D.deferredMSUnavailable())D.samples(1); // disable multi-sampling if we can't support it
- D.setShader(); // needed because shaders are set only for current renderer type
- }
- return T;
- }
- WaterClass& WaterClass::max1Light(Bool on) {/*if(_max_1_light!=on)*/_max_1_light=on; return T;}
- /******************************************************************************/
- void WaterClass::prepare() // this is called at the start
- {
- WaterMtrlLast=null;
- _under_mtrl =null;
- _draw_plane_surface=false;
- // check visibility for water plane
- if(draw)
- {
- Matrix3 matrix; matrix.setUp(plane.normal);
- Flt size=D.viewRange();
- VecD p =PointOnPlane(CamMatrix.pos, plane.pos, plane.normal);
- under(plane, T);
- if(Frustum(Box(size*2, wave_scale, size*2), MatrixM(matrix, p)))
- {
- _draw_plane_surface=true;
- _quad.set(p+size*(matrix.z-matrix.x), p+size*(matrix.x+matrix.z), p+size*(matrix.x-matrix.z), p+size*(-matrix.x-matrix.z));
- }
- }
- // !! it is important to call this as the first thing during rendering, because 'Game.WorldManager.draw' assumes so, if this needs to be changed then rework 'Game.WorldManager.draw' !!
- // test for under-water on all other water elements
- {
- _mode=MODE_UNDERWATER; Renderer.mode(RM_WATER); Renderer._render();
- _mode=MODE_DRAW ;
- }
- // set draw plane surface
- if(_draw_plane_surface)
- {
- if(_under_mtrl && _under_step>=1) // totally under water
- {
- _draw_plane_surface=false;
- }else
- {
- VecD left =FullScreenToPos(Vec2(D.viewRect().min.x, 0), D.viewRange()),
- right=FullScreenToPos(Vec2(D.viewRect().max.x, 0), D.viewRange());
- left =PointOnPlaneRay(left , plane.pos, plane.normal, CamMatrix.y);
- right=PointOnPlaneRay(right, plane.pos, plane.normal, CamMatrix.y);
- Vec2 l2=PosToFullScreen(left ),
- r2=PosToFullScreen(right);
- Rect rect=D.viewRect();
- Flt dot =Dot(CamMatrix.y, plane.normal);
- if(dot>EPS)
- {
- rect.max.y=Max(l2.y, r2.y);
- if(rect.max.y<rect.min.y)_draw_plane_surface=false;else MIN(rect.max.y, D.viewRect().max.y);
- }else
- if(dot<-EPS)
- {
- rect.min.y=Min(l2.y, r2.y);
- if(rect.min.y>rect.max.y)_draw_plane_surface=false;else MAX(rect.min.y, D.viewRect().min.y);
- }
- /*l2.draw(RED);
- r2.draw(RED);
- rect.draw(0x30FFFFFF);*/
- if(_draw_plane_surface)
- {
- // full range is D.viewRect().min.y .. D.viewRect().max.y
- // drawing range is rect .min.y .. rect .max.y
- Flt y_min_frac=LerpR(D.viewRect().min.y, D.viewRect().max.y, rect.min.y),
- y_max_frac=LerpR(D.viewRect().min.y, D.viewRect().max.y, rect.max.y);
- #if 1
- _y_mul_add.x=y_max_frac-y_min_frac;
- _y_mul_add.y=1-y_max_frac;
- #else
- _y_mul_add.x=1;
- _y_mul_add.y=0;
- #endif
- if(reflection_allow && reflect_world>EPS_COL)Renderer.requestMirror(plane, 1, reflection_shadows, reflection_resolution);
- WS.load();
- }
- }
- }
- // test for lake reflections
- if(reflection_allow && reflect_world>EPS_COL && !Renderer._mirror_want)
- if(!(_under_mtrl && _under_step>=1))
- {
- _mode=MODE_REFLECTION; Renderer.mode(RM_WATER); Renderer._render();
- _mode=MODE_DRAW ;
- }
- }
- /******************************************************************************/
- void WaterClass::setEyeViewport()
- {
- Renderer.setEyeViewport();
- if(Renderer._mirror_rt)
- {
- Vec2 scale=1,
- offs =0;
- if(Renderer._stereo)
- {
- scale.x=2;
- if(Renderer._eye)offs.x-=1;
- offs.x-=ProjMatrixEyeOffset[Renderer._eye]*0.5f;
- }
- SPSet("WaterRflMulAdd", Vec4(scale, offs));
- }else
- {
- SPSet("WaterRflMulAdd", Vec4(1, 1, 0, 0));
- }
- }
- /******************************************************************************/
- void WaterClass::begin()
- {
- if(!_began)
- {
- _began=true;
- WS.load();
- Renderer._has_glow=true;
- D.alpha(ALPHA_NONE);
- if(_use_secondary_rt)
- {
- _swapped_ds=false;
- Renderer._water_col.get (ImageRTDesc(Renderer._col->w(), Renderer._col->h(), IMAGERT_RGBA)); // here Alpha is used for Glow
- Renderer._water_nrm.get (ImageRTDesc(Renderer._col->w(), Renderer._col->h(), D.signedNrmRT() ? IMAGERT_RGBA_S : IMAGERT_RGBA)); // here Alpha is used for Specular
- Renderer._water_ds .getDS( Renderer._col->w(), Renderer._col->h(), 1, false);
- if(Renderer.stage)switch(Renderer.stage)
- {
- case RS_WATER_COLOR : Renderer._water_col->clearFull(); break;
- case RS_WATER_NORMAL: Renderer._water_nrm->clearFull(); break;
- }
- // set RT's and depth buffer
- if(Shader *shader=Sh.h_SetDepth) // if we can copy depth buffer from existing solid's, then do it, to prevent drawing water pixels if they're occluded
- {
- #if DX9
- Renderer.set(Renderer._water_col(), Renderer._water_nrm(), null, null, Renderer._water_ds(), true); // DX9 always requires a RT set
- D.colWrite(0, 0);
- D.colWrite(0, 1);
- #else
- Renderer.set(null, Renderer._water_ds(), true);
- #endif
- D.depthLock (true); D.depthFunc(FUNC_ALWAYS); D.stencil(STENCIL_ALWAYS_SET, 0); shader->draw(Renderer._ds_1s);
- D.depthUnlock( ); D.depthFunc(FUNC_LESS ); D.stencil(STENCIL_NONE );
- #if DX9
- D.colWrite(COL_WRITE_RGBA, 0);
- D.colWrite(COL_WRITE_RGBA, 1);
- #else
- //Renderer.set(Renderer._water_col(), Renderer._water_nrm(), null, null, Renderer._water_ds(), true); don't set, instead swap first and set later
- #endif
- _swapped_ds=Renderer.swapDS1S(Renderer._water_ds); // try to swap DS to put existing stencil values into '_water_ds' because we will write water depths onto '_water_ds' and we want to use it later instead of '_ds_1s' so we want all stencil values to be kept
- Renderer.set(Renderer._water_col(), Renderer._water_nrm(), null, null, Renderer._water_ds(), true);
- }else // if we can't copy then just clear it
- {
- Renderer.set(Renderer._water_col(), Renderer._water_nrm(), null, null, Renderer._water_ds(), true);
- D.clearDS();
- }
- }else
- {
- if(Lights.elms() && Lights[0].type==LIGHT_DIR)Lights[0].dir.set();else LightDir(Vec(0,-1,0), VecZero, 0).set();
- // we're going to draw water on top of existing RT, including refraction, so we need to have a color copy of what's underwater (solid) for the refraction, also we want to do softing so we need to backup depth because we can't read and write to depth in the same time
- Renderer._water_col.get(ImageRTDesc(Renderer._col->w(), Renderer._col->h(), GetImageRTType(Renderer._col->type()))); // create RT for the copy
- Renderer._col->copyHw(*Renderer._water_col, false, D.viewRect()); // copy
- if(_shader_soft)
- {
- Renderer._water_ds.get(ImageRTDesc(Renderer._col->w(), Renderer._col->h(), IMAGERT_F32));
- Renderer._ds_1s->copyHw(*Renderer._water_ds, false, D.viewRect());
- }
- setImages(Renderer._water_col(), Renderer._water_ds());
- Renderer.set(Renderer._col(), Renderer._ds(), true);
- }
- SetOneMatrix();
- D.wire (Renderer.wire);
- D.depth (true);
- D.cull (true);
- D.sampler3D ( );
- D.stencil (STENCIL_WATER_SET, STENCIL_REF_WATER);
- SPSet("WaterFlow", Time.time()*3);
- SPSet("WaterOfs" , _offset );
- Rect uv=D.screenToUV(D.viewRect()); // UV
- if(Renderer._mirror_rt)
- {
- uv=Round(uv*Renderer._mirror_rt->size()); // convert to RectI of RT size
- uv.extend(-0.5f)/=Renderer._mirror_rt->size(); // decrease half pixel to avoid tex filtering issues and convert back to UV
- SPSet("WaterPlnPos", Renderer._mirror_plane.pos *CamMatrixInv );
- SPSet("WaterPlnNrm", Renderer._mirror_plane.normal*CamMatrixInv.orn());
- }
- SPSet("WaterClamp", uv);
- setEyeViewport();
- }
- }
- void WaterClass::end()
- {
- if(_began)
- {
- _began=false;
- D.wire (false);
- D.sampler2D();
- D.stencil (STENCIL_NONE);
- if(!_use_secondary_rt)
- {
- endImages();
- Renderer._water_col.clear();
- Renderer._water_ds .clear();
- if(Renderer._ds!=Renderer._ds_1s && Renderer._ds_1s) // if we've drawn to MSAA ds, then we need to setup 1S DS
- {
- Renderer.set(null, Renderer._ds_1s(), true);
- D.alpha(ALPHA_NONE);
- D.depthLock (true); Sh.h_ResolveDepth->draw(Renderer._ds); // here we can keep FUNC_LESS because 1S DS was already set before and we just need to apply water on top
- D.depthUnlock( );
- }
- }
- }
- }
- /******************************************************************************/
- void WaterClass::under(C PlaneM &plane, WaterMtrl &mtrl)
- {
- Flt step=(Dist(CamMatrix.pos, plane)-D.viewFromActual())/-WATER_SMOOTH+1;
- if( step>EPS_COL)
- {
- if(!_under_mtrl || step>_under_step){_under_mtrl=&mtrl; _under_step=step; _under_plane=plane; _under_plane.pos+=_under_plane.normal*(D.viewFromActual()+WATER_SMOOTH);}
- }
- }
- /******************************************************************************/
- void WaterClass::setImages(Image *src, Image *depth)
- {
- Sh.h_ImageCol[1]->set(Renderer._mirror_rt()); Sh.h_ImageCol[1]->_sampler=&SamplerLinearClamp; // reflection
- Sh.h_ImageCol[2]->set( src ); Sh.h_ImageCol[2]->_sampler=&SamplerLinearClamp; // solid underwater
- Sh.h_ImageDet[0]->set( depth ); // solid depth
- }
- void WaterClass::endImages()
- {
- Sh.h_ImageCol[1]->_sampler=null;
- Sh.h_ImageCol[2]->_sampler=null;
- MaterialClear();
- }
- /******************************************************************************/
- Bool WaterClass::ocean()
- {
- #define EPS_WAVE_SCALE 0.001f // 1 mm
- return _bump && wave_scale>EPS_WAVE_SCALE;
- }
- Shader* WaterClass::shader()
- {
- Bool fake_reflect=(_reflection_map!=null);
- return _use_secondary_rt ? (ocean() ? WS.h_Ocean : WS.h_Lake )[fake_reflect]
- : (ocean() ? WS.h_OceanL : WS.h_LakeL)[fake_reflect][_shader_shadow][_shader_soft];
- }
- /******************************************************************************/
- void WaterClass::drawSurfaces()
- {
- // these are used only when '_use_secondary_rt' is disabled
- _shader_shadow=((Lights.elms() && Lights[0].type==LIGHT_DIR && Lights[0].shadow) ? D.shadowMapNumActual() : 0);
- _shader_soft =Renderer.canReadDepth();
- REPS(Renderer._eye, Renderer._eye_num)
- {
- setEyeViewport();
- if(_draw_plane_surface)
- if(Shader *shader=T.shader())
- {
- begin();
- set ();
- if(ocean())
- {
- SPSet("WaterPlnPos" , plane.pos *CamMatrixInv );
- SPSet("WaterPlnNrm" , plane.normal*CamMatrixInv.orn());
- SPSet("WaterYMulAdd", _y_mul_add );
- shader->begin(); _mshr.set().drawFull();
- ShaderEnd();
- }else
- {
- VI.shader(shader);
- VI.cull (true );
- VI.quad (_quad );
- VI.end ( );
- }
- }
- if(!(_under_mtrl && _under_step>=1)) // don't draw any surfaces when totally under water
- {
- Renderer.mode(RM_WATER); Renderer._render();
- }
- }
- end();
- }
- /******************************************************************************/
- WaterClass& WaterClass::update(C Vec2 &vel)
- {
- _offset+=vel*Time.d();
- return T;
- }
- /******************************************************************************/
- // WATER MESH
- /******************************************************************************/
- void WaterMesh::zero()
- {
- depth=0;
- _lake =false;
- _box.zero();
- }
- WaterMesh::WaterMesh() {zero();}
- void WaterMesh::del()
- {
- _mshb.del();
- _mshr.del();
- _material.clear();
- zero();
- }
- void WaterMesh::create(C MeshBase &src, Bool lake, Flt depth, C WaterMtrlPtr &material)
- {
- T._lake =lake;
- T. depth =depth;
- T._material=material;
- _mshb.create(src, VTX_POS|VTX_TEX0|TRI_IND|QUAD_IND).getBox(_box);
- _mshr.create(_mshb); // 'mshb' is kept for testing 'under'
- WS.load();
- }
- /******************************************************************************/
- Bool WaterMesh::under(C Vec &pos, Flt *depth)C
- {
- if(pos.x>=_box.min.x && pos.x<=_box.max.x
- && pos.z>=_box.min.z && pos.z<=_box.max.z
- && pos.y<=_box.max.y && pos.y>=_box.min.y-T.depth)
- {
- Bool flat=(_box.h()<=0.01f);
- // per face precision
- Vec2 pos2=pos.xz();
- C Vec *p =_mshb.vtx.pos();
- REPA(_mshb.tri)
- {
- C VecI &ind=_mshb.tri.ind(i);
- Tri2 tri(p[ind.x].xz(), p[ind.y].xz(), p[ind.z].xz());
- if(Cuts(pos2, tri))
- {
- if(flat)
- {
- if(depth)*depth=_box.max.y-pos.y;
- return true;
- }else
- {
- Vec blend=TriBlend(pos2, tri);
- Flt water=p[ind.x].y*blend.x + p[ind.y].y*blend.y + p[ind.z].y*blend.z,
- d =water-pos.y;
- if( d>=0 && d<T.depth)
- {
- if(depth)*depth=d;
- return true;
- }
- return false;
- }
- }
- }
- REPA(_mshb.quad)
- {
- C VecI4 &ind=_mshb.quad.ind(i);
- Quad2 quad(p[ind.x].xz(), p[ind.y].xz(), p[ind.z].xz(), p[ind.w].xz());
- if(Cuts(pos2, quad))
- {
- if(flat)
- {
- if(depth)*depth=_box.max.y-pos.y;
- return true;
- }else
- {
- Vec blend=TriBlend(pos2, quad.tri013());
- Flt water=p[ind.x].y*blend.x + p[ind.y].y*blend.y + p[ind.w].y*blend.z,
- d =water-pos.y;
- if( d>=0 && d<T.depth)
- {
- if(depth)*depth=d;
- return true;
- }
- return false;
- }
- }
- }
- }
- return false;
- }
- /******************************************************************************/
- Shader* WaterMesh::shader()C
- {
- if(WaterMtrl *mtrl=getMaterial())
- {
- Bool fake_reflect=(mtrl->_reflection_map!=null);
- return Water._use_secondary_rt ? (_lake ? WS.h_Lake : WS.h_River )[fake_reflect]
- : (_lake ? WS.h_LakeL : WS.h_RiverL)[fake_reflect][Water._shader_shadow][Water._shader_soft];
- }
- return null;
- }
- /******************************************************************************/
- void WaterMesh::draw()C
- {
- if(WaterMtrl *mtrl=getMaterial())switch(Water._mode)
- {
- case WaterClass::MODE_DRAW:
- {
- if(Frustum(_box) && _mshr.is())
- if(Shader *shader=T.shader())
- {
- Water .begin();
- mtrl ->set ();
- shader->begin(); _mshr.set().drawFull();
- ShaderEnd();
- }
- }break;
- case WaterClass::MODE_REFLECTION:
- {
- if(_box.h()<=0.01f /*&& mtrl->reflect>EPS_COL*/) // for reflections accept only flat waters, 'reflect' is taken globally
- if(CamMatrix.pos.y>=_box.min.y) // if camera is above surface
- if(Frustum(_box) && _mshr.is())
- Renderer.requestMirror(PlaneM(VecD(0, _box.max.y, 0), Vec(0, 1, 0)), 0, Water.reflection_shadows, Water.reflection_resolution);
- }break;
- case WaterClass::MODE_UNDERWATER:
- {
- if(_mshb.vtxs())
- {
- Flt depth, eps=D.viewFromActual()+WATER_SMOOTH;
- VecD test=CamMatrix.pos; test.y-=eps;
- if(under(test, &depth))
- {
- test.y+=depth;
- Water.under(PlaneM(test, Vec(0, 1, 0)), *mtrl);
- }
- }
- }break;
- }
- }
- /******************************************************************************/
- Bool WaterMesh::save(File &f, CChar *path)C
- {
- f.cmpUIntV(0); // version
- f<<_lake<<depth<<_box;
- if(_mshb.save(f))
- if(_mshr.save(f))
- {
- f._putStr(_material.name(path));
- return f.ok();
- }
- return false;
- }
- Bool WaterMesh::load(File &f, CChar *path)
- {
- switch(f.decUIntV()) // version
- {
- case 0:
- {
- f>>_lake>>depth>>_box;
- if(_mshb.load(f))
- if(_mshr.load(f))
- {
- _material.require(f._getStr(), path);
- if(f.ok())
- {
- WS.load();
- return true;
- }
- }
- }break;
- }
- del(); return false;
- }
- /******************************************************************************/
- // WATER DROPS
- /******************************************************************************
- struct WaterDrops
- {
- Int num ; // number of water drops
- Vec *pos , // position
- *nrm , // normal (1st random direction)
- *tan ; // tangent (2nd random direction)
- Flt *time , // time offset
- *blend ; // bone blend value
- VecB4 *matrix; // bone matrix index
- Image *image ; // drop texture
- // manage
- WaterDrops& del ( ); // delete
- WaterDrops& create(Image &image,Int num ); // create with 'num' drops
- WaterDrops& create(Image &image,Int num,Shape *shape,Int shapes); // create from shapes
- WaterDrops& create(Image &image,Int num,Ragdoll &ragdoll ); // create from ragdoll
- // operations
- void setSkin(Skeleton &skeleton); // recalculate bone skinning values according to 'skeleton'
- // draw
- void draw( ); // render with active matrix
- void draw(Matrix &matrix ); // render with 'matrix' matrix
- void draw(AnimatedSkeleton &anim_skel); // render with 'anim_skel' matrixes
- ~WaterDrops() {del ( );}
- WaterDrops() {Zero(T);}
- NO_COPY_CONSTRUCTOR(WaterDrops);
- };
- /******************************************************************************
- WaterDrops& WaterDrops::del()
- {
- Free(pos);
- Free(nrm);
- Free(tan);
- Free(time);
- Free(blend);
- Free(matrix);
- Zero(T); return T;
- }
- WaterDrops& WaterDrops::create(Image &image,Int num)
- {
- del();
- T.image=ℑ
- T.num = num ;
- Alloc(pos ,num);
- Alloc(nrm ,num);
- Alloc(tan ,num);
- Alloc(time,num);
- return T;
- }
- WaterDrops& WaterDrops::create(Image &image,Int num,Shape *shape,Int shapes)
- {
- create(image,num);
- Box box;
- Bool box_set=false;
- REP(shapes)
- {
- Box b;
- Shape &s=shape[i];
- if(s.type==SHAPE_BALL)
- {
- Ball &ball=s.ball;
- b.set(ball.pos-ball.r,ball.pos+ball.r);
- }else
- if(s.type==SHAPE_CAPSULE)
- {
- Capsule &capsule=s.capsule;
- Vec up =capsule.up*(capsule.h*0.5f-capsule.r);
- b.from(capsule.pos-up,capsule.pos+up).extend(capsule.r);
- }else continue;
- if(!box_set){box_set=true; box=b;}else box|=b;
- }
- REP(num)
- {
- pos [i].zero();
- nrm [i]=Random (Ball(1),false)*Random.f(1/1.2f,1.2f)*0.008f;
- tan [i]=Random (Ball(1),false)*Random.f(1/1.2f,1.2f)*0.008f;
- time[i]=Random.f(10);
- Vec &p=pos[i];
- REPD(a,256)
- {
- p=Random(box);
- Bool cut=false;
- REP(shapes)
- {
- Shape &s=shape[i];
- if(s.type==SHAPE_BALL && Cuts(p,s.ball )){cut=true; break;}else
- if(s.type==SHAPE_CAPSULE && Cuts(p,s.capsule)){cut=true; break;}
- }
- if(cut)break;
- }
- }
- return T;
- }
- WaterDrops& WaterDrops::create(Image &image,Int num,Ragdoll &ragdoll)
- {
- return create(image,num,ragdoll.shape,ragdoll.bones);
- }
- /******************************************************************************
- void WaterDrops::setSkin(Skeleton &skeleton)
- {
- if(!blend )Alloc(blend ,num);
- if(!matrix)Alloc(matrix,num);
- REP(num)skeleton.getSkin(pos[i],blend[i],matrix[i]);
- }
- /******************************************************************************
- void WaterDrops::draw()
- {
- VI.image (image);
- VI.technique(blend ? Sh.h_RndrWaterdS : Sh.h_RndrWaterd);
- REP(num)
- {
- Flt t1=Sin(Time.time()*1.5f+time[i]),
- t2=Sin(Time.time()*1.7f+time[i]);
- Vec p=pos[i]+t1*nrm[i]+t2*tan[i];
- if(blend)VI.image(WHITE,0.020f,p,blend[i],matrix[i]);
- else VI.image(WHITE,0.020f,p);
- }
- VI.end();
- }
- void WaterDrops::draw(Matrix &matrix)
- {
- SetOneMatrix(matrix);
- draw();
- }
- void WaterDrops::draw(AnimatedSkeleton &anim_skel)
- {
- anim_skel.setMatrix();
- draw();
- }
- /******************************************************************************/
- }
- /******************************************************************************/
|