From 5d5e878129be994d435ee4bcf3c513b8a76f8420 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Thu, 23 Oct 2014 20:48:58 -0500 Subject: [PATCH] dynamic cubemap support for tsStatics engine: implements the capacity for tsstatic objects to allow themselves to use the reflector system in order to display runtime generated cubemaps. script: defines a calibrated reflectordesc that reflects all object types within the space of approximately half stock veiwdistance usage: cubeReflectorDesc = DefaultCubeDesc placed in a given object-insatnces entry that uses a material with a dynamiccubemap = true; flag. immediate purpose: consistency of application of materials. long term impact: tags steps required in order to associate a given runtime generated cubemap with an object-instance. in the future, this is likely to give way to an area-derived cubemap based on the accumulation volume tech developed by Andrew Mac, or a screenspace reflection. --- Engine/source/T3D/tsStatic.cpp | 60 +++++++++++++++++++ Engine/source/T3D/tsStatic.h | 9 +++ .../Full/game/art/datablocks/environment.cs | 12 ++++ 3 files changed, 81 insertions(+) diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 1474bf96d..c7ef76d4f 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -90,6 +90,9 @@ ConsoleDocClass( TSStatic, ); TSStatic::TSStatic() +: + cubeDescId( 0 ), + reflectorDesc( NULL ) { mNetFlags.set(Ghostable | ScopeAlways); @@ -180,6 +183,11 @@ void TSStatic::initPersistFields() endGroup("Rendering"); + addGroup( "Reflection" ); + addField( "cubeReflectorDesc", TypeRealString, Offset( cubeDescName, TSStatic ), + "References a ReflectorDesc datablock that defines performance and quality properties for dynamic reflections.\n"); + endGroup( "Reflection" ); + addGroup("Collision"); addField( "collisionType", TypeTSMeshType, Offset( mCollisionType, TSStatic ), @@ -279,6 +287,14 @@ bool TSStatic::onAdd() addToScene(); + if ( isClientObject() ) + { + mCubeReflector.unregisterReflector(); + + if ( reflectorDesc ) + mCubeReflector.registerReflector( this, reflectorDesc ); + } + _updateShouldTick(); return true; @@ -337,6 +353,16 @@ bool TSStatic::_createShape() if ( mAmbientThread ) mShapeInstance->setSequence( mAmbientThread, ambientSeq, 0); + // Resolve CubeReflectorDesc. + if ( cubeDescName.isNotEmpty() ) + { + Sim::findObject( cubeDescName, reflectorDesc ); + } + else if( cubeDescId > 0 ) + { + Sim::findObject( cubeDescId, reflectorDesc ); + } + return true; } @@ -402,6 +428,8 @@ void TSStatic::onRemove() mShapeInstance = NULL; mAmbientThread = NULL; + if ( isClientObject() ) + mCubeReflector.unregisterReflector(); Parent::onRemove(); } @@ -504,6 +532,12 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); + // If we're currently rendering our own reflection we + // don't want to render ourselves into it. + if ( mCubeReflector.isRendering() ) + return; + + if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else @@ -520,6 +554,9 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); + if ( mCubeReflector.isEnabled() ) + rdata.setCubemap( mCubeReflector.getCubemap() ); + // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; @@ -544,6 +581,20 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); + if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) + { + RenderPassManager *pass = state->getRenderPass(); + OccluderRenderInst *ri = pass->allocInst(); + + ri->type = RenderPassManager::RIT_Occluder; + ri->query = mCubeReflector.getOcclusionQuery(); + mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); + ri->scale.set( mObjBox.getExtents() ); + ri->orientation = pass->allocUniqueXform( mObjToWorld ); + ri->isSphere = false; + state->getRenderPass()->addInst( ri ); + } + mShapeInstance->animate(); mShapeInstance->render( rdata ); @@ -628,6 +679,10 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream) if ( mLightPlugin ) retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream); + if( stream->writeFlag( reflectorDesc != NULL ) ) + { + stream->writeRangedU32( reflectorDesc->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast ); + } return retMask; } @@ -687,6 +742,11 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream) mLightPlugin->unpackUpdate(this, con, stream); } + if( stream->readFlag() ) + { + cubeDescId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); + } + if ( isProperlyAdded() ) _updateShouldTick(); } diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index fe7113294..ac6c50cc1 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -39,6 +39,10 @@ #include "ts/tsShape.h" #endif +#ifndef _REFLECTOR_H_ + #include "scene/reflector.h" +#endif + class TSShapeInstance; class TSThread; class TSStatic; @@ -135,6 +139,11 @@ protected: /// Start or stop processing ticks depending on our state. void _updateShouldTick(); + String cubeDescName; + U32 cubeDescId; + ReflectorDesc *reflectorDesc; + CubeReflector mCubeReflector; + protected: Convex *mConvexList; diff --git a/Templates/Full/game/art/datablocks/environment.cs b/Templates/Full/game/art/datablocks/environment.cs index 386703f67..c9d2b0a51 100644 --- a/Templates/Full/game/art/datablocks/environment.cs +++ b/Templates/Full/game/art/datablocks/environment.cs @@ -84,3 +84,15 @@ datablock LightningData(DefaultStorm) thunderSounds[2] = ThunderCrash3Sound; thunderSounds[3] = ThunderCrash4Sound; }; + +datablock ReflectorDesc( DefaultCubeDesc ) +{ + texSize = 256; + nearDist = 0.1; + farDist = 1000.0; + objectTypeMask = 0xFFFFFFFF; + detailAdjust = 1.0; + priority = 1.0; + maxRateMs = 15; + useOcclusionQuery = true; +};