waterObject.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "environment/waterObject.h"
  24. #include "console/consoleTypes.h"
  25. #include "materials/materialParameters.h"
  26. #include "materials/baseMatInstance.h"
  27. #include "materials/materialManager.h"
  28. #include "materials/customMaterialDefinition.h"
  29. #include "materials/sceneData.h"
  30. #include "core/stream/bitStream.h"
  31. #include "scene/reflectionManager.h"
  32. #include "scene/sceneRenderState.h"
  33. #include "lighting/lightInfo.h"
  34. #include "math/mathIO.h"
  35. #include "postFx/postEffect.h"
  36. #include "T3D/gameBase/gameConnection.h"
  37. #include "T3D/shapeBase.h"
  38. #include "gfx/gfxOcclusionQuery.h"
  39. #include "gfx/gfxTextureManager.h"
  40. #include "gfx/sim/cubemapData.h"
  41. #include "math/util/matrixSet.h"
  42. #include "sfx/sfxAmbience.h"
  43. #include "T3D/sfx/sfx3DWorld.h"
  44. #include "sfx/sfxTypes.h"
  45. GFXImplementVertexFormat( GFXWaterVertex )
  46. {
  47. addElement( "POSITION", GFXDeclType_Float3 );
  48. addElement( "NORMAL", GFXDeclType_Float3 );
  49. addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
  50. addElement( "TEXCOORD", GFXDeclType_Float4, 1 );
  51. }
  52. void WaterMatParams::clear()
  53. {
  54. mRippleMatSC = NULL;
  55. mRippleDirSC = NULL;
  56. mRippleTexScaleSC = NULL;
  57. mRippleSpeedSC = NULL;
  58. mRippleMagnitudeSC = NULL;
  59. mFoamDirSC = NULL;
  60. mFoamTexScaleSC = NULL;
  61. mFoamSpeedSC = NULL;
  62. mFoamOpacitySC = NULL;
  63. mWaveDirSC = NULL;
  64. mWaveDataSC = NULL;
  65. mReflectTexSizeSC = NULL;
  66. mBaseColorSC = NULL;
  67. mMiscParamsSC = NULL;
  68. mReflectParamsSC = NULL;
  69. mReflectNormalSC = NULL;
  70. mHorizonPositionSC = NULL;
  71. mFogParamsSC = NULL;
  72. mMoreFogParamsSC = NULL;
  73. mFarPlaneDistSC = NULL;
  74. mWetnessParamsSC = NULL;
  75. mDistortionParamsSC = NULL;
  76. mUndulateMaxDistSC = NULL;
  77. mAmbientColorSC = NULL;
  78. mLightDirSC = NULL;
  79. mFoamParamsSC = NULL;
  80. mGridElementSizeSC = NULL;
  81. mElapsedTimeSC = NULL;
  82. mFoamSamplerSC = NULL;
  83. mRippleSamplerSC = NULL;
  84. mCubemapSamplerSC = NULL;
  85. mSpecularParamsSC = NULL;
  86. mDepthGradMaxSC = NULL;
  87. mReflectivitySC = NULL;
  88. mDepthGradSamplerSC = NULL;
  89. }
  90. void WaterMatParams::init( BaseMatInstance* matInst )
  91. {
  92. clear();
  93. mRippleMatSC = matInst->getMaterialParameterHandle( "$rippleMat" );
  94. mRippleDirSC = matInst->getMaterialParameterHandle( "$rippleDir" );
  95. mRippleTexScaleSC = matInst->getMaterialParameterHandle( "$rippleTexScale" );
  96. mRippleSpeedSC = matInst->getMaterialParameterHandle( "$rippleSpeed" );
  97. mRippleMagnitudeSC = matInst->getMaterialParameterHandle( "$rippleMagnitude" );
  98. mFoamDirSC = matInst->getMaterialParameterHandle( "$foamDir" );
  99. mFoamTexScaleSC = matInst->getMaterialParameterHandle( "$foamTexScale" );
  100. mFoamSpeedSC = matInst->getMaterialParameterHandle( "$foamSpeed" );
  101. mFoamOpacitySC = matInst->getMaterialParameterHandle( "$foamOpacity" );
  102. mWaveDirSC = matInst->getMaterialParameterHandle( "$waveDir" );
  103. mWaveDataSC = matInst->getMaterialParameterHandle( "$waveData" );
  104. mReflectTexSizeSC = matInst->getMaterialParameterHandle( "$reflectTexSize" );
  105. mBaseColorSC = matInst->getMaterialParameterHandle( "$baseColor" );
  106. mMiscParamsSC = matInst->getMaterialParameterHandle( "$miscParams" );
  107. mReflectParamsSC = matInst->getMaterialParameterHandle( "$reflectParams" );
  108. mReflectNormalSC = matInst->getMaterialParameterHandle( "$reflectNormal" );
  109. mHorizonPositionSC = matInst->getMaterialParameterHandle( "$horizonPos" );
  110. mFogParamsSC = matInst->getMaterialParameterHandle( "$fogParams" );
  111. mMoreFogParamsSC = matInst->getMaterialParameterHandle( "$moreFogParams" );
  112. mFarPlaneDistSC = matInst->getMaterialParameterHandle( "$farPlaneDist" );
  113. mWetnessParamsSC = matInst->getMaterialParameterHandle( "$wetnessParams" );
  114. mDistortionParamsSC = matInst->getMaterialParameterHandle( "$distortionParams" );
  115. mUndulateMaxDistSC = matInst->getMaterialParameterHandle( "$undulateMaxDist" );
  116. mAmbientColorSC = matInst->getMaterialParameterHandle( "$ambientColor" );
  117. mLightDirSC = matInst->getMaterialParameterHandle( "$inLightVec" );
  118. mFoamParamsSC = matInst->getMaterialParameterHandle( "$foamParams" );
  119. mGridElementSizeSC = matInst->getMaterialParameterHandle( "$gridElementSize" );
  120. mElapsedTimeSC = matInst->getMaterialParameterHandle( "$elapsedTime" );
  121. mModelMatSC = matInst->getMaterialParameterHandle( "$modelMat" );
  122. mFoamSamplerSC = matInst->getMaterialParameterHandle( "$foamMap" );
  123. mRippleSamplerSC = matInst->getMaterialParameterHandle( "$bumpMap" );
  124. mCubemapSamplerSC = matInst->getMaterialParameterHandle( "$skyMap" );
  125. mSpecularParamsSC = matInst->getMaterialParameterHandle( "$specularParams" );
  126. mDepthGradMaxSC = matInst->getMaterialParameterHandle( "$depthGradMax" );
  127. mReflectivitySC = matInst->getMaterialParameterHandle( "$reflectivity" );
  128. mDepthGradSamplerSC = matInst->getMaterialParameterHandle( "$depthGradMap" );
  129. }
  130. bool WaterObject::smWireframe = false;
  131. bool WaterObject::smEnableTrueReflections = true;
  132. //-------------------------------------------------------------------------
  133. // WaterObject Class
  134. //-------------------------------------------------------------------------
  135. IMPLEMENT_CONOBJECT( WaterObject );
  136. ConsoleDocClass( WaterObject,
  137. "@brief Abstract base class for representing a body of water.\n\n"
  138. "%WaterObject is abstract and may not be created. It defines functionality "
  139. "shared by its derived classes.\n\n"
  140. "%WaterObject exposes many fields for controlling it visual quality.\n\n"
  141. "%WaterObject surface rendering has the following general features:\n"
  142. "\t- Waves represented by vertex undulation and user paramaters.\n"
  143. "\t- Ripples represented by a normal map and user parameters.\n"
  144. "\t- Refraction of underwater objects.\n"
  145. "\t- Dynamic planar reflection or static cubemap reflection.\n"
  146. "\t- Paramable water fog and color shift.\n\n"
  147. "It will, however, look significantly different depending on the LightingManager "
  148. "that is active. With Basic Lighting, we do not have a deferred texture to "
  149. "lookup per-pixel depth and therefore cannot use our rendering techniques that depend on it.\n\n"
  150. "In particular, the following field groups are not used under Basic Lighting:\n"
  151. "\t- Underwater Fogging \n"
  152. "\t- Misc \n"
  153. "\t- Distortion \n"
  154. "\t- And foam related fields under the %WaterObject group.\n\n"
  155. "%WaterObject also defines several fields for gameplay use and objects "
  156. "that support buoyancy.\n\n"
  157. "@ingroup Water"
  158. );
  159. WaterObject::WaterObject()
  160. : mViscosity( 1.0f ),
  161. mDensity( 1.0f ),
  162. mLiquidType( "Water" ),
  163. mFresnelBias( 0.3f ),
  164. mFresnelPower( 6.0f ),
  165. mReflectNormalUp( true ),
  166. mReflectivity( 0.5f ),
  167. mDistortStartDist( 0.1f ),
  168. mDistortEndDist( 20.0f ),
  169. mDistortFullDepth( 3.5f ),
  170. mOverallFoamOpacity( 1.0f ),
  171. mFoamMaxDepth( 2.0f ),
  172. mFoamAmbientLerp( 0.5f ),
  173. mFoamRippleInfluence( 0.05f ),
  174. mClarity( 0.5f ),
  175. mUnderwaterColor(9, 6, 5, 240),
  176. mUndulateMaxDist(50.0f),
  177. mMiscParamW( 0.0f ),
  178. mUnderwaterPostFx( NULL ),
  179. mOverallRippleMagnitude( 0.1f ),
  180. mOverallWaveMagnitude( 1.0f ),
  181. mBasicLighting( false ),
  182. mSpecularPower( 48.0f ),
  183. mSoundAmbience( NULL ),
  184. mCubemap( NULL ),
  185. mSpecularColor( 1.0f, 1.0f, 1.0f, 1.0f ),
  186. mEmissive( false ),
  187. mFullReflect(true),
  188. mDepthGradientMax( 50.0f )
  189. {
  190. mTypeMask = WaterObjectType;
  191. for( U32 i=0; i < MAX_WAVES; i++ )
  192. {
  193. mRippleDir[i].set( 0.0f, 0.0f );
  194. mRippleSpeed[i] = 0.0f;
  195. mRippleTexScale[i].set( 0.0f, 0.0f );
  196. mWaveDir[i].set( 0.0f, 0.0f );
  197. mWaveSpeed[i] = 0.0f;
  198. mWaveMagnitude[i] = 0.0f;
  199. }
  200. for ( U32 i = 0; i < MAX_FOAM; i++ )
  201. {
  202. mFoamDir[i].set( 0.0f, 0.0f );
  203. mFoamSpeed[i] = 0.0f;
  204. mFoamTexScale[i].set( 0.0f, 0.0f );
  205. mFoamOpacity[i] = 0.0f;
  206. }
  207. mFoamDir[0].set( 1, 0 );
  208. mFoamDir[1].set( 0, 1 );
  209. mFoamTexScale[0].set( 1, 1 );
  210. mFoamTexScale[1].set( 3, 3 );
  211. mRippleMagnitude[0] = 1.0f;
  212. mRippleMagnitude[1] = 1.0f;
  213. mRippleMagnitude[2] = 0.3f;
  214. mWaterFogData.density = 0.1f;
  215. mWaterFogData.densityOffset = 1.0f;
  216. mWaterFogData.wetDepth = 1.5f;
  217. mWaterFogData.wetDarkening = 0.2f;
  218. mWaterFogData.color = ColorI::BLUE;
  219. mSurfMatName[WaterMat] = "WaterMat";
  220. mSurfMatName[UnderWaterMat] = "UnderWaterMat";
  221. mSurfMatName[BasicWaterMat] = "WaterBasicMat";
  222. mSurfMatName[BasicUnderWaterMat] = "UnderWaterBasicMat";
  223. dMemset( mMatInstances, 0, sizeof(mMatInstances) );
  224. dMemset(mMatParamHandles, 0, sizeof(mMatParamHandles));
  225. mUnderwater = false;
  226. mWaterPos.set( 0,0,0 );
  227. mWaterPlane.set( mWaterPos, Point3F(0,0,1) );
  228. mGenerateVB = true;
  229. mMatrixSet = reinterpret_cast<MatrixSet *>(dMalloc_aligned(sizeof(MatrixSet), 16));
  230. constructInPlace(mMatrixSet);
  231. INIT_ASSET(RippleTex);
  232. INIT_ASSET(FoamTex);
  233. INIT_ASSET(DepthGradientTex);
  234. mCubemapName = StringTable->EmptyString();
  235. }
  236. WaterObject::~WaterObject()
  237. {
  238. dFree_aligned(mMatrixSet);
  239. }
  240. void WaterObject::initPersistFields()
  241. {
  242. addGroup( "WaterObject" );
  243. addProtectedField( "density", TypeF32, Offset( mDensity, WaterObject ), &WaterObject::_checkDensity, &defaultProtectedGetFn, "Affects buoyancy of an object, thus affecting the Z velocity of a player (jumping, falling, etc.");
  244. addField( "viscosity", TypeF32, Offset( mViscosity, WaterObject ), "Affects drag force applied to an object submerged in this container." );
  245. addField( "liquidType", TypeRealString, Offset( mLiquidType, WaterObject ), "Liquid type of WaterBlock, such as water, ocean, lava"
  246. " Currently only Water is defined and used.");
  247. addField( "baseColor", TypeColorI, Offset( mWaterFogData.color, WaterObject ), "Changes color of water fog." );
  248. addField( "fresnelBias", TypeF32, Offset( mFresnelBias, WaterObject ), "Extent of fresnel affecting reflection fogging." );
  249. addField( "fresnelPower", TypeF32, Offset( mFresnelPower, WaterObject ), "Measures intensity of affect on reflection based on fogging." );
  250. addField( "specularPower", TypeF32, Offset( mSpecularPower, WaterObject ), "Power used for specularity on the water surface ( sun only )." );
  251. addField( "specularColor", TypeColorF, Offset( mSpecularColor, WaterObject ), "Color used for specularity on the water surface ( sun only )." );
  252. addField( "emissive", TypeBool, Offset( mEmissive, WaterObject ), "When true the water colors don't react to changes to environment lighting." );
  253. addArray( "Waves (vertex undulation)", MAX_WAVES );
  254. addField( "waveDir", TypePoint2F, Offset( mWaveDir, WaterObject ), MAX_WAVES, "Direction waves flow toward shores." );
  255. addField( "waveSpeed", TypeF32, Offset( mWaveSpeed, WaterObject ), MAX_WAVES, "Speed of water undulation." );
  256. addField( "waveMagnitude", TypeF32, Offset( mWaveMagnitude, WaterObject ), MAX_WAVES, "Height of water undulation." );
  257. endArray( "Waves (vertex undulation)" );
  258. addField( "overallWaveMagnitude", TypeF32, Offset( mOverallWaveMagnitude, WaterObject ), "Master variable affecting entire body"
  259. " of water's undulation" );
  260. INITPERSISTFIELD_IMAGEASSET(RippleTex, WaterObject, "Normal map used to simulate small surface ripples");
  261. addArray( "Ripples (texture animation)", MAX_WAVES );
  262. addField( "rippleDir", TypePoint2F, Offset( mRippleDir, WaterObject ), MAX_WAVES, "Modifies the direction of ripples on the surface." );
  263. addField( "rippleSpeed", TypeF32, Offset( mRippleSpeed, WaterObject ), MAX_WAVES, "Modifies speed of surface ripples.");
  264. addField( "rippleTexScale", TypePoint2F, Offset( mRippleTexScale, WaterObject ), MAX_WAVES, "Intensifies the affect of the normal map "
  265. "applied to the surface.");
  266. addField( "rippleMagnitude", TypeF32, Offset( mRippleMagnitude, WaterObject ), MAX_WAVES, "Intensifies the vertext modification of the surface." );
  267. endArray( "Ripples (texture animation)" );
  268. addField( "overallRippleMagnitude", TypeF32, Offset( mOverallRippleMagnitude, WaterObject ), "Master variable affecting entire surface");
  269. INITPERSISTFIELD_IMAGEASSET(FoamTex, WaterObject, "Diffuse texture for foam in shallow water (advanced lighting only)");
  270. addArray( "Foam", MAX_FOAM );
  271. addField( "foamDir", TypePoint2F, Offset( mFoamDir, WaterObject ), MAX_FOAM, "" );
  272. addField( "foamSpeed", TypeF32, Offset( mFoamSpeed, WaterObject ), MAX_FOAM, "");
  273. addField( "foamTexScale", TypePoint2F, Offset( mFoamTexScale, WaterObject ), MAX_FOAM, ""
  274. "applied to the surface.");
  275. addField( "foamOpacity", TypeF32, Offset( mFoamOpacity, WaterObject ), MAX_FOAM, "" );
  276. endArray( "Foam" );
  277. addField( "overallFoamOpacity", TypeF32, Offset( mOverallFoamOpacity, WaterObject ), "" );
  278. addField( "foamMaxDepth", TypeF32, Offset( mFoamMaxDepth, WaterObject ), "" );
  279. addField( "foamAmbientLerp", TypeF32, Offset( mFoamAmbientLerp, WaterObject ), "" );
  280. addField( "foamRippleInfluence", TypeF32, Offset( mFoamRippleInfluence, WaterObject ), "" );
  281. endGroup( "WaterObject" );
  282. addGroup( "Reflect" );
  283. addField( "cubemap", TypeCubemapName, Offset( mCubemapName, WaterObject ), "Cubemap used instead of reflection texture if fullReflect is off." );
  284. addProtectedField( "fullReflect", TypeBool, Offset( mFullReflect, WaterObject ),
  285. &WaterObject::_setFullReflect,
  286. &defaultProtectedGetFn,
  287. "Enables dynamic reflection rendering." );
  288. addField( "reflectivity", TypeF32, Offset( mReflectivity, WaterObject ), "Overall scalar to the reflectivity of the water surface." );
  289. addField( "reflectPriority", TypeF32, Offset( mReflectorDesc.priority, WaterObject ), "Affects the sort order of reflected objects." );
  290. addField( "reflectMaxRateMs", TypeS32, Offset( mReflectorDesc.maxRateMs, WaterObject ), "Affects the sort time of reflected objects." );
  291. //addField( "reflectMaxDist", TypeF32, Offset( mReflectMaxDist, WaterObject ), "vert distance at which only cubemap color is used" );
  292. //addField( "reflectMinDist", TypeF32, Offset( mReflectMinDist, WaterObject ), "vert distance at which only reflection color is used" );
  293. addField( "reflectDetailAdjust", TypeF32, Offset( mReflectorDesc.detailAdjust, WaterObject ), "scale up or down the detail level for objects rendered in a reflection" );
  294. addField( "reflectNormalUp", TypeBool, Offset( mReflectNormalUp, WaterObject ), "always use z up as the reflection normal" );
  295. addField( "useOcclusionQuery", TypeBool, Offset( mReflectorDesc.useOcclusionQuery, WaterObject ), "turn off reflection rendering when occluded (delayed)." );
  296. addField( "reflectTexSize", TypeS32, Offset( mReflectorDesc.texSize, WaterObject ), "The texture size used for reflections (square)" );
  297. endGroup( "Reflect" );
  298. addGroup( "Underwater Fogging" );
  299. addField( "waterFogDensity", TypeF32, Offset( mWaterFogData.density, WaterObject ), "Intensity of underwater fogging." );
  300. addField( "waterFogDensityOffset", TypeF32, Offset( mWaterFogData.densityOffset, WaterObject ), "Delta, or limit, applied to waterFogDensity." );
  301. addField( "wetDepth", TypeF32, Offset( mWaterFogData.wetDepth, WaterObject ), "The depth in world units at which full darkening will be received,"
  302. " giving a wet look to objects underwater." );
  303. addField( "wetDarkening", TypeF32, Offset( mWaterFogData.wetDarkening, WaterObject ), "The refract color intensity scaled at wetDepth." );
  304. endGroup( "Underwater Fogging" );
  305. addGroup( "Misc" );
  306. INITPERSISTFIELD_IMAGEASSET(DepthGradientTex, WaterObject, "1D texture defining the base water color by depth");
  307. addField( "depthGradientMax", TypeF32, Offset( mDepthGradientMax, WaterObject ), "Depth in world units, the max range of the color gradient texture." );
  308. endGroup( "Misc" );
  309. addGroup( "Distortion" );
  310. addField( "distortStartDist", TypeF32, Offset( mDistortStartDist, WaterObject ), "Determines start of distortion effect where water"
  311. " surface intersects the camera near plane.");
  312. addField( "distortEndDist", TypeF32, Offset( mDistortEndDist, WaterObject ), "Max distance that distortion algorithm is performed. "
  313. "The lower, the more distorted the effect.");
  314. addField( "distortFullDepth", TypeF32, Offset( mDistortFullDepth, WaterObject ), "Determines the scaling down of distortion "
  315. "in shallow water.");
  316. endGroup( "Distortion" );
  317. addGroup( "Basic Lighting" );
  318. addField( "clarity", TypeF32, Offset( mClarity, WaterObject ), "Relative opacity or transparency of the water surface." );
  319. addField( "underwaterColor", TypeColorI, Offset( mUnderwaterColor, WaterObject ), "Changes the color shading of objects beneath"
  320. " the water surface.");
  321. endGroup( "Basic Lighting" );
  322. addGroup( "Sound" );
  323. addField( "soundAmbience", TypeSFXAmbienceName, Offset( mSoundAmbience, WaterObject ), "Ambient sound environment when listener is submerged." );
  324. endGroup( "Sound" );
  325. Parent::initPersistFields();
  326. Con::addVariable( "$WaterObject::wireframe", TypeBool, &smWireframe, "If true, will render the wireframe of the WaterObject.\n"
  327. "@ingroup Water\n");
  328. }
  329. void WaterObject::consoleInit()
  330. {
  331. Parent::consoleInit();
  332. Con::addVariable( "$pref::Water::EnableTrueReflections", TypeBool, &WaterObject::smEnableTrueReflections,
  333. "Force all water objects to use static cubemap reflections.\n"
  334. "@ingroup Water");
  335. }
  336. void WaterObject::inspectPostApply()
  337. {
  338. Parent::inspectPostApply();
  339. setMaskBits( UpdateMask | WaveMask | TextureMask | SoundMask );
  340. }
  341. bool WaterObject::processArguments( S32 argc, ConsoleValue *argv )
  342. {
  343. if( typeid( *this ) == typeid( WaterObject ) )
  344. {
  345. Con::errorf( ConsoleLogEntry::Script, "WaterObject is an abstract class, only its child classes may be allocated." );
  346. return false;
  347. }
  348. else
  349. return Parent::processArguments( argc, argv );
  350. }
  351. bool WaterObject::_setFullReflect( void *object, const char *index, const char *data )
  352. {
  353. WaterObject *water = static_cast<WaterObject*>( object );
  354. water->mFullReflect = dAtob( data );
  355. if ( water->isProperlyAdded() && water->isClientObject() )
  356. {
  357. bool isEnabled = water->mPlaneReflector.isEnabled();
  358. bool enable = water->mFullReflect && smEnableTrueReflections;
  359. if ( enable && !isEnabled )
  360. water->mPlaneReflector.registerReflector( water, &water->mReflectorDesc );
  361. else if ( !enable && isEnabled )
  362. water->mPlaneReflector.unregisterReflector();
  363. }
  364. return false;
  365. }
  366. bool WaterObject::_checkDensity( void *object, const char *index, const char *data )
  367. {
  368. //Water densities above 1000 shoot the player high and fast into the air.
  369. //value clamped to prevent errors.
  370. WaterObject *water = static_cast<WaterObject*>( object );
  371. water->mDensity = mClampF(dAtof( data ), 0.0f, 1000.0f);
  372. return false;
  373. }
  374. U32 WaterObject::packUpdate( NetConnection * conn, U32 mask, BitStream *stream )
  375. {
  376. U32 retMask = Parent::packUpdate( conn, mask, stream );
  377. if ( stream->writeFlag( mask & UpdateMask ) )
  378. {
  379. stream->write( mDensity );
  380. stream->write( mViscosity );
  381. stream->write( mLiquidType );
  382. if ( stream->writeFlag( mFullReflect ) )
  383. {
  384. stream->write( mReflectorDesc.priority );
  385. stream->writeInt( mReflectorDesc.maxRateMs, 32 );
  386. //stream->write( mReflectMaxDist );
  387. //stream->write( mReflectMinDist );
  388. stream->write( mReflectorDesc.detailAdjust );
  389. stream->writeFlag( mReflectNormalUp );
  390. stream->writeFlag( mReflectorDesc.useOcclusionQuery );
  391. stream->writeInt( mReflectorDesc.texSize, 32 );
  392. }
  393. stream->write( mReflectivity );
  394. stream->write( mWaterFogData.density );
  395. stream->write( mWaterFogData.densityOffset );
  396. stream->write( mWaterFogData.wetDepth );
  397. stream->write( mWaterFogData.wetDarkening );
  398. stream->write( mDistortStartDist );
  399. stream->write( mDistortEndDist );
  400. stream->write( mDistortFullDepth );
  401. stream->write( mDepthGradientMax );
  402. stream->writeFlag( mEmissive );
  403. stream->write( mFoamMaxDepth );
  404. stream->write( mFoamAmbientLerp );
  405. stream->write( mFoamRippleInfluence );
  406. stream->write( mWaterFogData.color );
  407. stream->write( mFresnelBias );
  408. stream->write( mFresnelPower );
  409. Point4F specularData( mSpecularColor.red, mSpecularColor.green, mSpecularColor.blue, mSpecularPower );
  410. mathWrite( *stream, specularData );
  411. stream->write( mClarity );
  412. stream->write( mUnderwaterColor );
  413. stream->write( mOverallRippleMagnitude );
  414. stream->write( mOverallWaveMagnitude );
  415. stream->write( mOverallFoamOpacity );
  416. }
  417. if ( stream->writeFlag( mask & WaveMask ) )
  418. {
  419. for( U32 i=0; i<MAX_WAVES; i++ )
  420. {
  421. stream->write( mRippleSpeed[i] );
  422. mathWrite( *stream, mRippleDir[i] );
  423. mathWrite( *stream, mRippleTexScale[i] );
  424. stream->write( mRippleMagnitude[i] );
  425. stream->write( mWaveSpeed[i] );
  426. mathWrite( *stream, mWaveDir[i] );
  427. stream->write( mWaveMagnitude[i] );
  428. }
  429. for ( U32 i = 0; i < MAX_FOAM; i++ )
  430. {
  431. stream->write( mFoamSpeed[i] );
  432. mathWrite( *stream, mFoamDir[i] );
  433. mathWrite( *stream, mFoamTexScale[i] );
  434. stream->write( mFoamOpacity[i] );
  435. }
  436. }
  437. if ( stream->writeFlag( mask & MaterialMask ) )
  438. {
  439. for ( U32 i = 0; i < NumMatTypes; i++ )
  440. stream->write( mSurfMatName[i] );
  441. }
  442. if ( stream->writeFlag( mask & TextureMask ) )
  443. {
  444. PACK_ASSET(conn, RippleTex);
  445. PACK_ASSET(conn, DepthGradientTex);
  446. PACK_ASSET(conn, FoamTex);
  447. stream->writeString( mCubemapName );
  448. }
  449. if( stream->writeFlag( mask & SoundMask ) )
  450. sfxWrite( stream, mSoundAmbience );
  451. return retMask;
  452. }
  453. void WaterObject::unpackUpdate( NetConnection * conn, BitStream *stream )
  454. {
  455. Parent::unpackUpdate( conn, stream );
  456. // UpdateMask
  457. if ( stream->readFlag() )
  458. {
  459. stream->read( &mDensity );
  460. stream->read( &mViscosity );
  461. stream->read( &mLiquidType );
  462. if ( stream->readFlag() )
  463. {
  464. mFullReflect = true;
  465. stream->read( &mReflectorDesc.priority );
  466. mReflectorDesc.maxRateMs = stream->readInt( 32 );
  467. //stream->read( &mReflectMaxDist );
  468. //stream->read( &mReflectMinDist );
  469. stream->read( &mReflectorDesc.detailAdjust );
  470. mReflectNormalUp = stream->readFlag();
  471. mReflectorDesc.useOcclusionQuery = stream->readFlag();
  472. mReflectorDesc.texSize = stream->readInt( 32 );
  473. if ( isProperlyAdded() && !mPlaneReflector.isEnabled() && smEnableTrueReflections )
  474. mPlaneReflector.registerReflector( this, &mReflectorDesc );
  475. }
  476. else
  477. {
  478. mFullReflect = false;
  479. if ( isProperlyAdded() && mPlaneReflector.isEnabled() )
  480. mPlaneReflector.unregisterReflector();
  481. }
  482. stream->read( &mReflectivity );
  483. stream->read( &mWaterFogData.density );
  484. stream->read( &mWaterFogData.densityOffset );
  485. stream->read( &mWaterFogData.wetDepth );
  486. stream->read( &mWaterFogData.wetDarkening );
  487. stream->read( &mDistortStartDist );
  488. stream->read( &mDistortEndDist );
  489. stream->read( &mDistortFullDepth );
  490. stream->read( &mDepthGradientMax );
  491. mEmissive = stream->readFlag();
  492. stream->read( &mFoamMaxDepth );
  493. stream->read( &mFoamAmbientLerp );
  494. stream->read( &mFoamRippleInfluence );
  495. stream->read( &mWaterFogData.color );
  496. stream->read( &mFresnelBias );
  497. stream->read( &mFresnelPower );
  498. Point4F specularData;
  499. mathRead( *stream, &specularData );
  500. mSpecularColor.set( specularData.x, specularData.y, specularData.z, 1.0f );
  501. mSpecularPower = specularData.w;
  502. stream->read( &mClarity );
  503. stream->read( &mUnderwaterColor );
  504. stream->read( &mOverallRippleMagnitude );
  505. stream->read( &mOverallWaveMagnitude );
  506. stream->read( &mOverallFoamOpacity );
  507. }
  508. // WaveMask
  509. if ( stream->readFlag() )
  510. {
  511. for( U32 i=0; i<MAX_WAVES; i++ )
  512. {
  513. stream->read( &mRippleSpeed[i] );
  514. mathRead( *stream, &mRippleDir[i] );
  515. mathRead( *stream, &mRippleTexScale[i] );
  516. stream->read( &mRippleMagnitude[i] );
  517. stream->read( &mWaveSpeed[i] );
  518. mathRead( *stream, &mWaveDir[i] );
  519. stream->read( &mWaveMagnitude[i] );
  520. }
  521. for ( U32 i = 0; i < MAX_FOAM; i++ )
  522. {
  523. stream->read( &mFoamSpeed[i] );
  524. mathRead( *stream, &mFoamDir[i] );
  525. mathRead( *stream, &mFoamTexScale[i] );
  526. stream->read( &mFoamOpacity[i] );
  527. }
  528. }
  529. // MaterialMask
  530. if ( stream->readFlag() )
  531. {
  532. for ( U32 i = 0; i < NumMatTypes; i++ )
  533. stream->read( &mSurfMatName[i] );
  534. if ( isProperlyAdded() )
  535. {
  536. // So they will be reloaded on next use.
  537. cleanupMaterials();
  538. }
  539. }
  540. // TextureMask
  541. if ( stream->readFlag() )
  542. {
  543. UNPACK_ASSET(conn, RippleTex);
  544. UNPACK_ASSET(conn, DepthGradientTex);
  545. UNPACK_ASSET(conn, FoamTex);
  546. mCubemapName = stream->readSTString();
  547. if ( isProperlyAdded() )
  548. initTextures();
  549. }
  550. // Sound environment.
  551. if( stream->readFlag() )
  552. {
  553. String errorStr;
  554. if( !sfxReadAndResolve( stream, &mSoundAmbience, errorStr ) )
  555. Con::errorf( "WaterObject::unpackUpdate - pad packet: %s", errorStr.c_str() );
  556. if( isProperlyAdded() && gSFX3DWorld )
  557. gSFX3DWorld->notifyChanged( this );
  558. }
  559. }
  560. void WaterObject::prepRenderImage( SceneRenderState *state )
  561. {
  562. PROFILE_SCOPE(WaterObject_prepRenderImage);
  563. // Are we in Basic Lighting?
  564. mBasicLighting = dStricmp( LIGHTMGR->getId(), "BLM" ) == 0;
  565. mUnderwater = isUnderwater( state->getCameraPosition() );
  566. // We only render during the normal diffuse render pass.
  567. if( !state->isDiffusePass() )
  568. return;
  569. // Setup scene transforms
  570. mMatrixSet->setSceneView(GFX->getWorldMatrix());
  571. mMatrixSet->setSceneProjection(GFX->getProjectionMatrix());
  572. _getWaterPlane( state->getCameraPosition(), mWaterPlane, mWaterPos );
  573. mWaterFogData.plane = mWaterPlane;
  574. mPlaneReflector.refplane = mWaterPlane;
  575. updateUnderwaterEffect( state );
  576. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  577. ri->renderDelegate.bind( this, &WaterObject::renderObject );
  578. ri->type = RenderPassManager::RIT_Water;
  579. ri->defaultKey = 1;
  580. state->getRenderPass()->addInst( ri );
  581. //mRenderUpdateCount++;
  582. }
  583. void WaterObject::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
  584. {
  585. if ( overrideMat )
  586. return;
  587. // TODO: Revive projection z-bias at some point.
  588. // The current issue with this method of fixing z-fighting
  589. // in the WaterBlock is that a constant bias does not alleviate
  590. // the issue at the extreme end of the view range.
  591. //GFXTransformSaver saver;
  592. //MatrixF projMat( true );
  593. //const Frustum &frustum = ri->state->getFrustum();
  594. //
  595. //F32 bias = Con::getFloatVariable( "$waterBlockBias", 0.0002418f );
  596. //MathUtils::getZBiasProjectionMatrix( bias, frustum, &projMat );
  597. //GFX->setProjectionMatrix( projMat );
  598. GFXOcclusionQuery *query = mPlaneReflector.getOcclusionQuery();
  599. bool doQuery = ( !mPlaneReflector.mQueryPending && query && mReflectorDesc.useOcclusionQuery );
  600. // We need to call this for avoid a DX9 or Nvidia bug.
  601. // At some resollutions read from render target,
  602. // break current occlusion query.
  603. REFLECTMGR->getRefractTex();
  604. if ( doQuery )
  605. query->begin();
  606. // Real render call, done by derived class.
  607. innerRender( state );
  608. if ( doQuery )
  609. query->end();
  610. if ( mUnderwater && mBasicLighting )
  611. drawUnderwaterFilter( state );
  612. }
  613. void WaterObject::setCustomTextures( S32 matIdx, U32 pass, const WaterMatParams &paramHandles )
  614. {
  615. // Always use the ripple texture.
  616. GFX->setTexture( paramHandles.mRippleSamplerSC->getSamplerRegister(pass), mRippleTex );
  617. // Only above-water in advanced-lighting uses the foam texture.
  618. if ( matIdx == WaterMat )
  619. {
  620. GFX->setTexture( paramHandles.mFoamSamplerSC->getSamplerRegister(pass), mFoamTex );
  621. GFX->setTexture( paramHandles.mDepthGradSamplerSC->getSamplerRegister(pass), mDepthGradientTex );
  622. }
  623. if ( ( matIdx == WaterMat || matIdx == BasicWaterMat ) && mCubemap )
  624. GFX->setCubeTexture( paramHandles.mCubemapSamplerSC->getSamplerRegister(pass), mCubemap->mCubemap );
  625. else if(paramHandles.mCubemapSamplerSC->getSamplerRegister(pass) != -1 )
  626. GFX->setCubeTexture( paramHandles.mCubemapSamplerSC->getSamplerRegister(pass), NULL );
  627. }
  628. void WaterObject::drawUnderwaterFilter( SceneRenderState *state )
  629. {
  630. // set up camera transforms
  631. MatrixF proj = GFX->getProjectionMatrix();
  632. MatrixF newMat(true);
  633. GFX->setProjectionMatrix( newMat );
  634. GFX->pushWorldMatrix();
  635. GFX->setWorldMatrix( newMat );
  636. // set up render states
  637. GFX->setupGenericShaders();
  638. GFX->setStateBlock( mUnderwaterSB );
  639. /*
  640. const Frustum &frustum = state->getFrustum();
  641. const MatrixF &camXfm = state->getCameraTransform();
  642. F32 nearDist = frustum.getNearDist();
  643. F32 nearLeft = frustum.getNearLeft();
  644. F32 nearRight = frustum.getNearRight();
  645. F32 nearTop = frustum.getNearTop();
  646. F32 nearBottom = frustum.getNearBottom();
  647. Point3F centerPnt;
  648. frustum.getCenterPoint( &centerPnt );
  649. MatrixF.mul
  650. Point3F linePnt, lineDir;
  651. if ( mIntersect( nearPlane, mWaterPlane, &linePnt, &lineDir ) )
  652. {
  653. Point3F leftPnt( centerPnt );
  654. leftPnt.x = near
  655. }
  656. */
  657. Point2I resolution = GFX->getActiveRenderTarget()->getSize();
  658. F32 copyOffsetX = 1.0 / resolution.x;
  659. F32 copyOffsetY = 1.0 / resolution.y;
  660. /*
  661. ClippedPolyList polylist;
  662. polylist.addPoint( Point3F( -1.0f - copyOffsetX, -1.0f + copyOffsetY, 0.0f ) );
  663. polylist.addPoint( Point3F( -1.0f - copyOffsetX, 1.0f + copyOffsetY, 0.0f ) );
  664. polylist.addPoint( Point3F( 1.0f - copyOffsetX, 1.0f + copyOffsetY, 0.0f ) );
  665. polylist.addPoint( Point3F( 1.0f - copyOffsetX, -1.0f + copyOffsetY, 0.0f ) );
  666. polylist.addPlane( clipPlane );
  667. polylist.begin( NULL, 0 );
  668. polylist.vertex( 0 );
  669. polylist.vertex( 1 );
  670. polylist.vertex( 2 );
  671. polylist.vertex( 0 );
  672. polylist.vertex( 2 );
  673. polylist.vertex( 3 );
  674. */
  675. // draw quad
  676. GFXVertexBufferHandle<GFXVertexPCT> verts( GFX, 4, GFXBufferTypeVolatile );
  677. verts.lock();
  678. verts[0].point.set(1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
  679. verts[0].color = mUnderwaterColor;
  680. verts[1].point.set(1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
  681. verts[1].color = mUnderwaterColor;
  682. verts[2].point.set(-1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
  683. verts[2].color = mUnderwaterColor;
  684. verts[3].point.set(-1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
  685. verts[3].color = mUnderwaterColor;
  686. verts.unlock();
  687. GFX->setVertexBuffer( verts );
  688. GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
  689. // reset states / transforms
  690. GFX->setProjectionMatrix( proj );
  691. GFX->popWorldMatrix();
  692. }
  693. bool WaterObject::onAdd()
  694. {
  695. if ( !Parent::onAdd() )
  696. return false;
  697. Con::NotifyDelegate clbk( this, &WaterObject::_onEnableTrueReflections );
  698. Con::addVariableNotify( "$pref::Water::EnableTrueReflections", clbk );
  699. if ( isClientObject() )
  700. {
  701. GFXStateBlockDesc desc;
  702. desc.blendDefined = true;
  703. desc.blendEnable = true;
  704. desc.blendSrc = GFXBlendSrcAlpha;
  705. desc.blendDest = GFXBlendInvSrcAlpha;
  706. desc.zDefined = true;
  707. desc.zEnable = false;
  708. desc.cullDefined = true;
  709. desc.cullMode = GFXCullNone;
  710. mUnderwaterSB = GFX->createStateBlock( desc );
  711. initTextures();
  712. if ( mFullReflect && smEnableTrueReflections )
  713. mPlaneReflector.registerReflector( this, &mReflectorDesc );
  714. }
  715. return true;
  716. }
  717. void WaterObject::onRemove()
  718. {
  719. Con::NotifyDelegate clbk( this, &WaterObject::_onEnableTrueReflections );
  720. Con::removeVariableNotify( "$pref::Water::EnableTrueReflections", clbk );
  721. if ( isClientObject() )
  722. {
  723. mPlaneReflector.unregisterReflector();
  724. cleanupMaterials();
  725. PostEffect *underWaterEffect = getUnderwaterEffect( );
  726. if( underWaterEffect )
  727. underWaterEffect->disable( );
  728. }
  729. Parent::onRemove();
  730. }
  731. void WaterObject::_onEnableTrueReflections()
  732. {
  733. // Same code as _setFullReflect
  734. if ( isProperlyAdded() && isClientObject() )
  735. {
  736. bool isEnabled = mPlaneReflector.isEnabled();
  737. bool enable = mFullReflect && smEnableTrueReflections;
  738. if ( enable && !isEnabled )
  739. mPlaneReflector.registerReflector( this, &mReflectorDesc );
  740. else if ( !enable && isEnabled )
  741. mPlaneReflector.unregisterReflector();
  742. }
  743. }
  744. void WaterObject::setShaderParams( SceneRenderState *state, BaseMatInstance *mat, const WaterMatParams &paramHandles )
  745. {
  746. MaterialParameters* matParams = mat->getMaterialParameters();
  747. matParams->setSafe( paramHandles.mElapsedTimeSC, (F32)Sim::getCurrentTime() / 1000.0f );
  748. // set vertex shader constants
  749. //-----------------------------------
  750. Point2F reflectTexSize( mPlaneReflector.reflectTex.getWidth(), mPlaneReflector.reflectTex.getHeight() );
  751. matParams->setSafe( paramHandles.mReflectTexSizeSC, reflectTexSize );
  752. static AlignedArray<Point2F> mConstArray( MAX_WAVES, sizeof( Point4F ) );
  753. // Ripples...
  754. for ( U32 i = 0; i < MAX_WAVES; i++ )
  755. mConstArray[i].set( -mRippleDir[i].x, -mRippleDir[i].y );
  756. matParams->setSafe( paramHandles.mRippleDirSC, mConstArray );
  757. Point3F rippleSpeed( mRippleSpeed[0], mRippleSpeed[1], mRippleSpeed[2] );
  758. matParams->setSafe( paramHandles.mRippleSpeedSC, rippleSpeed );
  759. Point4F rippleMagnitude( mRippleMagnitude[0],
  760. mRippleMagnitude[1],
  761. mRippleMagnitude[2],
  762. mOverallRippleMagnitude );
  763. matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude );
  764. for ( U32 i = 0; i < MAX_WAVES; i++ )
  765. {
  766. Point2F texScale = mRippleTexScale[i];
  767. if ( texScale.x > 0.0 )
  768. texScale.x = 1.0 / texScale.x;
  769. if ( texScale.y > 0.0 )
  770. texScale.y = 1.0 / texScale.y;
  771. mConstArray[i].set( texScale.x, texScale.y );
  772. }
  773. matParams->setSafe(paramHandles.mRippleTexScaleSC, mConstArray);
  774. static AlignedArray<Point4F> mConstArray4F( 3, sizeof( Point4F ) );
  775. F32 angle, cosine, sine;
  776. for ( U32 i = 0; i < MAX_WAVES; i++ )
  777. {
  778. angle = mAtan2( mRippleDir[i].x, -mRippleDir[i].y );
  779. cosine = mCos( angle );
  780. sine = mSin( angle );
  781. mConstArray4F[i].set( cosine, sine, -sine, cosine );
  782. matParams->setSafe( paramHandles.mRippleMatSC, mConstArray4F );
  783. }
  784. // Waves...
  785. for ( U32 i = 0; i < MAX_WAVES; i++ )
  786. mConstArray[i].set( -mWaveDir[i].x, -mWaveDir[i].y );
  787. matParams->setSafe( paramHandles.mWaveDirSC, mConstArray );
  788. for ( U32 i = 0; i < MAX_WAVES; i++ )
  789. mConstArray[i].set( mWaveSpeed[i], mWaveMagnitude[i] * mOverallWaveMagnitude );
  790. matParams->setSafe( paramHandles.mWaveDataSC, mConstArray );
  791. // Foam...
  792. Point4F foamDir( mFoamDir[0].x, mFoamDir[0].y, mFoamDir[1].x, mFoamDir[1].y );
  793. matParams->setSafe( paramHandles.mFoamDirSC, foamDir );
  794. Point2F foamSpeed( mFoamSpeed[0], mFoamSpeed[1] );
  795. matParams->setSafe( paramHandles.mFoamSpeedSC, foamSpeed );
  796. //Point3F rippleMagnitude( mRippleMagnitude[0] * mOverallRippleMagnitude,
  797. // mRippleMagnitude[1] * mOverallRippleMagnitude,
  798. // mRippleMagnitude[2] * mOverallRippleMagnitude );
  799. //matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude );
  800. Point4F foamTexScale( mFoamTexScale[0].x, mFoamTexScale[0].y, mFoamTexScale[1].x, mFoamTexScale[1].y );
  801. for ( U32 i = 0; i < 4; i++ )
  802. {
  803. if ( foamTexScale[i] > 0.0f )
  804. foamTexScale[i] = 1.0 / foamTexScale[i];
  805. }
  806. matParams->setSafe(paramHandles.mFoamTexScaleSC, foamTexScale);
  807. // Other vert params...
  808. matParams->setSafe( paramHandles.mUndulateMaxDistSC, mUndulateMaxDist );
  809. // set pixel shader constants
  810. //-----------------------------------
  811. Point2F fogParams( mWaterFogData.density, mWaterFogData.densityOffset );
  812. matParams->setSafe(paramHandles.mFogParamsSC, fogParams );
  813. matParams->setSafe(paramHandles.mFarPlaneDistSC, (F32)state->getFarPlane() );
  814. Point2F wetnessParams( mWaterFogData.wetDepth, mWaterFogData.wetDarkening );
  815. matParams->setSafe(paramHandles.mWetnessParamsSC, wetnessParams );
  816. Point3F distortionParams( mDistortStartDist, mDistortEndDist, mDistortFullDepth );
  817. matParams->setSafe(paramHandles.mDistortionParamsSC, distortionParams );
  818. LightInfo *sun = LIGHTMGR->getSpecialLight(LightManager::slSunLightType);
  819. const LinearColorF &sunlight = state->getAmbientLightColor();
  820. Point3F ambientColor = mEmissive ? Point3F::One : sunlight;
  821. matParams->setSafe(paramHandles.mAmbientColorSC, ambientColor );
  822. matParams->setSafe(paramHandles.mLightDirSC, sun->getDirection() );
  823. Point4F foamParams( mOverallFoamOpacity, mFoamMaxDepth, mFoamAmbientLerp, mFoamRippleInfluence );
  824. matParams->setSafe(paramHandles.mFoamParamsSC, foamParams );
  825. Point4F miscParams( mFresnelBias, mFresnelPower, mClarity, mMiscParamW );
  826. matParams->setSafe( paramHandles.mMiscParamsSC, miscParams );
  827. Point4F specularParams( mSpecularColor.red, mSpecularColor.green, mSpecularColor.blue, mSpecularPower );
  828. if ( !mEmissive )
  829. {
  830. const LinearColorF &sunColor = sun->getColor();
  831. F32 brightness = sun->getBrightness();
  832. specularParams.x *= sunColor.red * brightness;
  833. specularParams.y *= sunColor.green * brightness;
  834. specularParams.z *= sunColor.blue * brightness;
  835. }
  836. matParams->setSafe( paramHandles.mSpecularParamsSC, specularParams );
  837. matParams->setSafe( paramHandles.mDepthGradMaxSC, mDepthGradientMax );
  838. matParams->setSafe( paramHandles.mReflectivitySC, mReflectivity );
  839. }
  840. PostEffect* WaterObject::getUnderwaterEffect()
  841. {
  842. if ( mUnderwaterPostFx.isValid() )
  843. return mUnderwaterPostFx;
  844. PostEffect *effect;
  845. if ( Sim::findObject( "UnderwaterFogPostFx", effect ) )
  846. mUnderwaterPostFx = effect;
  847. return mUnderwaterPostFx;
  848. }
  849. void WaterObject::updateUnderwaterEffect( SceneRenderState *state )
  850. {
  851. AssertFatal( isClientObject(), "uWaterObject::updateUnderwaterEffect() called on the server" );
  852. PostEffect *effect = getUnderwaterEffect();
  853. if ( !effect )
  854. return;
  855. // Never use underwater postFx with Basic Lighting, we don't have depth.
  856. if ( mBasicLighting )
  857. {
  858. effect->disable();
  859. return;
  860. }
  861. GameConnection *conn = GameConnection::getConnectionToServer();
  862. if ( !conn )
  863. return;
  864. GameBase *control = conn->getControlObject();
  865. if ( !control )
  866. return;
  867. WaterObject *water = control->getCurrentWaterObject();
  868. if ( water == NULL )
  869. effect->disable();
  870. else if ( water == this )
  871. {
  872. MatrixF mat;
  873. conn->getControlCameraTransform( 0, &mat );
  874. if ( mUnderwater )
  875. {
  876. effect->enable();
  877. effect->setOnThisFrame( true );
  878. mWaterFogData.depthGradMax = mDepthGradientMax;
  879. state->getSceneManager()->setWaterFogData( mWaterFogData );
  880. // Register our depthGradient texture with a name so it can
  881. // be fetched by the effect when it renders.
  882. if ( !mNamedDepthGradTex.isRegistered() )
  883. mNamedDepthGradTex.registerWithName( "waterDepthGradMap" );
  884. mNamedDepthGradTex.setTexture( mDepthGradientTex );
  885. }
  886. else
  887. effect->disable();
  888. }
  889. }
  890. bool WaterObject::initMaterial( S32 idx )
  891. {
  892. // We must return false for any case which it is NOT safe for the caller
  893. // to use the indexed material.
  894. if ( idx < 0 || idx >= NumMatTypes )
  895. return false;
  896. BaseMatInstance *mat = mMatInstances[idx];
  897. WaterMatParams &matParams = mMatParamHandles[idx];
  898. // Is it already initialized?
  899. if ( mat && mat->isValid() )
  900. return true;
  901. // Do we need to allocate anything?
  902. if ( mSurfMatName[idx].isNotEmpty() )
  903. {
  904. if ( mat )
  905. SAFE_DELETE( mat );
  906. CustomMaterial *custMat;
  907. if ( Sim::findObject( mSurfMatName[idx], custMat ) && custMat->mShaderData )
  908. mat = custMat->createMatInstance();
  909. else
  910. mat = MATMGR->createMatInstance( mSurfMatName[idx] );
  911. const GFXVertexFormat *flags = getGFXVertexFormat<GFXVertexPCT>();
  912. if ( mat && mat->init( MATMGR->getDefaultFeatures(), flags ) )
  913. {
  914. mMatInstances[idx] = mat;
  915. matParams.init( mat );
  916. return true;
  917. }
  918. SAFE_DELETE( mat );
  919. }
  920. return false;
  921. }
  922. void WaterObject::initTextures()
  923. {
  924. if ( mNamedDepthGradTex.isRegistered() )
  925. mNamedDepthGradTex.setTexture( mDepthGradientTex );
  926. if ( mCubemapName != StringTable->EmptyString() )
  927. Sim::findObject( mCubemapName, mCubemap );
  928. if ( mCubemap )
  929. mCubemap->createMap();
  930. }
  931. void WaterObject::cleanupMaterials()
  932. {
  933. for (U32 i = 0; i < NumMatTypes; i++)
  934. SAFE_DELETE(mMatInstances[i]);
  935. }
  936. S32 WaterObject::getMaterialIndex( const Point3F &camPos )
  937. {
  938. bool underwater = isUnderwater( camPos );
  939. bool basicLighting = dStricmp( LIGHTMGR->getId(), "BLM" ) == 0;
  940. // set the material
  941. S32 matIdx = -1;
  942. if ( underwater )
  943. {
  944. if ( basicLighting )
  945. matIdx = BasicUnderWaterMat;
  946. else
  947. matIdx = UnderWaterMat;
  948. }
  949. else
  950. {
  951. if ( basicLighting )
  952. matIdx = BasicWaterMat;
  953. else
  954. matIdx = WaterMat;
  955. }
  956. return matIdx;
  957. }