waterObject.cpp
Engine/source/environment/waterObject.cpp
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 ¶mHandles ) 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( ¢erPnt ); 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 ¶mHandles ) 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