Torque3D Documentation / _generateds / waterObject.cpp

waterObject.cpp

Engine/source/environment/waterObject.cpp

More...

Public Functions

ConsoleDocClass(WaterObject , "@brief Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> representing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> body of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">water.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> is abstract and may not be created. It defines functionality " "shared by its derived <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> exposes many fields <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> controlling it visual <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">quality.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> surface rendering has the following general <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">features:\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Waves represented by vertex undulation and user <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">paramaters.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Ripples represented by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> normal map and user <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameters.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Refraction of underwater <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Dynamic planar reflection or static cubemap <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reflection.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Paramable water fog and color <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">shift.\n\n</a>" "It will, however , look significantly different depending on the LightingManager " "that is active. With Basic Lighting, we do not have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> deferred texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "lookup per-pixel depth and therefore cannot use our rendering techniques that depend on <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "In particular, the following field groups are not used under Basic <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting:\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Underwater Fogging \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Misc \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Distortion \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- And foam related fields under the %<a href="/coding/class/classwaterobject/">WaterObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> also defines several fields <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> gameplay use and objects " "that support <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">buoyancy.\n\n</a>" " @ingroup Water" )
GFXImplementVertexFormat(GFXWaterVertex )

Detailed Description

Public Functions

ConsoleDocClass(WaterObject , "@brief Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> representing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> body of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">water.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> is abstract and may not be created. It defines functionality " "shared by its derived <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> exposes many fields <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> controlling it visual <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">quality.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> surface rendering has the following general <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">features:\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Waves represented by vertex undulation and user <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">paramaters.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Ripples represented by <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> normal map and user <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameters.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Refraction of underwater <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Dynamic planar reflection or static cubemap <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reflection.\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Paramable water fog and color <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">shift.\n\n</a>" "It will, however , look significantly different depending on the LightingManager " "that is active. With Basic Lighting, we do not have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> deferred texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "lookup per-pixel depth and therefore cannot use our rendering techniques that depend on <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "In particular, the following field groups are not used under Basic <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting:\n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Underwater Fogging \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Misc \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- Distortion \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "\<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1aded116371789db1fd63c90ef00c95a3d">t</a>- And foam related fields under the %<a href="/coding/class/classwaterobject/">WaterObject</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group.\n\n</a>" "%<a href="/coding/class/classwaterobject/">WaterObject</a> also defines several fields <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> gameplay use and objects " "that support <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">buoyancy.\n\n</a>" " @ingroup Water" )

GFXImplementVertexFormat(GFXWaterVertex )

IMPLEMENT_CONOBJECT(WaterObject )

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