2015-12-01 06:49:37 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
# include "environment/VolumetricFog.h"
# include "windowManager/platformWindowMgr.h"
# include "gfx/gfxTransformSaver.h"
# include "renderInstance/renderPassManager.h"
# include "math/mathIO.h"
# include "materials/shaderData.h"
# include "math/util/matrixSet.h"
# include "core/resourceManager.h"
# include "core/stream/bitStream.h"
# include "T3D/gameBase/gameConnection.h"
# include "T3D/shapeBase.h"
# include "ts/tsShapeInstance.h"
# include "console/engineAPI.h"
# include "gui/core/guiCanvas.h"
# include "VolumetricFogRTManager.h"
# include "lighting/lightInfo.h"
# include "lighting/lightManager.h"
# define COLBOX_SCALE Point3F(1.02f, 1.02f, 1.02f)
IMPLEMENT_CO_NETOBJECT_V1 ( VolumetricFog ) ;
ConsoleDocClass ( VolumetricFog ,
" @brief Volumetric Fog Object class. Main class defining the Volumetric \n "
" Fog objects in the scene. Used in conjunction with the VolumetricFogRTManager \n "
" class which is responsible for the required rendertargets. \n \n "
" Methods (exposed to script): \n "
" setFogColorF(color) Changes the overall fog color (color.rgba range 0.0 - 1.0). \n ; "
" setFogColor(color) Changes the overall fog color color.rgba range 0 - 255). \n ; "
" setFogDensity(density) Changes the overall fog density. \n "
" setFogModulation(strength, speed1, speed2) changes the strength \n "
" and the speeds of the 2 animation layers. \n \n "
" Callbacks: \n "
" onEnterFog triggered whenever the controlobject (Player or Camera) enters the Fog. \n "
" (current Fog object and the controlobject are exposed to script. \n "
" onLeaveFog triggered whenever the controlobject (Player or Camera) left the Fog. \n "
" (current Fog object and the controlobject are exposed to script. \n \n "
" @tsexample \n "
" new VolumetricFog() \n "
" { \n "
" shapeName = \" art/environment/FogRCube.dts \" ; \n "
" fogColor = \" 200 200 200 128 \" ; \n "
" fogDensity = \" 0.2 \" ; \n "
" ignoreWater = \" 0 \" ; \n "
" MinSize = \" 250 \" ; \n "
" FadeSize = \" 750 \" ; \n "
" texture = \" art/environment/FogMod_heavy.dds \" ; \n "
" tiles = \" 1.5 \" ; \n "
" modStrength = \" 0.2 \" ; \n "
" PrimSpeed = \" -0.01 0.04 \" ; \n "
" SecSpeed = \" 0.02 -0.02 \" ; \n "
" position = \" 748.644 656.371 65.3506 \" ; \n "
" rotation = \" 0 0 1 20.354 \" ; \n "
" scale = \" 40 30 6 \" ; \n "
" }; \n "
" @endtsexample \n "
) ;
IMPLEMENT_CALLBACK ( VolumetricFog , onEnterFog , void , ( SimObjectId obj ) , ( obj ) ,
" @brief Called when an object enters the volume of the Fog instance. \n \n "
" @param obj the controlobject entering the fog. " ) ;
IMPLEMENT_CALLBACK ( VolumetricFog , onLeaveFog , void , ( SimObjectId obj ) , ( obj ) ,
" @brief Called when an object left the volume of the Fog instance. \n \n "
" @param obj the controlobject leaving the fog. " ) ;
VolumetricFog : : VolumetricFog ( )
{
AssertFatal ( VFRTM ! = NULL , " VolumetricFog Fatal Error: No Manager found " ) ;
if ( ! VFRTM - > IsInitialized ( ) )
VFRTM - > Init ( ) ;
mNetFlags . set ( Ghostable | ScopeAlways ) ;
mTypeMask | = EnvironmentObjectType | StaticObjectType ;
2017-04-11 05:23:14 +00:00
mDeferredTarget = NULL ;
2015-12-01 06:49:37 +00:00
mDepthBufferTarget = NULL ;
mFrontBufferTarget = NULL ;
z_buf = NULL ;
mTexture = NULL ;
mIsVBDirty = false ;
mIsPBDirty = false ;
mFogColor . set ( 200 , 200 , 200 , 255 ) ;
mFogDensity = 0.3f ;
mIgnoreWater = false ;
mReflect = false ;
mCamInFog = false ;
mResizing = false ;
mFogReflStrength = 20.0 ;
mUseGlow = false ;
mGlowStrength = 0.3f ;
mGlowing = 0 ;
mModifLightRays = false ;
mLightRayMod = 1.0f ;
mOldLightRayStrength = 0.1f ;
mShapeLoaded = false ;
mMinDisplaySize = 10.0f ;
mFadeSize = 0.0f ;
mCurDetailLevel = 0 ;
mNumDetailLevels = 0 ;
det_size . clear ( ) ;
mIsTextured = false ;
mStrength = 0.5f ;
mTexTiles = 1.0f ;
mSpeed1 . set ( 0.5f , 0.0f ) ;
mSpeed2 . set ( 0.1f , 0.1f ) ;
2019-12-06 02:42:47 +00:00
2021-10-03 07:56:26 +00:00
INIT_ASSET ( Shape ) ;
INIT_ASSET ( Texture ) ;
2015-12-01 06:49:37 +00:00
}
VolumetricFog : : ~ VolumetricFog ( )
{
2017-05-07 00:57:10 +00:00
if ( ! isClientObject ( ) )
2015-12-01 06:49:37 +00:00
return ;
for ( S32 i = 0 ; i < det_size . size ( ) ; i + + )
{
if ( det_size [ i ] . indices ! = NULL )
delete ( det_size [ i ] . indices ) ;
if ( det_size [ i ] . piArray ! = NULL )
delete ( det_size [ i ] . piArray ) ;
if ( det_size [ i ] . verts ! = NULL )
2017-05-07 00:57:10 +00:00
delete [ ] ( det_size [ i ] . verts ) ;
2015-12-01 06:49:37 +00:00
}
det_size . clear ( ) ;
2017-05-07 00:57:10 +00:00
z_buf = NULL ;
2015-12-01 06:49:37 +00:00
if ( ! mTexture . isNull ( ) )
mTexture . free ( ) ;
}
void VolumetricFog : : initPersistFields ( )
{
2023-01-25 01:30:09 +00:00
Parent : : initPersistFields ( ) ;
2023-01-24 23:12:23 +00:00
addGroup ( " Shapes " ) ;
INITPERSISTFIELD_SHAPEASSET ( Shape , VolumetricFog , " The source shape asset. " ) ;
endGroup ( " Shapes " ) ;
2019-12-06 02:42:47 +00:00
2023-01-24 23:12:23 +00:00
addGroup ( " VolumetricFogData " ) ;
2015-12-01 06:49:37 +00:00
addField ( " FogColor " , TypeColorI , Offset ( mFogColor , VolumetricFog ) ,
" Fog color RGBA (Alpha is ignored) " ) ;
addField ( " FogDensity " , TypeF32 , Offset ( mFogDensity , VolumetricFog ) ,
" Overal fog density value (0 disables the fog). " ) ;
addField ( " IgnoreWater " , TypeBool , Offset ( mIgnoreWater , VolumetricFog ) ,
" Set to true if volumetric fog should continue while submerged. " ) ;
addField ( " MinSize " , TypeF32 , Offset ( mMinDisplaySize , VolumetricFog ) ,
" Min size (in pixels) for fog to be rendered. " ) ;
addField ( " FadeSize " , TypeF32 , Offset ( mFadeSize , VolumetricFog ) ,
" Object size in pixels at which the FX-fading kicks in (0 disables fading). " ) ;
endGroup ( " VolumetricFogData " ) ;
addGroup ( " VolumetricFogModulation " ) ;
2021-07-19 06:07:08 +00:00
INITPERSISTFIELD_IMAGEASSET ( Texture , VolumetricFog , " A texture which contains Fogdensity modulator in the red channel and color with 1-green channel. No texture disables modulation. " ) ;
2015-12-01 06:49:37 +00:00
addField ( " tiles " , TypeF32 , Offset ( mTexTiles , VolumetricFog ) ,
" How many times the texture is mapped to the object. " ) ;
addField ( " modStrength " , TypeF32 , Offset ( mStrength , VolumetricFog ) ,
" Overall strength of the density modulation (0 disables modulation). " ) ;
addField ( " PrimSpeed " , TypePoint2F , Offset ( mSpeed1 , VolumetricFog ) ,
" Overall primary speed of the density modulation (x-speed(u) y-speed(v)) " ) ;
addField ( " SecSpeed " , TypePoint2F , Offset ( mSpeed2 , VolumetricFog ) ,
" Overall secundary speed of the density modulation (x-speed(u) y-speed(v)) " ) ;
endGroup ( " VolumetricFogModulation " ) ;
addGroup ( " Reflections " ) ;
addField ( " Reflectable " , TypeBool , Offset ( mReflect , VolumetricFog ) ,
" Set to true if volumetric fog should be reflected. " ) ;
addField ( " ReflectStrength " , TypeF32 , Offset ( mFogReflStrength , VolumetricFog ) ,
" Strength of the reflections (0 disables the fog). " ) ;
endGroup ( " Reflections " ) ;
addGroup ( " PostFX " ) ;
addField ( " useGlow " , TypeBool , Offset ( mUseGlow , VolumetricFog ) ,
" Set to true if volumetric fog should use glow PostFX. " ) ;
addField ( " glowStrength " , TypeF32 , Offset ( mGlowStrength , VolumetricFog ) ,
" Overall strength of the glow PostFX. " ) ;
addField ( " modLightRay " , TypeBool , Offset ( mModifLightRays , VolumetricFog ) ,
" Set to true if volumetric fog should modify the brightness of the Lightrays. " ) ;
addField ( " lightRayMod " , TypeF32 , Offset ( mLightRayMod , VolumetricFog ) ,
" Modifier for LightRay PostFX when inside Fog. " ) ;
endGroup ( " PostFX " ) ;
}
2019-12-06 02:42:47 +00:00
bool VolumetricFog : : _setShapeAsset ( void * obj , const char * index , const char * data )
{
VolumetricFog * fog = static_cast < VolumetricFog * > ( obj ) ; // ->setFile(FileName(data));
fog - > setShapeAsset ( StringTable - > insert ( data ) ) ;
return false ;
}
2015-12-01 06:49:37 +00:00
void VolumetricFog : : inspectPostApply ( )
{
Parent : : inspectPostApply ( ) ;
mSpeed . set ( mSpeed1 . x , mSpeed1 . y , mSpeed2 . x , mSpeed2 . y ) ;
setMaskBits ( VolumetricFogMask | FogColorMask | FogDensityMask | FogModulationMask | FogPostFXMask | FogShapeMask ) ;
}
bool VolumetricFog : : onAdd ( )
{
if ( ! Parent : : onAdd ( ) )
return false ;
if ( ! VFRTM - > IsInitialized ( ) )
{
Con : : errorf ( " No VolumetricFogRTManager present!! " ) ;
return false ;
}
resetWorldBox ( ) ;
mShapeLoaded = LoadShape ( ) ;
setRenderTransform ( mObjToWorld ) ;
addToScene ( ) ;
ColBox . set ( getTransform ( ) , ( mObjBox . getExtents ( ) * getScale ( ) * COLBOX_SCALE ) ) ;
mObjSize = mWorldBox . getGreatestDiagonalLength ( ) ;
mObjScale = getScale ( ) ;
mTexTiles = mAbs ( mTexTiles ) ;
mSpeed . set ( mSpeed1 . x , mSpeed1 . y , mSpeed2 . x , mSpeed2 . y ) ;
mInvScale = ( 1.0f / getMax ( getMax ( mObjScale . x , mObjScale . y ) , mObjScale . z ) ) ;
2017-09-15 18:46:19 +00:00
VFRTM - > IncFogObjects ( ) ;
2015-12-01 06:49:37 +00:00
if ( isClientObject ( ) )
{
conn = GameConnection : : getConnectionToServer ( ) ;
if ( ! conn )
{
Con : : errorf ( " VolumetricFog::onAdd - No Serverconnection " ) ;
return false ;
}
glowFX = static_cast < PostEffect * > ( Sim : : findObject ( " VolFogGlowPostFx " ) ) ;
mOldLightRayStrength = Con : : getFloatVariable ( " $LightRayPostFX::brightScalar " , 1.0f ) ;
GuiCanvas * cv = dynamic_cast < GuiCanvas * > ( Sim : : findObject ( " Canvas " ) ) ;
if ( cv = = NULL )
{
Con : : errorf ( " VolumetricFog::onAdd - Canvas not found!! " ) ;
return false ;
}
mPlatformWindow = cv - > getPlatformWindow ( ) ;
VolumetricFogRTManager : : getVolumetricFogRTMResizeSignal ( ) . notify ( this , & VolumetricFog : : handleResize ) ;
GuiCanvas : : getCanvasSizeChangeSignal ( ) . notify ( this , & VolumetricFog : : handleCanvasResize ) ;
InitTexture ( ) ;
return setupRenderer ( ) ;
}
return true ;
}
void VolumetricFog : : onRemove ( )
{
if ( isClientObject ( ) )
{
if ( isTicking ( ) )
{
setProcessTick ( false ) ;
if ( mGlowing ! = 0 )
{
mGlowing = 0 ;
glowFX - > disable ( ) ;
}
2017-09-15 18:46:19 +00:00
_leaveFog ( dynamic_cast < ShapeBase * > ( conn - > getControlObject ( ) ) ) ;
2015-12-01 06:49:37 +00:00
}
VolumetricFogRTManager : : getVolumetricFogRTMResizeSignal ( ) . remove ( this , & VolumetricFog : : handleResize ) ;
GuiCanvas : : getCanvasSizeChangeSignal ( ) . remove ( this , & VolumetricFog : : handleCanvasResize ) ;
}
removeFromScene ( ) ;
VFRTM - > DecFogObjects ( ) ;
Parent : : onRemove ( ) ;
}
void VolumetricFog : : handleCanvasResize ( GuiCanvas * canvas )
{
UpdateBuffers ( 0 , true ) ;
}
void VolumetricFog : : handleResize ( VolumetricFogRTManager * RTM , bool resize )
{
if ( resize )
{
mResizing = true ;
RTM - > FogAnswered ( ) ;
}
else
mResizing = false ;
if ( mIsTextured )
{
F32 width = ( F32 ) mPlatformWindow - > getClientExtent ( ) . x ;
F32 height = ( F32 ) mPlatformWindow - > getClientExtent ( ) . y ;
2016-03-20 11:52:11 +00:00
2015-12-01 06:49:37 +00:00
mTexScale . x = 2.0f - ( ( F32 ) mTexture . getWidth ( ) / width ) ;
mTexScale . y = 2.0f - ( ( F32 ) mTexture . getHeight ( ) / height ) ;
}
UpdateBuffers ( 0 , true ) ;
}
//-----------------------------------------------------------------------------
// Loadshape extracted from TSMesh and TSShapeInstance
//-----------------------------------------------------------------------------
2019-12-06 02:42:47 +00:00
bool VolumetricFog : : setShapeAsset ( const StringTableEntry shapeAssetId )
{
mShapeAssetId = shapeAssetId ;
LoadShape ( ) ;
return true ;
}
2015-12-01 06:49:37 +00:00
bool VolumetricFog : : LoadShape ( )
{
GFXPrimitiveType GFXdrawTypes [ ] = { GFXTriangleList , GFXTriangleStrip } ;
2019-12-06 02:42:47 +00:00
2021-07-19 06:07:08 +00:00
if ( mShapeAsset . isNull ( ) )
2019-12-06 02:42:47 +00:00
{
2021-07-19 06:07:08 +00:00
Con : : errorf ( " [VolumetricFog] Failed to load shape asset. " ) ;
return false ;
2019-12-06 02:42:47 +00:00
}
2015-12-01 06:49:37 +00:00
2021-07-19 06:07:08 +00:00
if ( ! mShape )
2015-12-01 06:49:37 +00:00
{
2021-07-19 06:07:08 +00:00
Con : : errorf ( " VolumetricFog::_createShape() - Shape Asset had no valid shape! " ) ;
2015-12-01 06:49:37 +00:00
return false ;
}
2018-03-13 06:05:15 +00:00
mObjBox = mShape - > mBounds ;
2018-03-13 20:31:00 +00:00
mRadius = mShape - > mRadius ;
2015-12-01 06:49:37 +00:00
resetWorldBox ( ) ;
if ( ! isClientObject ( ) )
return false ;
TSShapeInstance * mShapeInstance = new TSShapeInstance ( mShape , false ) ;
meshes mesh_detail ;
for ( S32 i = 0 ; i < det_size . size ( ) ; i + + )
{
if ( det_size [ i ] . indices ! = NULL )
delete ( det_size [ i ] . indices ) ;
if ( det_size [ i ] . piArray ! = NULL )
delete ( det_size [ i ] . piArray ) ;
if ( det_size [ i ] . verts ! = NULL )
2017-05-07 00:57:10 +00:00
delete [ ] ( det_size [ i ] . verts ) ;
2015-12-01 06:49:37 +00:00
}
det_size . clear ( ) ;
// browsing model for detail levels
for ( U32 i = 0 ; i < mShape - > details . size ( ) ; i + + )
{
const TSDetail * detail = & mShape - > details [ i ] ;
mesh_detail . det_size = detail - > size ;
mesh_detail . sub_shape = detail - > subShapeNum ;
mesh_detail . obj_det = detail - > objectDetailNum ;
mesh_detail . verts = NULL ;
mesh_detail . piArray = NULL ;
mesh_detail . indices = NULL ;
if ( detail - > size > = 0.0f & & detail - > subShapeNum > = 0 )
det_size . push_back ( mesh_detail ) ;
}
for ( U32 i = 0 ; i < det_size . size ( ) ; i + + )
{
const S32 ss = det_size [ i ] . sub_shape ;
if ( ss > = 0 )
{
const S32 start = mShape - > subShapeFirstObject [ ss ] ;
const S32 end = start + mShape - > subShapeNumObjects [ ss ] ;
for ( S32 j = start ; j < end ; j + + )
{
// Loading shape, only the first mesh for each detail will be used!
TSShapeInstance : : MeshObjectInstance * meshObj = & mShapeInstance - > mMeshObjects [ j ] ;
if ( ! meshObj )
continue ;
TSMesh * mesh = meshObj - > getMesh ( det_size [ i ] . obj_det ) ;
if ( mesh ! = NULL )
{
const U32 numNrms = mesh - > mNumVerts ;
GFXVertexPNTT * tmpVerts = NULL ;
tmpVerts = new GFXVertexPNTT [ numNrms ] ;
mIsVBDirty = true ;
for ( U32 k = 0 ; k < numNrms ; k + + )
{
2015-01-10 19:41:25 +00:00
const TSMesh : : __TSMeshVertexBase & vd = mesh - > mVertexData . getBase ( k ) ;
Point3F norm = vd . normal ( ) ;
Point3F vert = vd . vert ( ) ;
Point2F uv = vd . tvert ( ) ;
2015-12-01 06:49:37 +00:00
tmpVerts [ k ] . point = vert ;
tmpVerts [ k ] . texCoord = uv ;
tmpVerts [ k ] . normal = norm ;
}
det_size [ i ] . verts = tmpVerts ;
det_size [ i ] . num_verts = numNrms ;
det_size [ i ] . piArray = new Vector < GFXPrimitive > ( ) ;
GFXPrimitive pInfo ;
det_size [ i ] . indices = new Vector < U32 > ( ) ;
2018-03-13 16:36:36 +00:00
for ( U32 k = 0 ; k < mesh - > mIndices . size ( ) ; k + + )
det_size [ i ] . indices - > push_back ( mesh - > mIndices [ k ] ) ;
2015-12-01 06:49:37 +00:00
2018-03-13 19:53:23 +00:00
U32 primitivesSize = mesh - > mPrimitives . size ( ) ;
2015-12-01 06:49:37 +00:00
for ( U32 k = 0 ; k < primitivesSize ; k + + )
{
2018-03-13 19:53:23 +00:00
const TSDrawPrimitive & draw = mesh - > mPrimitives [ k ] ;
2015-12-01 06:49:37 +00:00
GFXPrimitiveType drawType = GFXdrawTypes [ draw . matIndex > > 30 ] ;
switch ( drawType )
{
case GFXTriangleList :
pInfo . type = drawType ;
pInfo . numPrimitives = draw . numElements / 3 ;
pInfo . startIndex = draw . start ;
// Use the first index to determine which 16-bit address space we are operating in
2018-03-13 16:36:36 +00:00
pInfo . startVertex = mesh - > mIndices [ draw . start ] & 0xFFFF0000 ;
2015-12-01 06:49:37 +00:00
pInfo . minIndex = pInfo . startVertex ;
pInfo . numVertices = getMin ( ( U32 ) 0x10000 , mesh - > mNumVerts - pInfo . startVertex ) ;
break ;
case GFXTriangleStrip :
pInfo . type = drawType ;
pInfo . numPrimitives = draw . numElements - 2 ;
pInfo . startIndex = draw . start ;
// Use the first index to determine which 16-bit address space we are operating in
2018-03-13 16:36:36 +00:00
pInfo . startVertex = mesh - > mIndices [ draw . start ] & 0xFFFF0000 ;
2015-12-01 06:49:37 +00:00
pInfo . minIndex = pInfo . startVertex ;
pInfo . numVertices = getMin ( ( U32 ) 0x10000 , mesh - > mNumVerts - pInfo . startVertex ) ;
break ;
default :
Con : : errorf ( " VolumetricFog::LoadShape Unknown drawtype!?! " ) ;
return false ;
break ;
}
det_size [ i ] . piArray - > push_back ( pInfo ) ;
j = end ;
}
}
else
{
Con : : errorf ( " VolumetricFog::LoadShape Error loading mesh from shape! " ) ;
delete mShapeInstance ;
return false ;
}
mIsVBDirty = true ;
mIsPBDirty = true ;
}
}
}
mNumDetailLevels = det_size . size ( ) ;
mCurDetailLevel = 0 ;
UpdateBuffers ( mCurDetailLevel ) ;
delete mShapeInstance ;
return true ;
}
//-----------------------------------------------------------------------------
// UpdateBuffers called whenever detaillevel changes (LOD)
//-----------------------------------------------------------------------------
bool VolumetricFog : : UpdateBuffers ( U32 dl , bool force )
{
if ( mVB . isNull ( ) | | mIsVBDirty | | dl ! = mCurDetailLevel | | force )
{
mVB . set ( GFX , det_size [ dl ] . num_verts , GFXBufferTypeDynamic ) ;
mIsVBDirty = false ;
}
GFXVertexPNTT * vertPtr = mVB . lock ( ) ;
if ( ! vertPtr )
{
mVB . unlock ( ) ;
return false ;
}
dMemcpy ( vertPtr , det_size [ dl ] . verts , sizeof ( GFXVertexPNTT ) * det_size [ dl ] . num_verts ) ;
mVB . unlock ( ) ;
if ( mIsPBDirty | | mPB . isNull ( ) | | dl ! = mCurDetailLevel | | force )
{
# ifdef TORQUE_DEBUG
mPB . set ( GFX , det_size [ dl ] . indices - > size ( ) , det_size [ dl ] . piArray - > size ( ) , GFXBufferTypeDynamic , avar ( " %s() - VolFogPrimBuffer (line %d) " , __FUNCTION__ , __LINE__ ) ) ;
# else
mPB . set ( GFX , det_size [ dl ] . indices - > size ( ) , det_size [ dl ] . piArray - > size ( ) , GFXBufferTypeDynamic ) ;
# endif
U16 * ibIndices = NULL ;
GFXPrimitive * piInput = NULL ;
mPB . lock ( & ibIndices , & piInput ) ;
dCopyArray ( ibIndices , det_size [ dl ] . indices - > address ( ) , det_size [ dl ] . indices - > size ( ) ) ;
dMemcpy ( piInput , det_size [ dl ] . piArray - > address ( ) , det_size [ dl ] . piArray - > size ( ) * sizeof ( GFXPrimitive ) ) ;
mPB . unlock ( ) ;
mIsPBDirty = false ;
}
mCurDetailLevel = dl ;
return true ;
}
U32 VolumetricFog : : packUpdate ( NetConnection * con , U32 mask , BitStream * stream )
{
U32 retMask = Parent : : packUpdate ( con , mask , stream ) ;
if ( stream - > writeFlag ( mask & FogColorMask ) )
stream - > write ( mFogColor ) ;
if ( stream - > writeFlag ( mask & FogDensityMask ) )
stream - > write ( mFogDensity ) ;
if ( stream - > writeFlag ( mask & FogModulationMask ) )
{
2021-10-03 07:56:26 +00:00
PACK_ASSET ( con , Texture ) ;
2015-12-01 06:49:37 +00:00
mTexTiles = mFabs ( mTexTiles ) ;
stream - > write ( mTexTiles ) ;
stream - > write ( mStrength ) ;
mathWrite ( * stream , mSpeed ) ;
}
if ( stream - > writeFlag ( mask & FogPostFXMask ) )
{
stream - > writeFlag ( mUseGlow ) ;
stream - > write ( mGlowStrength ) ;
stream - > writeFlag ( mModifLightRays ) ;
stream - > write ( mLightRayMod ) ;
}
if ( stream - > writeFlag ( mask & VolumetricFogMask ) )
{
stream - > writeFlag ( mIgnoreWater ) ;
stream - > writeFlag ( mReflect ) ;
stream - > write ( mFogReflStrength ) ;
stream - > writeFlag ( mResizing ) ;
stream - > write ( mMinDisplaySize ) ;
stream - > write ( mFadeSize ) ;
}
if ( stream - > writeFlag ( mask & FogShapeMask ) )
{
2021-10-03 07:56:26 +00:00
PACK_ASSET ( con , Shape ) ;
2015-12-01 06:49:37 +00:00
mathWrite ( * stream , getTransform ( ) ) ;
mathWrite ( * stream , getScale ( ) ) ;
2019-12-06 02:42:47 +00:00
2021-07-19 06:07:08 +00:00
if ( mShapeAsset . notNull ( ) )
2019-12-06 02:42:47 +00:00
{
2021-07-19 06:07:08 +00:00
mObjBox = mShapeAsset - > getShapeResource ( ) - > mBounds ;
mRadius = mShapeAsset - > getShapeResource ( ) - > mRadius ;
2019-12-06 02:42:47 +00:00
}
2021-07-19 06:07:08 +00:00
else
2019-12-06 02:42:47 +00:00
{
2015-12-01 06:49:37 +00:00
return retMask ;
2021-07-19 06:07:08 +00:00
}
2019-12-06 02:42:47 +00:00
2015-12-01 06:49:37 +00:00
resetWorldBox ( ) ;
mObjSize = mWorldBox . getGreatestDiagonalLength ( ) ;
mObjScale = getScale ( ) ;
mInvScale = ( 1.0f / getMax ( getMax ( mObjScale . x , mObjScale . y ) , mObjScale . z ) ) ;
}
return retMask ;
}
void VolumetricFog : : unpackUpdate ( NetConnection * con , BitStream * stream )
{
Parent : : unpackUpdate ( con , stream ) ;
MatrixF mat ;
VectorF scale ;
VectorF mOldScale = getScale ( ) ;
2021-07-19 06:07:08 +00:00
StringTableEntry oldTextureName = mTextureAssetId ;
2019-12-06 02:42:47 +00:00
StringTableEntry oldShapeAsset = mShapeAssetId ;
2015-12-01 06:49:37 +00:00
StringTableEntry oldShape = mShapeName ;
if ( stream - > readFlag ( ) ) // Fog color
stream - > read ( & mFogColor ) ;
if ( stream - > readFlag ( ) ) // Fog Density
{
stream - > read ( & mFogDensity ) ;
if ( isTicking ( ) )
{
char buf [ 20 ] ;
dSprintf ( buf , sizeof ( buf ) , " %3.7f " , mFogDensity ) ;
Con : : setVariable ( " $VolumetricFog::density " , buf ) ;
}
}
if ( stream - > readFlag ( ) ) // Fog Modulation
{
2021-10-03 07:56:26 +00:00
UNPACK_ASSET ( con , Texture ) ;
2015-12-01 06:49:37 +00:00
stream - > read ( & mTexTiles ) ;
mTexTiles = mFabs ( mTexTiles ) ;
stream - > read ( & mStrength ) ;
mathRead ( * stream , & mSpeed ) ;
mSpeed1 . set ( mSpeed . x , mSpeed . y ) ;
mSpeed2 . set ( mSpeed . z , mSpeed . w ) ;
if ( isProperlyAdded ( ) )
{
2021-07-19 06:07:08 +00:00
if ( oldTextureName ! = mTextureAssetId )
2015-12-01 06:49:37 +00:00
InitTexture ( ) ;
2021-07-19 06:07:08 +00:00
if ( oldTextureName ! = StringTable - > EmptyString ( ) & & mTextureAssetId = = StringTable - > EmptyString ( ) )
2015-12-01 06:49:37 +00:00
{
mIsTextured = false ;
mTexture . free ( ) ;
}
}
}
if ( stream - > readFlag ( ) ) //Fog PostFX
{
mUseGlow = stream - > readFlag ( ) ;
stream - > read ( & mGlowStrength ) ;
mModifLightRays = stream - > readFlag ( ) ;
stream - > read ( & mLightRayMod ) ;
if ( isTicking ( ) )
{
2018-03-13 07:11:57 +00:00
char glowStrBuf [ 20 ] ;
dSprintf ( glowStrBuf , sizeof ( glowStrBuf ) , " %3.7f " , mGlowStrength ) ;
Con : : setVariable ( " $VolFogGlowPostFx::glowStrength " , glowStrBuf ) ;
2015-12-01 06:49:37 +00:00
if ( mUseGlow & & ! glowFX - > isEnabled ( ) )
glowFX - > enable ( ) ;
if ( ! mUseGlow & & glowFX - > isEnabled ( ) )
glowFX - > disable ( ) ;
2018-03-13 07:11:57 +00:00
F32 rayStrength = mOldLightRayStrength ;
if ( mModifLightRays )
rayStrength * = mLightRayMod ;
char rayStrBuf [ 20 ] ;
dSprintf ( rayStrBuf , sizeof ( rayStrBuf ) , " %3.7f " , rayStrength ) ;
Con : : setVariable ( " $LightRayPostFX::brightScalar " , rayStrBuf ) ;
2015-12-01 06:49:37 +00:00
}
}
if ( stream - > readFlag ( ) ) //Volumetric Fog
{
mIgnoreWater = stream - > readFlag ( ) ;
mReflect = stream - > readFlag ( ) ;
stream - > read ( & mFogReflStrength ) ;
mResizing = stream - > readFlag ( ) ;
stream - > read ( & mMinDisplaySize ) ;
stream - > read ( & mFadeSize ) ;
}
if ( stream - > readFlag ( ) ) //Fog shape
{
2021-10-03 07:56:26 +00:00
UNPACK_ASSET ( con , Shape ) ;
2019-12-06 02:42:47 +00:00
2015-12-01 06:49:37 +00:00
mathRead ( * stream , & mat ) ;
mathRead ( * stream , & scale ) ;
2019-12-06 02:42:47 +00:00
if ( strcmp ( oldShapeAsset , mShapeAssetId ) ! = 0 | | strcmp ( oldShape , mShapeName ) ! = 0 )
2015-12-01 06:49:37 +00:00
{
mIsVBDirty = true ;
mShapeLoaded = LoadShape ( ) ;
}
setScale ( scale ) ;
setTransform ( mat ) ;
ColBox . set ( getTransform ( ) , ( mObjBox . getExtents ( ) * getScale ( ) * COLBOX_SCALE ) ) ;
mObjSize = mWorldBox . getGreatestDiagonalLength ( ) ;
mObjScale = getScale ( ) ;
mInvScale = ( 1.0f / getMax ( getMax ( mObjScale . x , mObjScale . y ) , mObjScale . z ) ) ;
}
}
void VolumetricFog : : processTick ( const Move * move )
{
Parent : : processTick ( move ) ;
mCounter + + ;
if ( mGlowing = = 1 & & mCurGlow < mGlowStrength )
{
mCurGlow + = ( mGlowStrength / 10.0 ) ;
char buf [ 20 ] ;
dSprintf ( buf , sizeof ( buf ) , " %3.7f " , mCurGlow ) ;
Con : : setVariable ( " $VolFogGlowPostFx::glowStrength " , buf ) ;
}
else if ( mGlowing = = 2 & & mCurGlow > 0.0f )
{
mCurGlow - = ( mGlowStrength / 5.0f ) ;
if ( mCurGlow < = 0.0f )
{
glowFX - > disable ( ) ;
mGlowing = 0 ;
setProcessTick ( false ) ;
return ;
}
else
{
char buf [ 20 ] ;
dSprintf ( buf , sizeof ( buf ) , " %3.7f " , mCurGlow ) ;
Con : : setVariable ( " $VolFogGlowPostFx::glowStrength " , buf ) ;
}
}
if ( mCounter = = 3 )
{
2017-09-15 18:46:19 +00:00
ShapeBase * control = dynamic_cast < ShapeBase * > ( conn - > getControlObject ( ) ) ;
if ( ! control )
return ;
2015-12-01 06:49:37 +00:00
MatrixF xfm ;
control - > getRenderEyeTransform ( & xfm ) ;
Point3F pos = xfm . getPosition ( ) ;
if ( ! ColBox . isContained ( pos ) )
_leaveFog ( control ) ;
mCounter = 0 ;
}
}
void VolumetricFog : : _enterFog ( ShapeBase * control )
{
if ( mUseGlow )
{
if ( glowFX )
{
mCurGlow = 0.0f ;
Con : : setVariable ( " $VolFogGlowPostFx::glowStrength " , " 0.0 " ) ;
glowFX - > enable ( ) ;
mGlowing = 1 ;
}
}
if ( mModifLightRays )
{
char buf [ 20 ] ;
dSprintf ( buf , sizeof ( buf ) , " %3.7f " , mOldLightRayStrength * mLightRayMod ) ;
Con : : setVariable ( " $LightRayPostFX::brightScalar " , buf ) ;
}
mCounter = 0 ;
char buf [ 20 ] ;
dSprintf ( buf , sizeof ( buf ) , " %3.7f " , mFogDensity ) ;
Con : : setVariable ( " $VolumetricFog::density " , buf ) ;
setProcessTick ( true ) ;
if ( control )
onEnterFog_callback ( control - > getId ( ) ) ;
}
void VolumetricFog : : _leaveFog ( ShapeBase * control )
{
mCamInFog = false ;
Con : : setVariable ( " $VolumetricFog::density " , " 0.0 " ) ;
if ( mModifLightRays )
{
char buf [ 20 ] ;
dSprintf ( buf , sizeof ( buf ) , " %3.7f " , mOldLightRayStrength ) ;
Con : : setVariable ( " $LightRayPostFX::brightScalar " , buf ) ;
}
if ( mUseGlow )
{
if ( glowFX & & mGlowing ! = 2 )
{
mCurGlow = mGlowStrength ;
mGlowing = 2 ;
if ( control )
onLeaveFog_callback ( control - > getId ( ) ) ;
}
}
else
{
setProcessTick ( false ) ;
if ( control )
onLeaveFog_callback ( control - > getId ( ) ) ;
}
}
//-----------------------------------------------------------------------------
// Setting up the renderers
//-----------------------------------------------------------------------------
bool VolumetricFog : : setupRenderer ( )
{
2017-04-11 05:23:14 +00:00
// Search for the deferred rendertarget and shadermacros.
mDeferredTarget = NamedTexTarget : : find ( " deferred " ) ;
if ( ! mDeferredTarget . isValid ( ) )
2015-12-01 06:49:37 +00:00
{
2017-04-11 05:23:14 +00:00
Con : : errorf ( " VolumetricFog::setupRenderer - could not find DeferredTarget " ) ;
2015-12-01 06:49:37 +00:00
return false ;
}
Vector < GFXShaderMacro > macros ;
2017-04-11 05:23:14 +00:00
if ( mDeferredTarget )
mDeferredTarget - > getShaderMacros ( & macros ) ;
2015-12-01 06:49:37 +00:00
// Search the depth and frontbuffers which are created by the VolumetricFogRTManager
mDepthBufferTarget = NamedTexTarget : : find ( " volfogdepth " ) ;
if ( ! mDepthBufferTarget . isValid ( ) )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not find depthbuffer " ) ;
return false ;
}
mFrontBufferTarget = NamedTexTarget : : find ( " volfogfront " ) ;
if ( ! mFrontBufferTarget . isValid ( ) )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not find frontbuffer " ) ;
return false ;
}
2017-04-11 05:23:14 +00:00
// Find and setup the deferred Shader
2015-12-01 06:49:37 +00:00
ShaderData * shaderData ;
2017-04-11 05:23:14 +00:00
mDeferredShader = Sim : : findObject ( " VolumetricFogDeferredShader " , shaderData ) ?
2015-12-01 06:49:37 +00:00
shaderData - > getShader ( ) : NULL ;
2017-04-11 05:23:14 +00:00
if ( ! mDeferredShader )
2015-12-01 06:49:37 +00:00
{
2017-04-11 05:23:14 +00:00
Con : : errorf ( " VolumetricFog::setupRenderer - could not find VolumetricFogDeferredShader " ) ;
2015-12-01 06:49:37 +00:00
return false ;
}
// Create ShaderConstBuffer and Handles
2017-04-11 05:23:14 +00:00
mPPShaderConsts = mDeferredShader - > allocConstBuffer ( ) ;
2015-12-01 06:49:37 +00:00
if ( mPPShaderConsts . isNull ( ) )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not allocate ShaderConstants 1. " ) ;
return false ;
}
2017-04-11 05:23:14 +00:00
mPPModelViewProjSC = mDeferredShader - > getShaderConstHandle ( " $modelView " ) ;
2015-12-01 06:49:37 +00:00
// Find and setup the VolumetricFog Shader
shaderData = NULL ;
mShader = Sim : : findObject ( " VolumetricFogShader " , shaderData ) ?
shaderData - > getShader ( macros ) : NULL ;
if ( ! mShader )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not find VolumetricFogShader " ) ;
return false ;
}
// Create ShaderConstBuffer and Handles
mShaderConsts = mShader - > allocConstBuffer ( ) ;
if ( mShaderConsts . isNull ( ) )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not allocate ShaderConstants 2. " ) ;
return false ;
}
mModelViewProjSC = mShader - > getShaderConstHandle ( " $modelView " ) ;
mFadeSizeSC = mShader - > getShaderConstHandle ( " $fadesize " ) ;
mFogColorSC = mShader - > getShaderConstHandle ( " $fogColor " ) ;
mFogDensitySC = mShader - > getShaderConstHandle ( " $fogDensity " ) ;
mPreBias = mShader - > getShaderConstHandle ( " $preBias " ) ;
mAccumTime = mShader - > getShaderConstHandle ( " $accumTime " ) ;
mIsTexturedSC = mShader - > getShaderConstHandle ( " $textured " ) ;
mTexTilesSC = mShader - > getShaderConstHandle ( " $numtiles " ) ;
mModStrengthSC = mShader - > getShaderConstHandle ( " $modstrength " ) ;
mModSpeedSC = mShader - > getShaderConstHandle ( " $modspeed " ) ;
mViewPointSC = mShader - > getShaderConstHandle ( " $viewpoint " ) ;
mTexScaleSC = mShader - > getShaderConstHandle ( " $texscale " ) ;
mAmbientColorSC = mShader - > getShaderConstHandle ( " $ambientColor " ) ;
// Find and setup the reflection Shader
shaderData = NULL ;
mReflectionShader = Sim : : findObject ( " VolumetricFogReflectionShader " , shaderData ) ?
shaderData - > getShader ( ) : NULL ;
if ( ! mReflectionShader )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not find VolumetricFogReflectionShader " ) ;
return false ;
}
mReflShaderConsts = mReflectionShader - > allocConstBuffer ( ) ;
if ( mReflShaderConsts . isNull ( ) )
{
Con : : errorf ( " VolumetricFog::setupRenderer - could not allocate ShaderConstants for VolumetricFogReflectionShader. " ) ;
return false ;
}
mReflModelViewProjSC = mReflectionShader - > getShaderConstHandle ( " $modelView " ) ;
mReflFogColorSC = mReflectionShader - > getShaderConstHandle ( " $fogColor " ) ;
mReflFogDensitySC = mReflectionShader - > getShaderConstHandle ( " $fogDensity " ) ;
mReflFogStrengthSC = mReflectionShader - > getShaderConstHandle ( " $reflStrength " ) ;
2017-04-11 05:23:14 +00:00
// Create the deferred StateBlock
2015-12-01 06:49:37 +00:00
desc_preD . setCullMode ( GFXCullCW ) ;
desc_preD . setBlend ( true ) ;
desc_preD . setZReadWrite ( false , false ) ;
desc_preD . stencilEnable = false ;
desc_preF . setCullMode ( GFXCullCCW ) ;
desc_preF . setBlend ( true ) ;
desc_preF . setZReadWrite ( true , false ) ;
desc_preF . stencilEnable = false ;
// Create the VolumetricFog StateBlock
descD . setCullMode ( GFXCullCW ) ;
descD . setBlend ( true ) ;
descD . setZReadWrite ( false , false ) ; // desc.setZReadWrite(true, false);
2017-04-11 05:23:14 +00:00
// deferredBuffer sampler
2015-12-01 06:49:37 +00:00
descD . samplersDefined = true ;
descD . samplers [ 0 ] . addressModeU = GFXAddressClamp ;
descD . samplers [ 0 ] . addressModeV = GFXAddressClamp ;
descD . samplers [ 0 ] . addressModeW = GFXAddressClamp ;
descD . samplers [ 0 ] . magFilter = GFXTextureFilterLinear ;
descD . samplers [ 0 ] . minFilter = GFXTextureFilterLinear ;
descD . samplers [ 0 ] . mipFilter = GFXTextureFilterLinear ;
// DepthBuffer sampler
descD . samplers [ 1 ] . addressModeU = GFXAddressClamp ;
descD . samplers [ 1 ] . addressModeV = GFXAddressClamp ;
descD . samplers [ 1 ] . addressModeW = GFXAddressClamp ;
descD . samplers [ 1 ] . magFilter = GFXTextureFilterLinear ;
descD . samplers [ 1 ] . minFilter = GFXTextureFilterLinear ;
descD . samplers [ 1 ] . mipFilter = GFXTextureFilterLinear ;
// FrontBuffer sampler
descD . samplers [ 2 ] . addressModeU = GFXAddressClamp ;
descD . samplers [ 2 ] . addressModeV = GFXAddressClamp ;
descD . samplers [ 2 ] . addressModeW = GFXAddressClamp ;
descD . samplers [ 2 ] . magFilter = GFXTextureFilterLinear ;
descD . samplers [ 2 ] . minFilter = GFXTextureFilterLinear ;
descD . samplers [ 2 ] . mipFilter = GFXTextureFilterLinear ;
// animated density modifier map sampler
descD . samplers [ 3 ] . addressModeU = GFXAddressWrap ;
descD . samplers [ 3 ] . addressModeV = GFXAddressWrap ;
descD . samplers [ 3 ] . addressModeW = GFXAddressWrap ;
descD . samplers [ 3 ] . magFilter = GFXTextureFilterLinear ;
descD . samplers [ 3 ] . minFilter = GFXTextureFilterLinear ;
descD . samplers [ 3 ] . mipFilter = GFXTextureFilterLinear ;
dMemcpy ( & descF , & descD , sizeof ( GFXStateBlockDesc ) ) ;
descF . setCullMode ( GFXCullCCW ) ;
descF . setBlend ( true ) ;
descF . setZReadWrite ( true , false ) ;
desc_refl . setCullMode ( GFXCullCCW ) ;
desc_refl . setBlend ( true ) ;
desc_refl . setZReadWrite ( true , false ) ;
mStateblock_preD = GFX - > createStateBlock ( desc_preD ) ;
mStateblock_preF = GFX - > createStateBlock ( desc_preF ) ;
mStateblockD = GFX - > createStateBlock ( descD ) ;
mStateblockF = GFX - > createStateBlock ( descF ) ;
mStateblock_refl = GFX - > createStateBlock ( desc_refl ) ;
// Create Rendertarget
z_buf = GFX - > allocRenderToTextureTarget ( ) ;
if ( z_buf = = NULL )
{
Con : : errorf ( " VolumetricFog::setupRenderer - Could not create Render Target " ) ;
return false ;
}
return true ;
}
void VolumetricFog : : prepRenderImage ( SceneRenderState * state )
{
if ( ! mShapeLoaded | | mFogDensity < = 0.0f | | mResizing )
return ;
if ( ! state - > isDiffusePass ( ) )
{
if ( ! state - > isReflectPass ( ) )
return ;
}
PROFILE_SCOPE ( VolumetricFog_prepRenderImage ) ;
2017-09-15 18:46:19 +00:00
ShapeBase * control = dynamic_cast < ShapeBase * > ( conn - > getControlObject ( ) ) ;
if ( ! control | | ( control - > getWaterCoverage ( ) > = 0.9f & & ! mIgnoreWater ) )
2015-12-01 06:49:37 +00:00
return ;
camPos = state - > getCameraPosition ( ) ;
F32 dist = ( camPos - getBoxCenter ( ) ) . len ( ) ;
F32 scaleFactor = dist * mInvScale ;
if ( scaleFactor < = 0.0f )
{
if ( mCurDetailLevel ! = 0 )
UpdateBuffers ( 0 ) ;
}
const F32 pixelScale = state - > getViewport ( ) . extent . y / 300.0f ;
mPixelSize = ( mRadius / scaleFactor ) * state - > getWorldToScreenScale ( ) . y * pixelScale ;
if ( mPixelSize < mMinDisplaySize )
return ;
if ( mNumDetailLevels > 1 )
{
2020-09-19 23:25:10 +00:00
if ( ( mCurDetailLevel < mNumDetailLevels - 1 ) & & ( det_size [ mCurDetailLevel ] . det_size > mPixelSize ) )
2015-12-01 06:49:37 +00:00
UpdateBuffers ( mCurDetailLevel + 1 ) ;
else if ( mCurDetailLevel > 0 )
{
if ( mPixelSize > = det_size [ mCurDetailLevel - 1 ] . det_size )
UpdateBuffers ( mCurDetailLevel - 1 ) ;
}
}
if ( state - > isReflectPass ( ) & & mReflect )
{
ObjectRenderInst * ri = state - > getRenderPass ( ) - > allocInst < ObjectRenderInst > ( ) ;
ri - > renderDelegate . bind ( this , & VolumetricFog : : reflect_render ) ;
ri - > type = RenderPassManager : : RIT_VolumetricFog ;
ri - > translucentSort = true ;
ri - > sortDistSq = getRenderWorldBox ( ) . getSqDistanceToPoint ( camPos ) ;
if ( dist < 1.0f )
ri - > defaultKey = 1 ;
else
ri - > defaultKey = U32 ( dist ) ;
state - > getRenderPass ( ) - > addInst ( ri ) ;
return ;
}
else if ( state - > isDiffusePass ( ) )
{
viewDist = state - > getFarPlane ( ) ;
mFOV = state - > getCameraFrustum ( ) . getFov ( ) / M_PI_F ;
Point3F mEyeVec = state - > getVectorEye ( ) * viewDist ;
mViewPoint . x = ( ( mAtan2 ( mEyeVec . x , mEyeVec . y ) / M_PI_F ) + 1.0f ) * mTexTiles ;
mViewPoint . y = ( 0.5f - ( mAsin ( mEyeVec . z ) / M_PI_F ) ) * mTexTiles ;
bool isInside = ColBox . isContained ( camPos ) ;
if ( isInside & & ! mCamInFog )
{
mCamInFog = true ;
_enterFog ( control ) ;
}
else if ( ! isInside & & mCamInFog )
mCamInFog = false ;
ObjectRenderInst * ri = state - > getRenderPass ( ) - > allocInst < ObjectRenderInst > ( ) ;
ri - > renderDelegate . bind ( this , & VolumetricFog : : render ) ;
ri - > type = RenderPassManager : : RIT_VolumetricFog ;
ri - > translucentSort = true ;
ri - > sortDistSq = getRenderWorldBox ( ) . getSqDistanceToPoint ( camPos ) ;
if ( dist < 1.0f )
ri - > defaultKey = 1 ;
else
ri - > defaultKey = U32 ( dist ) ;
state - > getRenderPass ( ) - > addInst ( ri ) ;
return ;
}
return ;
}
void VolumetricFog : : render ( ObjectRenderInst * ri , SceneRenderState * state , BaseMatInstance * overrideMat )
{
if ( overrideMat | | ! mShapeLoaded | | ! isClientObject ( ) | | mResizing )
return ;
PROFILE_SCOPE ( VolumetricFog_Render ) ;
GFXTransformSaver saver ;
GFX - > setVertexBuffer ( mVB ) ;
GFX - > setPrimitiveBuffer ( mPB ) ;
MatrixF mat = getRenderTransform ( ) ;
mat . scale ( mObjScale ) ;
GFX - > multWorld ( mat ) ;
2017-04-11 05:23:14 +00:00
GFX - > setShader ( mDeferredShader ) ;
2015-12-01 06:49:37 +00:00
GFX - > setShaderConstBuffer ( mPPShaderConsts ) ;
GFX - > setStateBlock ( mStateblock_preD ) ;
// Set all the shader consts...
MatrixF xform ( GFX - > getProjectionMatrix ( ) ) ;
xform * = GFX - > getViewMatrix ( ) ;
xform * = GFX - > getWorldMatrix ( ) ;
mPPShaderConsts - > setSafe ( mPPModelViewProjSC , xform ) ;
2017-06-23 16:36:20 +00:00
const LinearColorF & sunlight = state - > getAmbientLightColor ( ) ;
2015-12-01 06:49:37 +00:00
Point3F ambientColor ( sunlight . red , sunlight . green , sunlight . blue ) ;
mShaderConsts - > setSafe ( mAmbientColorSC , ambientColor ) ;
GFXTextureObject * mDepthBuffer = mDepthBufferTarget ? mDepthBufferTarget - > getTexture ( 0 ) : NULL ;
GFXTextureObject * mFrontBuffer = mFrontBufferTarget ? mFrontBufferTarget - > getTexture ( 0 ) : NULL ;
GFX - > pushActiveRenderTarget ( ) ;
//render backside to target mDepthBuffer
z_buf - > attachTexture ( GFXTextureTarget : : DepthStencil , GFXTextureTarget : : sDefaultDepthStencil ) ;
z_buf - > attachTexture ( GFXTextureTarget : : Color0 , mDepthBuffer ) ;
GFX - > setActiveRenderTarget ( z_buf ) ;
GFX - > clear ( GFXClearStencil | GFXClearTarget , ColorI ( 0 , 0 , 0 , 0 ) , 1.0f , 0 ) ;
GFX - > drawPrimitive ( 0 ) ;
z_buf - > resolve ( ) ;
//render frontside to target mFrontBuffer
z_buf - > attachTexture ( GFXTextureTarget : : DepthStencil , GFXTextureTarget : : sDefaultDepthStencil ) ;
z_buf - > attachTexture ( GFXTextureTarget : : Color0 , mFrontBuffer ) ;
GFX - > clear ( GFXClearStencil | GFXClearTarget , ColorI ( 0 , 0 , 0 , 0 ) , 1.0f , 0 ) ;
GFX - > setStateBlock ( mStateblock_preF ) ;
GFX - > drawPrimitive ( 0 ) ;
z_buf - > resolve ( ) ;
GFX - > popActiveRenderTarget ( ) ;
z_buf - > attachTexture ( GFXTextureTarget : : Color0 , NULL ) ;
//render Volumetric Fog
GFX - > setShader ( mShader ) ;
GFX - > setShaderConstBuffer ( mShaderConsts ) ;
mShaderConsts - > setSafe ( mModelViewProjSC , xform ) ;
if ( mFadeSize > 0.0f )
mShaderConsts - > setSafe ( mFadeSizeSC , mClampF ( mPixelSize / mFadeSize , 0.0f , 1.0f ) ) ;
else
mShaderConsts - > setSafe ( mFadeSizeSC , 1.0f ) ;
mShaderConsts - > setSafe ( mFogColorSC , mFogColor ) ;
mShaderConsts - > setSafe ( mFogDensitySC , mFogDensity ) ;
mShaderConsts - > setSafe ( mPreBias , viewDist ) ;
mShaderConsts - > setSafe ( mAccumTime , ( F32 ) Sim : : getCurrentTime ( ) / 1000.0f ) ;
mShaderConsts - > setSafe ( mModStrengthSC , mStrength ) ;
mShaderConsts - > setSafe ( mModSpeedSC , mSpeed ) ;
mShaderConsts - > setSafe ( mViewPointSC , mViewPoint ) ;
mShaderConsts - > setSafe ( mTexScaleSC , mTexScale * mFOV ) ;
mShaderConsts - > setSafe ( mTexTilesSC , mTexTiles ) ;
2017-04-11 05:23:14 +00:00
GFXTextureObject * deferredtex = mDeferredTarget ? mDeferredTarget - > getTexture ( 0 ) : NULL ;
2015-12-01 06:49:37 +00:00
2017-04-11 05:23:14 +00:00
GFX - > setTexture ( 0 , deferredtex ) ;
2015-12-01 06:49:37 +00:00
GFX - > setTexture ( 1 , mDepthBuffer ) ;
GFX - > setTexture ( 2 , mFrontBuffer ) ;
if ( mIsTextured & & mStrength > 0.0f )
{
GFX - > setTexture ( 3 , mTexture ) ;
mShaderConsts - > setSafe ( mIsTexturedSC , 1.0f ) ;
}
else
mShaderConsts - > setSafe ( mIsTexturedSC , 0.0f ) ;
if ( mCamInFog )
{
/*GFXLockedRect *rect=mDepthBuffer->lock();
U32 pixoffset = 0 ; // 1572864 + (512 * 4);
U8 red = rect - > bits [ pixoffset ] ;
U8 green = rect - > bits [ pixoffset + 1 ] ;
U8 blue = rect - > bits [ pixoffset + 2 ] ;
U8 alpha = rect - > bits [ pixoffset + 3 ] ;
mDepthBuffer - > unlock ( ) ;
S32 lval = ( ( alpha < < 24 ) + ( blue < < 16 ) + ( green < < 8 ) + ( red ) ) ;
F32 fval = ( ( F32 ) lval / S32_MAX ) ;
Con : : printf ( " Color %d %d %d %d %d %f " , red , green , blue , alpha , lval , fval ) ; */
GFX - > setStateBlock ( mStateblockD ) ;
}
else
GFX - > setStateBlock ( mStateblockF ) ;
GFX - > drawPrimitive ( 0 ) ;
2016-03-20 11:52:11 +00:00
2017-07-09 20:15:30 +00:00
// Ensure these two textures are NOT bound to the pixel shader input on the second run as they are used as pixel shader outputs (render targets).
GFX - > clearTextureStateImmediate ( 1 ) ; //mDepthBuffer
GFX - > clearTextureStateImmediate ( 2 ) ; //mFrontBuffer
2015-12-01 06:49:37 +00:00
}
void VolumetricFog : : reflect_render ( ObjectRenderInst * ri , SceneRenderState * state , BaseMatInstance * overrideMat )
{
if ( overrideMat | | ! mShapeLoaded | | ! isClientObject ( ) | | mResizing | | ( mFogReflStrength = = 0.0f ) )
return ;
GFXTransformSaver saver ;
GFX - > setVertexBuffer ( mVB ) ;
GFX - > setPrimitiveBuffer ( mPB ) ;
MatrixF mat = getRenderTransform ( ) ;
mat . scale ( mObjScale ) ;
GFX - > multWorld ( mat ) ;
GFX - > setShader ( mReflectionShader ) ;
GFX - > setShaderConstBuffer ( mReflShaderConsts ) ;
GFX - > setStateBlock ( mStateblock_refl ) ;
// Set all the shader consts...
MatrixF xform ( GFX - > getProjectionMatrix ( ) ) ;
xform * = GFX - > getViewMatrix ( ) ;
xform * = GFX - > getWorldMatrix ( ) ;
mReflShaderConsts - > setSafe ( mReflModelViewProjSC , xform ) ;
mReflShaderConsts - > setSafe ( mReflFogColorSC , mFogColor ) ;
mReflShaderConsts - > setSafe ( mReflFogDensitySC , mFogDensity ) ;
mReflShaderConsts - > setSafe ( mReflFogStrengthSC , mFogReflStrength ) ;
GFX - > drawPrimitive ( 0 ) ;
}
//-----------------------------------------------------------------------------
// InitTexture is called whenever a modulation texture is added to the object
//-----------------------------------------------------------------------------
void VolumetricFog : : InitTexture ( )
{
mIsTextured = false ;
2021-07-19 06:07:08 +00:00
if ( mTextureAsset . isNull ( ) )
return ;
2015-12-01 06:49:37 +00:00
if ( ! mTexture . isNull ( ) )
{
mIsTextured = true ;
F32 width = ( F32 ) mPlatformWindow - > getClientExtent ( ) . x ;
F32 height = ( F32 ) mPlatformWindow - > getClientExtent ( ) . y ;
mTexScale . x = 2.0f - ( ( F32 ) mTexture . getWidth ( ) / width ) ;
mTexScale . y = 2.0f - ( ( F32 ) mTexture . getHeight ( ) / height ) ;
}
}
2017-06-23 16:36:20 +00:00
void VolumetricFog : : setFogColor ( LinearColorF color )
2015-12-01 06:49:37 +00:00
{
mFogColor . set ( 255 * color . red , 255 * color . green , 255 * color . blue ) ;
setMaskBits ( FogColorMask ) ;
}
void VolumetricFog : : setFogColor ( ColorI color )
{
mFogColor = color ;
setMaskBits ( FogColorMask ) ;
}
void VolumetricFog : : setFogDensity ( F32 density )
{
if ( density < 0.0f )
density = 0.0f ;
mFogDensity = density ;
setMaskBits ( FogDensityMask ) ;
}
void VolumetricFog : : setFogModulation ( F32 strength , Point2F speed1 , Point2F speed2 )
{
mStrength = strength ;
mSpeed1 = speed1 ;
mSpeed2 = speed2 ;
mSpeed . set ( speed1 . x , speed1 . y , speed2 . x , speed2 . y ) ;
setMaskBits ( FogModulationMask ) ;
}
void VolumetricFog : : setFogGlow ( bool on_off , F32 strength )
{
mUseGlow = on_off ;
mGlowStrength = strength ;
setMaskBits ( FogPostFXMask ) ;
}
void VolumetricFog : : setFogLightray ( bool on_off , F32 strength )
{
mModifLightRays = on_off ;
mLightRayMod = strength ;
setMaskBits ( FogPostFXMask ) ;
}
bool VolumetricFog : : isInsideFog ( )
{
return mCamInFog ;
}
2017-06-23 16:36:20 +00:00
DefineEngineMethod ( VolumetricFog , SetFogColorF , void , ( LinearColorF new_color ) , ,
2015-12-01 06:49:37 +00:00
" @brief Changes the color of the fog \n \n . "
" @params new_color the new fog color (rgb 0.0 - 1.0, a is ignored. " )
{
object - > setFogColor ( new_color ) ;
}
DefineEngineMethod ( VolumetricFog , SetFogColor , void , ( ColorI new_color ) , ,
" @brief Changes the color of the fog \n \n . "
" @params new_color the new fog color (rgb 0-255, a is ignored. " )
{
object - > setFogColor ( new_color ) ;
}
DefineEngineMethod ( VolumetricFog , SetFogDensity , void , ( F32 new_density ) , ,
" @brief Changes the density of the fog \n \n . "
" @params new_density the new fog density. " )
{
object - > setFogDensity ( new_density ) ;
}
DefineEngineMethod ( VolumetricFog , SetFogModulation , void , ( F32 new_strenght , Point2F new_speed1 , Point2F new_speed2 ) , ,
" @brief Changes the modulation of the fog \n \n . "
" @params new_strenght the new strength of the modulation. \n "
" @params new_speed1 the new speed (x y) of the modulation layer 1. \n "
" @params new_speed2 the new speed (x y) of the modulation layer 2. \n " )
{
object - > setFogModulation ( new_strenght , new_speed1 , new_speed2 ) ;
}
DefineEngineMethod ( VolumetricFog , SetFogGlow , void , ( bool on_off , F32 strength ) , ,
" @brief Changes the glow postfx when inside the fog \n \n . "
" @params on_off set to true to enable glow. \n "
" @params strength glow strength. \n " )
{
object - > setFogGlow ( on_off , strength ) ;
}
DefineEngineMethod ( VolumetricFog , SetFogLightray , void , ( bool on_off , F32 strength ) , ,
" @brief Changes the lightrays postfx when inside the fog \n \n . "
" @params on_off set to true to modification of the lightray postfx. \n "
" @params strength lightray strength. \n " )
{
object - > setFogLightray ( on_off , strength ) ;
}
DefineEngineMethod ( VolumetricFog , isInsideFog , bool , ( ) , ,
" @brief returns true if control object is inside the fog \n \n . " )
{
return object - > isInsideFog ( ) ;
2019-12-08 21:54:37 +00:00
}