diff --git a/Engine/source/T3D/accumulationVolume.cpp b/Engine/source/T3D/accumulationVolume.cpp new file mode 100644 index 000000000..7eef90634 --- /dev/null +++ b/Engine/source/T3D/accumulationVolume.cpp @@ -0,0 +1,349 @@ +//----------------------------------------------------------------------------- +// 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 "platform/platform.h" +#include "T3D/accumulationVolume.h" + +#include "scene/sceneManager.h" +#include "scene/sceneRenderState.h" +#include "gfx/gfxDevice.h" +#include "gfx/gfxDrawUtil.h" +#include "gfx/sim/debugDraw.h" +#include "util/tempAlloc.h" +#include "materials/materialDefinition.h" +#include "materials/materialManager.h" +#include "materials/materialFeatureTypes.h" +#include "materials/matInstance.h" +#include "console/consoleTypes.h" +#include "core/stream/bitStream.h" +#include "gfx/gfxDevice.h" +#include "console/console.h" +#include "console/engineAPI.h" +#include "gfx/gfxTextureHandle.h" +#include "scene/sceneContainer.h" + +#include "math/mPolyhedron.impl.h" + +Vector< SimObjectPtr > AccumulationVolume::smAccuObjects; +Vector< SimObjectPtr > AccumulationVolume::smAccuVolumes; + +//#define DEBUG_DRAW + +IMPLEMENT_CO_NETOBJECT_V1( AccumulationVolume ); + +ConsoleDocClass( AccumulationVolume, + "@brief An invisible shape that allow objects within it to have an accumulation map.\n\n" + + "AccumulationVolume is used to add additional realism to a scene. It's main use is in outdoor scenes " + " where objects could benefit from overlaying environment accumulation textures such as sand, snow, etc.\n\n" + + "Objects within the volume must have accumulation enabled in their material. \n\n" + + "@ingroup enviroMisc" +); + +//----------------------------------------------------------------------------- + +AccumulationVolume::AccumulationVolume() + : mTransformDirty( true ), + mSilhouetteExtractor( mPolyhedron ) +{ + VECTOR_SET_ASSOCIATION( mWSPoints ); + VECTOR_SET_ASSOCIATION( mVolumeQueryList ); + + //mObjectFlags.set( VisualOccluderFlag ); + + mNetFlags.set( Ghostable | ScopeAlways ); + mObjScale.set( 1.f, 1.f, 1.f ); + mObjBox.set( + Point3F( -0.5f, -0.5f, -0.5f ), + Point3F( 0.5f, 0.5f, 0.5f ) + ); + + mObjToWorld.identity(); + mWorldToObj.identity(); + + // Accumulation Texture. + mTextureName = ""; + mAccuTexture = NULL; + + resetWorldBox(); +} + +AccumulationVolume::~AccumulationVolume() +{ + mAccuTexture = NULL; +} + +void AccumulationVolume::initPersistFields() +{ + addProtectedField( "texture", TypeStringFilename, Offset( mTextureName, AccumulationVolume ), + &_setTexture, &defaultProtectedGetFn, "Accumulation texture." ); + + Parent::initPersistFields(); +} + +//----------------------------------------------------------------------------- + +void AccumulationVolume::consoleInit() +{ + // Disable rendering of occlusion volumes by default. + getStaticClassRep()->mIsRenderEnabled = false; +} + +//----------------------------------------------------------------------------- + +bool AccumulationVolume::onAdd() +{ + if( !Parent::onAdd() ) + return false; + + // Prepare some client side things. + if ( isClientObject() ) + { + smAccuVolumes.push_back(this); + refreshVolumes(); + } + + // Set up the silhouette extractor. + mSilhouetteExtractor = SilhouetteExtractorType( mPolyhedron ); + + return true; +} + +void AccumulationVolume::onRemove() +{ + if ( isClientObject() ) + { + smAccuVolumes.remove(this); + refreshVolumes(); + } + Parent::onRemove(); +} + +//----------------------------------------------------------------------------- + +void AccumulationVolume::_renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat ) +{ + Parent::_renderObject( ri, state, overrideMat ); + + #ifdef DEBUG_DRAW + if( state->isDiffusePass() ) + DebugDrawer::get()->drawPolyhedronDebugInfo( mPolyhedron, getTransform(), getScale() ); + #endif +} + +//----------------------------------------------------------------------------- + +void AccumulationVolume::setTransform( const MatrixF& mat ) +{ + Parent::setTransform( mat ); + mTransformDirty = true; + refreshVolumes(); +} + +//----------------------------------------------------------------------------- + +void AccumulationVolume::buildSilhouette( const SceneCameraState& cameraState, Vector< Point3F >& outPoints ) +{ + // Extract the silhouette of the polyhedron. This works differently + // depending on whether we project orthogonally or in perspective. + + TempAlloc< U32 > indices( mPolyhedron.getNumPoints() ); + U32 numPoints; + + if( cameraState.getFrustum().isOrtho() ) + { + // Transform the view direction into object space. + + Point3F osViewDir; + getWorldTransform().mulV( cameraState.getViewDirection(), &osViewDir ); + + // And extract the silhouette. + + SilhouetteExtractorOrtho< PolyhedronType > extractor( mPolyhedron ); + numPoints = extractor.extractSilhouette( osViewDir, indices, indices.size ); + } + else + { + // Create a transform to go from view space to object space. + + MatrixF camView( true ); + camView.scale( Point3F( 1.0f / getScale().x, 1.0f / getScale().y, 1.0f / getScale().z ) ); + camView.mul( getRenderWorldTransform() ); + camView.mul( cameraState.getViewWorldMatrix() ); + + // Do a perspective-correct silhouette extraction. + + numPoints = mSilhouetteExtractor.extractSilhouette( + camView, + indices, indices.size ); + } + + // If we haven't yet, transform the polyhedron's points + // to world space. + + if( mTransformDirty ) + { + const U32 numPoints = mPolyhedron.getNumPoints(); + const PolyhedronType::PointType* points = getPolyhedron().getPoints(); + + mWSPoints.setSize( numPoints ); + for( U32 i = 0; i < numPoints; ++ i ) + { + Point3F p = points[ i ]; + p.convolve( getScale() ); + getTransform().mulP( p, &mWSPoints[ i ] ); + } + + mTransformDirty = false; + } + + // Now store the points. + + outPoints.setSize( numPoints ); + for( U32 i = 0; i < numPoints; ++ i ) + outPoints[ i ] = mWSPoints[ indices[ i ] ]; +} + +//----------------------------------------------------------------------------- + +U32 AccumulationVolume::packUpdate( NetConnection *connection, U32 mask, BitStream *stream ) +{ + U32 retMask = Parent::packUpdate( connection, mask, stream ); + + if (stream->writeFlag(mask & InitialUpdateMask)) + { + stream->write( mTextureName ); + } + + return retMask; +} + +void AccumulationVolume::unpackUpdate( NetConnection *connection, BitStream *stream ) +{ + Parent::unpackUpdate( connection, stream ); + + if (stream->readFlag()) + { + stream->read( &mTextureName ); + setTexture(mTextureName); + } +} + +//----------------------------------------------------------------------------- + +void AccumulationVolume::inspectPostApply() +{ + Parent::inspectPostApply(); + setMaskBits(U32(-1) ); +} + +void AccumulationVolume::setTexture( const String& name ) +{ + mTextureName = name; + if ( isClientObject() && mTextureName.isNotEmpty() ) + { + mAccuTexture.set(mTextureName, &GFXDefaultStaticDiffuseProfile, "AccumulationVolume::mAccuTexture"); + if ( mAccuTexture.isNull() ) + Con::warnf( "AccumulationVolume::setTexture - Unable to load texture: %s", mTextureName.c_str() ); + } + refreshVolumes(); +} + +//----------------------------------------------------------------------------- +// Static Functions +//----------------------------------------------------------------------------- +bool AccumulationVolume::_setTexture( void *object, const char *index, const char *data ) +{ + AccumulationVolume* volume = reinterpret_cast< AccumulationVolume* >( object ); + volume->setTexture( data ); + return false; +} + +void AccumulationVolume::refreshVolumes() +{ + // This function tests each accumulation object to + // see if it's within the bounds of an accumulation + // volume. If so, it will pass on the accumulation + // texture of the volume to the object. + + // This function should only be called when something + // global like change of volume or material occurs. + + // Clear old data. + for (S32 n = 0; n < smAccuObjects.size(); ++n) + { + SimObjectPtr object = smAccuObjects[n]; + if ( object.isValid() ) + object->mAccuTex = GFXTexHandle::ZERO; + } + + // + for (S32 i = 0; i < smAccuVolumes.size(); ++i) + { + SimObjectPtr volume = smAccuVolumes[i]; + if ( volume.isNull() ) continue; + + for (S32 n = 0; n < smAccuObjects.size(); ++n) + { + SimObjectPtr object = smAccuObjects[n]; + if ( object.isNull() ) continue; + + if ( volume->containsPoint(object->getPosition()) ) + object->mAccuTex = volume->mAccuTexture; + } + } +} + +// Accumulation Object Management. +void AccumulationVolume::addObject(SimObjectPtr object) +{ + smAccuObjects.push_back(object); + refreshVolumes(); +} + +void AccumulationVolume::removeObject(SimObjectPtr object) +{ + smAccuObjects.remove(object); + refreshVolumes(); +} + +void AccumulationVolume::updateObject(SceneObject* object) +{ + // This function is called when an individual object + // has been moved. Tests to see if it's in any of the + // accumulation volumes. + + // We use ZERO instead of NULL so the accumulation + // texture will be updated in renderMeshMgr. + object->mAccuTex = GFXTexHandle::ZERO; + + for (S32 i = 0; i < smAccuVolumes.size(); ++i) + { + SimObjectPtr volume = smAccuVolumes[i]; + if ( volume.isNull() ) continue; + + if ( volume->containsPoint(object->getPosition()) ) + object->mAccuTex = volume->mAccuTexture; + } +} \ No newline at end of file diff --git a/Engine/source/T3D/accumulationVolume.h b/Engine/source/T3D/accumulationVolume.h new file mode 100644 index 000000000..eb9bce059 --- /dev/null +++ b/Engine/source/T3D/accumulationVolume.h @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#ifndef _ACCUMULATIONVOLUME_H_ +#define _ACCUMULATIONVOLUME_H_ + +#ifndef _SCENEPOLYHEDRALSPACE_H_ +#include "scene/scenePolyhedralSpace.h" +#endif + +#ifndef _MSILHOUETTEEXTRACTOR_H_ +#include "math/mSilhouetteExtractor.h" +#endif + +#ifndef _GFXDEVICE_H_ +#include "gfx/gfxDevice.h" +#endif + +/// A volume in space that blocks visibility. +class AccumulationVolume : public ScenePolyhedralSpace +{ + public: + + typedef ScenePolyhedralSpace Parent; + + protected: + + typedef SilhouetteExtractorPerspective< PolyhedronType > SilhouetteExtractorType; + + /// Whether the volume's transform has changed and we need to recompute + /// transform-based data. + bool mTransformDirty; + + /// World-space points of the volume's polyhedron. + Vector< Point3F > mWSPoints; + + /// Silhouette extractor when using perspective projections. + SilhouetteExtractorType mSilhouetteExtractor; + + mutable Vector< SceneObject* > mVolumeQueryList; + + // Name (path) of the accumulation texture. + String mTextureName; + + // SceneSpace. + virtual void _renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat ); + + public: + + GFXTexHandle mAccuTexture; + + AccumulationVolume(); + ~AccumulationVolume(); + + // SimObject. + DECLARE_CONOBJECT( AccumulationVolume ); + DECLARE_DESCRIPTION( "Allows objects in an area to have accumulation effect applied." ); + DECLARE_CATEGORY( "3D Scene" ); + + virtual bool onAdd(); + virtual void onRemove(); + void inspectPostApply(); + void setTexture( const String& name ); + + // Static Functions. + static void consoleInit(); + static void initPersistFields(); + static Vector< SimObjectPtr > smAccuObjects; + static Vector< SimObjectPtr > smAccuVolumes; + static void addObject(SimObjectPtr object); + static void removeObject(SimObjectPtr object); + static void refreshVolumes(); + static bool _setTexture( void *object, const char *index, const char *data ); + static void updateObject(SceneObject* object); + + // Network + U32 packUpdate( NetConnection *, U32 mask, BitStream *stream ); + void unpackUpdate( NetConnection *, BitStream *stream ); + + // SceneObject. + virtual void buildSilhouette( const SceneCameraState& cameraState, Vector< Point3F >& outPoints ); + virtual void setTransform( const MatrixF& mat ); +}; + +#endif // !_AccumulationVolume_H_ diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 9c0dfbbe4..d1e68a2c2 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -48,6 +48,7 @@ #include "materials/materialFeatureData.h" #include "materials/materialFeatureTypes.h" #include "console/engineAPI.h" +#include "T3D/accumulationVolume.h" using namespace Torque; @@ -293,6 +294,13 @@ bool TSStatic::onAdd() _updateShouldTick(); + // Accumulation + if ( isClientObject() && mShapeInstance ) + { + if ( mShapeInstance->hasAccumulation() ) + AccumulationVolume::addObject(this); + } + return true; } @@ -403,6 +411,13 @@ void TSStatic::onRemove() { SAFE_DELETE( mPhysicsRep ); + // Accumulation + if ( isClientObject() && mShapeInstance ) + { + if ( mShapeInstance->hasAccumulation() ) + AccumulationVolume::removeObject(this); + } + mConvexList->nukeList(); removeFromScene(); @@ -562,6 +577,9 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); + // Acculumation + rdata.setAccuTex(mAccuTex); + // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; @@ -649,6 +667,13 @@ void TSStatic::setTransform(const MatrixF & mat) if ( mPhysicsRep ) mPhysicsRep->setTransform( mat ); + // Accumulation + if ( isClientObject() && mShapeInstance ) + { + if ( mShapeInstance->hasAccumulation() ) + AccumulationVolume::updateObject(this); + } + // Since this is a static it's render transform changes 1 // to 1 with it's collision transform... no interpolation. setRenderTransform(mat); diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp index 010da5eeb..d1655ae60 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp @@ -330,6 +330,58 @@ void DeferredBumpFeatGLSL::processPix( Vector &componentList, output = meta; return; } + + else if (fd.features[MFT_AccuMap]) + { + Var *bumpSample = (Var *)LangElement::find("bumpSample"); + if (bumpSample == NULL) + { + MultiLine *meta = new MultiLine; + + Var *texCoord = getInTexCoord("texCoord", "vec2", true, componentList); + + Var *bumpMap = getNormalMapTex(); + + bumpSample = new Var; + bumpSample->setType("vec4"); + bumpSample->setName("bumpSample"); + LangElement *bumpSampleDecl = new DecOp(bumpSample); + + meta->addStatement(new GenOp(" @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord)); + + if (fd.features.hasFeature(MFT_DetailNormalMap)) + { + Var *bumpMap = (Var*)LangElement::find("detailBumpMap"); + if (!bumpMap) { + bumpMap = new Var; + bumpMap->setType("sampler2D"); + bumpMap->setName("detailBumpMap"); + bumpMap->uniform = true; + bumpMap->sampler = true; + bumpMap->constNum = Var::getTexUnitNum(); + } + + texCoord = getInTexCoord("detCoord", "vec2", true, componentList); + LangElement *texOp = new GenOp("tex2D(@, @)", bumpMap, texCoord); + + Var *detailBump = new Var; + detailBump->setName("detailBump"); + detailBump->setType("vec4"); + meta->addStatement(expandNormalMap(texOp, new DecOp(detailBump), detailBump, fd)); + + Var *detailBumpScale = new Var; + detailBumpScale->setType("float"); + detailBumpScale->setName("detailBumpStrength"); + detailBumpScale->uniform = true; + detailBumpScale->constSortPos = cspPass; + meta->addStatement(new GenOp(" @.xy += @.xy * @;\r\n", bumpSample, detailBump, detailBumpScale)); + } + + output = meta; + + return; + } + } else if ( fd.materialFeatures[MFT_NormalsOut] || fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) @@ -398,7 +450,20 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat, return; } - if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] && + if (!fd.features[MFT_PrePassConditioner] && fd.features[MFT_AccuMap]) + { + passData.mTexType[texIndex] = Material::Bump; + passData.mSamplerNames[texIndex] = "bumpMap"; + passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_NormalMap); + + if (fd.features.hasFeature(MFT_DetailNormalMap)) + { + passData.mTexType[texIndex] = Material::DetailBump; + passData.mSamplerNames[texIndex] = "detailBumpMap"; + passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_DetailNormalMap); + } + } + else if (!fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] && ( fd.features[MFT_PrePassConditioner] || fd.features[MFT_PixSpecular] ) ) { @@ -481,6 +546,14 @@ void DeferredPixelSpecularGLSL::processPix( Vector &component AssertFatal( lightInfoSamp && d_specular && d_NL_Att, "DeferredPixelSpecularGLSL::processPix - Something hosed the deferred features!" ); + if (fd.features[MFT_AccuMap]) { + // change specularity where the accu texture is applied + Var *accuPlc = (Var*)LangElement::find("plc"); + Var *accuSpecular = (Var*)LangElement::find("accuSpecular"); + if (accuPlc != NULL && accuSpecular != NULL) + //d_specular = clamp(lerp( d_specular, accuSpecular * d_specular, plc.a), 0, 1) + meta->addStatement(new GenOp(" @ = clamp( lerp( @, @ * @, @.a), 0, 1);\r\n", d_specular, d_specular, accuSpecular, d_specular, accuPlc)); + } // (a^m)^n = a^(m*n) meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", specDecl, d_specular, specPow, specStrength ) ); diff --git a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp index d948e6075..6a646a71e 100644 --- a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp @@ -330,6 +330,57 @@ void DeferredBumpFeatHLSL::processPix( Vector &componentList, output = meta; return; } + else if (fd.features[MFT_AccuMap]) + { + Var *bumpSample = (Var *)LangElement::find( "bumpSample" ); + if( bumpSample == NULL ) + { + MultiLine *meta = new MultiLine; + + Var *texCoord = getInTexCoord( "texCoord", "float2", true, componentList ); + + Var *bumpMap = getNormalMapTex(); + + bumpSample = new Var; + bumpSample->setType( "float4" ); + bumpSample->setName( "bumpSample" ); + LangElement *bumpSampleDecl = new DecOp( bumpSample ); + + meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord ) ); + + if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + Var *bumpMap = (Var*)LangElement::find( "detailBumpMap" ); + if ( !bumpMap ) { + bumpMap = new Var; + bumpMap->setType( "sampler2D" ); + bumpMap->setName( "detailBumpMap" ); + bumpMap->uniform = true; + bumpMap->sampler = true; + bumpMap->constNum = Var::getTexUnitNum(); + } + + texCoord = getInTexCoord( "detCoord", "float2", true, componentList ); + LangElement *texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); + + Var *detailBump = new Var; + detailBump->setName( "detailBump" ); + detailBump->setType( "float4" ); + meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) ); + + Var *detailBumpScale = new Var; + detailBumpScale->setType( "float" ); + detailBumpScale->setName( "detailBumpStrength" ); + detailBumpScale->uniform = true; + detailBumpScale->constSortPos = cspPass; + meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpSample, detailBump, detailBumpScale ) ); + } + + output = meta; + + return; + } + } else if ( fd.materialFeatures[MFT_NormalsOut] || fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] ) @@ -398,7 +449,20 @@ void DeferredBumpFeatHLSL::setTexData( Material::StageData &stageDat, return; } - if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] && + if ( !fd.features[MFT_PrePassConditioner] && fd.features[MFT_AccuMap] ) + { + passData.mTexType[ texIndex ] = Material::Bump; + passData.mSamplerNames[ texIndex ] = "bumpMap"; + passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); + + if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) + { + passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[texIndex] = "detailBumpMap"; + passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); + } + } + else if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] && ( fd.features[MFT_PrePassConditioner] || fd.features[MFT_PixSpecular] ) ) { @@ -481,6 +545,15 @@ void DeferredPixelSpecularHLSL::processPix( Vector &component AssertFatal( lightInfoSamp && d_specular && d_NL_Att, "DeferredPixelSpecularHLSL::processPix - Something hosed the deferred features!" ); + if (fd.features[ MFT_AccuMap ]) { + // change specularity where the accu texture is applied + Var *accuPlc = (Var*) LangElement::find( "plc" ); + Var *accuSpecular = (Var*)LangElement::find( "accuSpecular" ); + if(accuPlc != NULL && accuSpecular != NULL) + //d_specular = clamp(lerp( d_specular, accuSpecular * d_specular, plc.a), 0, 1) + meta->addStatement( new GenOp( " @ = clamp( lerp( @, @ * @, @.a), 0, 1);\r\n", d_specular, d_specular, accuSpecular, d_specular, accuPlc ) ); + } + // (a^m)^n = a^(m*n) meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n", specDecl, d_specular, specPow, specStrength ) ); diff --git a/Engine/source/materials/baseMatInstance.h b/Engine/source/materials/baseMatInstance.h index d15c9525c..4edd22664 100644 --- a/Engine/source/materials/baseMatInstance.h +++ b/Engine/source/materials/baseMatInstance.h @@ -185,6 +185,7 @@ public: // BTRTODO: This stuff below should probably not be in BaseMatInstance virtual bool hasGlow() = 0; + virtual bool hasAccumulation() = 0; virtual U32 getCurPass() = 0; diff --git a/Engine/source/materials/matInstance.cpp b/Engine/source/materials/matInstance.cpp index a61b75bf7..2bb8e52ed 100644 --- a/Engine/source/materials/matInstance.cpp +++ b/Engine/source/materials/matInstance.cpp @@ -497,6 +497,14 @@ bool MatInstance::hasGlow() return false; } +bool MatInstance::hasAccumulation() +{ + if( mProcessedMaterial ) + return mProcessedMaterial->hasAccumulation(); + else + return false; +} + const FeatureSet& MatInstance::getFeatures() const { return mProcessedMaterial->getFeatures(); diff --git a/Engine/source/materials/matInstance.h b/Engine/source/materials/matInstance.h index 3170f45f1..290385242 100644 --- a/Engine/source/materials/matInstance.h +++ b/Engine/source/materials/matInstance.h @@ -75,6 +75,7 @@ public: virtual SimObject* getUserObject() const { return mUserObject; } virtual Material *getMaterial() { return mMaterial; } virtual bool hasGlow(); + virtual bool hasAccumulation(); virtual U32 getCurPass() { return getMax( mCurPass, 0 ); } virtual U32 getCurStageNum(); virtual RenderPassData *getPass(U32 pass); diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index e654a3700..a47ac3a77 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -34,6 +34,7 @@ #include "sfx/sfxTrack.h" #include "sfx/sfxTypes.h" #include "core/util/safeDelete.h" +#include "T3D/accumulationVolume.h" IMPLEMENT_CONOBJECT( Material ); @@ -119,6 +120,13 @@ Material::Material() mSpecularStrength[i] = 1.0f; mPixelSpecular[i] = false; + mAccuEnabled[i] = false; + mAccuScale[i] = 1.0f; + mAccuDirection[i] = 1.0f; + mAccuStrength[i] = 0.6f; + mAccuCoverage[i] = 0.9f; + mAccuSpecular[i] = 16.0f; + mParallaxScale[i] = 0.0f; mVertLit[i] = false; @@ -250,6 +258,24 @@ void Material::initPersistFields() "normal map texture. Note that if pixel specular is enabled the DXTnm format will not " "work with your normal map, unless you are also using a specular map." ); + addProtectedField( "accuEnabled", TYPEID< bool >(), Offset( mAccuEnabled, Material ), + &_setAccuEnabled, &defaultProtectedGetFn, MAX_STAGES, "Accumulation texture." ); + + addField("accuScale", TypeF32, Offset(mAccuScale, Material), MAX_STAGES, + "The scale that is applied to the accu map texture. You can use this to fit the texture to smaller or larger objects."); + + addField("accuDirection", TypeF32, Offset(mAccuDirection, Material), MAX_STAGES, + "The direction of the accumulation. Chose whether you want the accu map to go from top to bottom (ie. snow) or upwards (ie. mold)."); + + addField("accuStrength", TypeF32, Offset(mAccuStrength, Material), MAX_STAGES, + "The strength of the accu map. This changes the transparency of the accu map texture. Make it subtle or add more contrast."); + + addField("accuCoverage", TypeF32, Offset(mAccuCoverage, Material), MAX_STAGES, + "The coverage ratio of the accu map texture. Use this to make the entire shape pick up some of the accu map texture or none at all."); + + addField("accuSpecular", TypeF32, Offset(mAccuSpecular, Material), MAX_STAGES, + "Changes specularity to this value where the accumulated material is present."); + addField( "specularMap", TypeImageFilename, Offset(mSpecularMapFilename, Material), MAX_STAGES, "The specular map texture. The RGB channels of this texture provide a per-pixel replacement for the 'specular' parameter on the material. " "If this texture contains alpha information, the alpha channel of the texture will be used as the gloss map. " @@ -669,4 +695,18 @@ ConsoleMethod( Material, setAutoGenerated, void, 3, 3, "setAutoGenerated(bool isAutoGenerated): Set whether or not the Material is autogenerated." ) { object->setAutoGenerated(dAtob(argv[2])); +} + +// Accumulation +bool Material::_setAccuEnabled( void *object, const char *index, const char *data ) +{ + Material* mat = reinterpret_cast< Material* >( object ); + + if ( index ) + { + U32 i = dAtoui(index); + mat->mAccuEnabled[i] = dAtob(data); + AccumulationVolume::refreshVolumes(); + } + return true; } \ No newline at end of file diff --git a/Engine/source/materials/materialDefinition.h b/Engine/source/materials/materialDefinition.h index b526bcb06..aae922d94 100644 --- a/Engine/source/materials/materialDefinition.h +++ b/Engine/source/materials/materialDefinition.h @@ -88,6 +88,7 @@ public: DynamicLightMask, NormalizeCube, TexTarget, + AccuMap, }; enum BlendOp @@ -198,6 +199,12 @@ public: // Data //----------------------------------------------------------------------- FileName mDiffuseMapFilename[MAX_STAGES]; + bool mAccuEnabled[MAX_STAGES]; + F32 mAccuScale[MAX_STAGES]; + F32 mAccuDirection[MAX_STAGES]; + F32 mAccuStrength[MAX_STAGES]; + F32 mAccuCoverage[MAX_STAGES]; + F32 mAccuSpecular[MAX_STAGES]; FileName mOverlayMapFilename[MAX_STAGES]; FileName mLightMapFilename[MAX_STAGES]; FileName mToneMapFilename[MAX_STAGES]; @@ -371,6 +378,9 @@ public: // static void initPersistFields(); + // Accumulation + static bool _setAccuEnabled( void *object, const char *index, const char *data ); + DECLARE_CONOBJECT(Material); protected: diff --git a/Engine/source/materials/materialFeatureTypes.cpp b/Engine/source/materials/materialFeatureTypes.cpp index afea9efc5..f7a63815b 100644 --- a/Engine/source/materials/materialFeatureTypes.cpp +++ b/Engine/source/materials/materialFeatureTypes.cpp @@ -32,6 +32,12 @@ ImplementFeatureType( MFT_TexAnim, MFG_PreTexture, 1.0f, true ); ImplementFeatureType( MFT_Parallax, MFG_PreTexture, 2.0f, true ); ImplementFeatureType( MFT_DiffuseVertColor, MFG_PreTexture, 3.0f, true ); +ImplementFeatureType( MFT_AccuScale, MFG_PreTexture, 4.0f, true ); +ImplementFeatureType( MFT_AccuDirection, MFG_PreTexture, 4.0f, true ); +ImplementFeatureType( MFT_AccuStrength, MFG_PreTexture, 4.0f, true ); +ImplementFeatureType( MFT_AccuCoverage, MFG_PreTexture, 4.0f, true ); +ImplementFeatureType( MFT_AccuSpecular, MFG_PreTexture, 4.0f, true ); + ImplementFeatureType( MFT_DiffuseMap, MFG_Texture, 2.0f, true ); ImplementFeatureType( MFT_OverlayMap, MFG_Texture, 3.0f, true ); ImplementFeatureType( MFT_DetailMap, MFG_Texture, 4.0f, true ); @@ -41,6 +47,8 @@ ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true ); ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true ); ImplementFeatureType( MFT_DetailNormalMap, MFG_Texture, 10.0f, true ); +ImplementFeatureType( MFT_AccuMap, MFG_PreLighting, 2.0f, true ); + ImplementFeatureType( MFT_RTLighting, MFG_Lighting, 2.0f, true ); ImplementFeatureType( MFT_SubSurface, MFG_Lighting, 3.0f, true ); ImplementFeatureType( MFT_LightMap, MFG_Lighting, 4.0f, true ); diff --git a/Engine/source/materials/materialFeatureTypes.h b/Engine/source/materials/materialFeatureTypes.h index 8ae552317..55b52506c 100644 --- a/Engine/source/materials/materialFeatureTypes.h +++ b/Engine/source/materials/materialFeatureTypes.h @@ -95,6 +95,13 @@ DeclareFeatureType( MFT_DetailMap ); DeclareFeatureType( MFT_DiffuseColor ); DeclareFeatureType( MFT_DetailNormalMap ); +DeclareFeatureType( MFT_AccuMap ); +DeclareFeatureType( MFT_AccuScale ); +DeclareFeatureType( MFT_AccuDirection ); +DeclareFeatureType( MFT_AccuStrength ); +DeclareFeatureType( MFT_AccuCoverage ); +DeclareFeatureType( MFT_AccuSpecular ); + /// This feature enables vertex coloring for the diffuse channel. DeclareFeatureType( MFT_DiffuseVertColor ); diff --git a/Engine/source/materials/processedCustomMaterial.cpp b/Engine/source/materials/processedCustomMaterial.cpp index 7c225362f..f2fd7678c 100644 --- a/Engine/source/materials/processedCustomMaterial.cpp +++ b/Engine/source/materials/processedCustomMaterial.cpp @@ -49,6 +49,7 @@ ProcessedCustomMaterial::ProcessedCustomMaterial(Material &mat) mCustomMaterial = static_cast(mMaterial); mHasSetStageData = false; mHasGlow = false; + mHasAccumulation = false; mMaxStages = 0; mMaxTex = 0; } diff --git a/Engine/source/materials/processedFFMaterial.cpp b/Engine/source/materials/processedFFMaterial.cpp index 1a1a4f9e5..46065bca1 100644 --- a/Engine/source/materials/processedFFMaterial.cpp +++ b/Engine/source/materials/processedFFMaterial.cpp @@ -67,6 +67,7 @@ void ProcessedFFMaterial::_construct() { mHasSetStageData = false; mHasGlow = false; + mHasAccumulation = false; mIsLightingMaterial = false; mDefaultHandle = new FFMaterialParameterHandle(); mDefaultParameters = new MaterialParameters(); diff --git a/Engine/source/materials/processedMaterial.cpp b/Engine/source/materials/processedMaterial.cpp index 80a5c9040..10181179e 100644 --- a/Engine/source/materials/processedMaterial.cpp +++ b/Engine/source/materials/processedMaterial.cpp @@ -93,6 +93,7 @@ ProcessedMaterial::ProcessedMaterial() mCurrentParams( NULL ), mHasSetStageData( false ), mHasGlow( false ), + mHasAccumulation( false ), mMaxStages( 0 ), mVertexFormat( NULL ), mUserObject( NULL ) diff --git a/Engine/source/materials/processedMaterial.h b/Engine/source/materials/processedMaterial.h index b72422cf9..5fb4075a5 100644 --- a/Engine/source/materials/processedMaterial.h +++ b/Engine/source/materials/processedMaterial.h @@ -197,6 +197,9 @@ public: /// Returns true if any pass glows bool hasGlow() const { return mHasGlow; } + /// Returns true if any pass accumulates + bool hasAccumulation() const { return mHasAccumulation; } + /// Gets the stage number for a pass U32 getStageFromPass(U32 pass) const { @@ -244,6 +247,9 @@ protected: /// If we glow bool mHasGlow; + /// If we have accumulation. + bool mHasAccumulation; + /// Number of stages (not to be confused with number of passes) U32 mMaxStages; diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index 723129404..ba7f29d61 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -55,6 +55,11 @@ void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/ mSpecularColorSC = shader->getShaderConstHandle(ShaderGenVars::specularColor); mSpecularPowerSC = shader->getShaderConstHandle(ShaderGenVars::specularPower); mSpecularStrengthSC = shader->getShaderConstHandle(ShaderGenVars::specularStrength); + mAccuScaleSC = shader->getShaderConstHandle("$accuScale"); + mAccuDirectionSC = shader->getShaderConstHandle("$accuDirection"); + mAccuStrengthSC = shader->getShaderConstHandle("$accuStrength"); + mAccuCoverageSC = shader->getShaderConstHandle("$accuCoverage"); + mAccuSpecularSC = shader->getShaderConstHandle("$accuSpecular"); mParallaxInfoSC = shader->getShaderConstHandle("$parallaxInfo"); mFogDataSC = shader->getShaderConstHandle(ShaderGenVars::fogData); mFogColorSC = shader->getShaderConstHandle(ShaderGenVars::fogColor); @@ -423,6 +428,34 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, fd.features.addFeature( MFT_GlossMap ); } + if ( mMaterial->mAccuEnabled[stageNum] ) + { + fd.features.addFeature( MFT_AccuMap ); + mHasAccumulation = true; + } + + // we need both diffuse and normal maps + sm3 to have an accu map + if( fd.features[ MFT_AccuMap ] && + ( !fd.features[ MFT_DiffuseMap ] || + !fd.features[ MFT_NormalMap ] || + GFX->getPixelShaderVersion() < 3.0f ) ) { + AssertWarn(false, "SAHARA: Using an Accu Map requires SM 3.0 and a normal map."); + fd.features.removeFeature( MFT_AccuMap ); + mHasAccumulation = false; + } + + // if we still have the AccuMap feature, we add all accu constant features + if ( fd.features[ MFT_AccuMap ] ) { + // add the dependencies of the accu map + fd.features.addFeature( MFT_AccuScale ); + fd.features.addFeature( MFT_AccuDirection ); + fd.features.addFeature( MFT_AccuStrength ); + fd.features.addFeature( MFT_AccuCoverage ); + fd.features.addFeature( MFT_AccuSpecular ); + // now remove some features that are not compatible with this + fd.features.removeFeature( MFT_UseInstancing ); + } + // Without a base texture use the diffuse color // feature to ensure some sort of output. if (!fd.features[MFT_DiffuseMap]) @@ -809,6 +842,13 @@ void ProcessedShaderMaterial::setTextureStages( SceneRenderState *state, const S case Material::BackBuff: GFX->setTexture( i, sgData.backBuffTex ); break; + + case Material::AccuMap: + if ( sgData.accuTex ) + GFX->setTexture( i, sgData.accuTex ); + else + GFX->setTexture( i, GFXTexHandle::ZERO ); + break; case Material::TexTarget: { @@ -1137,6 +1177,17 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons 0.0f, 0.0f ); // TODO: Wrap mode flags? shaderConsts->setSafe(handles->mBumpAtlasTileSC, atlasTileParams); } + + if( handles->mAccuScaleSC->isValid() ) + shaderConsts->set( handles->mAccuScaleSC, mMaterial->mAccuScale[stageNum] ); + if( handles->mAccuDirectionSC->isValid() ) + shaderConsts->set( handles->mAccuDirectionSC, mMaterial->mAccuDirection[stageNum] ); + if( handles->mAccuStrengthSC->isValid() ) + shaderConsts->set( handles->mAccuStrengthSC, mMaterial->mAccuStrength[stageNum] ); + if( handles->mAccuCoverageSC->isValid() ) + shaderConsts->set( handles->mAccuCoverageSC, mMaterial->mAccuCoverage[stageNum] ); + if( handles->mAccuSpecularSC->isValid() ) + shaderConsts->set( handles->mAccuSpecularSC, mMaterial->mAccuSpecular[stageNum] ); } bool ProcessedShaderMaterial::_hasCubemap(U32 pass) diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index a39e8df75..dc5dbf872 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/Engine/source/materials/processedShaderMaterial.h @@ -48,6 +48,11 @@ public: GFXShaderConstHandle* mSpecularPowerSC; GFXShaderConstHandle* mSpecularStrengthSC; GFXShaderConstHandle* mParallaxInfoSC; + GFXShaderConstHandle* mAccuScaleSC; + GFXShaderConstHandle* mAccuDirectionSC; + GFXShaderConstHandle* mAccuStrengthSC; + GFXShaderConstHandle* mAccuCoverageSC; + GFXShaderConstHandle* mAccuSpecularSC; GFXShaderConstHandle* mFogDataSC; GFXShaderConstHandle* mFogColorSC; GFXShaderConstHandle* mDetailScaleSC; diff --git a/Engine/source/materials/sceneData.h b/Engine/source/materials/sceneData.h index bd719209e..dd9299121 100644 --- a/Engine/source/materials/sceneData.h +++ b/Engine/source/materials/sceneData.h @@ -64,6 +64,7 @@ struct SceneData GFXTextureObject *backBuffTex; GFXTextureObject *reflectTex; GFXTextureObject *miscTex; + GFXTextureObject *accuTex; /// The current lights to use in rendering /// in order of the light importance. diff --git a/Engine/source/renderInstance/renderBinManager.cpp b/Engine/source/renderInstance/renderBinManager.cpp index df41b634c..8ebe69334 100644 --- a/Engine/source/renderInstance/renderBinManager.cpp +++ b/Engine/source/renderInstance/renderBinManager.cpp @@ -164,6 +164,7 @@ void RenderBinManager::setupSGData( MeshRenderInst *ri, SceneData &data ) data.cubemap = ri->cubemap; data.miscTex = ri->miscTex; data.reflectTex = ri->reflectTex; + data.accuTex = ri->accuTex; data.lightmap = ri->lightmap; data.visibility = ri->visibility; data.materialHint = ri->materialHint; diff --git a/Engine/source/renderInstance/renderMeshMgr.cpp b/Engine/source/renderInstance/renderMeshMgr.cpp index 0689a23d5..67114329d 100644 --- a/Engine/source/renderInstance/renderMeshMgr.cpp +++ b/Engine/source/renderInstance/renderMeshMgr.cpp @@ -115,6 +115,7 @@ void RenderMeshMgr::render(SceneRenderState * state) GFXCubemap *lastCubemap = NULL; GFXTextureObject *lastReflectTex = NULL; GFXTextureObject *lastMiscTex = NULL; + GFXTextureObject *lastAccuTex = NULL; SceneData sgData; sgData.init( state ); @@ -225,6 +226,15 @@ void RenderMeshMgr::render(SceneRenderState * state) dirty = true; } + // Update accumulation texture if it changed. + // Note: accumulation texture can be NULL, and must be updated. + if ( passRI->accuTex != lastAccuTex ) + { + sgData.accuTex = passRI->accuTex; + lastAccuTex = lastAccuTex; + dirty = true; + } + if ( dirty ) mat->setTextureStages( state, sgData ); diff --git a/Engine/source/renderInstance/renderPassManager.h b/Engine/source/renderInstance/renderPassManager.h index b13a7adba..b7f72b06c 100644 --- a/Engine/source/renderInstance/renderPassManager.h +++ b/Engine/source/renderInstance/renderPassManager.h @@ -366,6 +366,7 @@ struct MeshRenderInst : public RenderInst GFXTextureObject *backBuffTex; GFXTextureObject *reflectTex; GFXTextureObject *miscTex; + GFXTextureObject *accuTex; GFXCubemap *cubemap; void clear(); diff --git a/Engine/source/scene/sceneObject.cpp b/Engine/source/scene/sceneObject.cpp index 7fb3cc0c0..80e2ba338 100644 --- a/Engine/source/scene/sceneObject.cpp +++ b/Engine/source/scene/sceneObject.cpp @@ -43,6 +43,7 @@ #include "math/mTransform.h" #include "T3D/gameBase/gameProcess.h" #include "T3D/gameBase/gameConnection.h" +#include "T3D/accumulationVolume.h" IMPLEMENT_CONOBJECT(SceneObject); @@ -141,6 +142,8 @@ SceneObject::SceneObject() mObjectFlags.set( RenderEnabledFlag | SelectionEnabledFlag ); mIsScopeAlways = false; + + mAccuTex = NULL; } //----------------------------------------------------------------------------- @@ -152,6 +155,7 @@ SceneObject::~SceneObject() AssertFatal( !mSceneObjectLinks, "SceneObject::~SceneObject() - object is still linked to SceneTrackers" ); + mAccuTex = NULL; unlink(); } diff --git a/Engine/source/scene/sceneObject.h b/Engine/source/scene/sceneObject.h index cf682f1bf..42c3c53ed 100644 --- a/Engine/source/scene/sceneObject.h +++ b/Engine/source/scene/sceneObject.h @@ -51,6 +51,10 @@ #include "scene/sceneContainer.h" #endif +#ifndef _GFXDEVICE_H_ +#include "gfx/gfxDevice.h" +#endif + class SceneManager; class SceneRenderState; @@ -765,8 +769,14 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce static bool _setFieldRotation( void *object, const char *index, const char *data ); static bool _setFieldScale( void *object, const char *index, const char *data ); static bool _setMountPID( void* object, const char* index, const char* data ); + static bool _setAccuEnabled( void *object, const char *index, const char *data ); /// @} + + // Accumulation Texture + // Note: This was placed in SceneObject to both ShapeBase and TSStatic could support it. + public: + GFXTextureObject* mAccuTex; }; #endif // _SCENEOBJECT_H_ diff --git a/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp new file mode 100644 index 000000000..c663b93ea --- /dev/null +++ b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.cpp @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------- +// 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 "shaderGen/GLSL/accuFeatureGLSL.h" +#include "shaderGen/shaderFeature.h" +#include "shaderGen/shaderOp.h" +#include "shaderGen/featureMgr.h" +#include "materials/materialFeatureTypes.h" +#include "gfx/gfxDevice.h" +#include "materials/processedMaterial.h" + +//**************************************************************************** +// Accu Texture +//**************************************************************************** +void AccuTexFeatGLSL::processVert(Vector &componentList, + const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + getOutTexCoord( "texCoord", + "vec2", + true, + false, + meta, + componentList ); + + getOutObjToTangentSpace( componentList, meta, fd ); + addOutAccuVec( componentList, meta ); + + output = meta; +} + +void AccuTexFeatGLSL::processPix(Vector &componentList, + const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + + output = meta; + + // OUT.col + Var *color = (Var*) LangElement::find( "col" ); + if (!color) + { + output = new GenOp(" //NULL COLOR!"); + return; + } + + // accu map + Var *accuMap = new Var; + accuMap->setType( "sampler2D" ); + accuMap->setName( "accuMap" ); + accuMap->uniform = true; + accuMap->sampler = true; + accuMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + // accuColor var + Var *accuColor = new Var; + accuColor->setType( "vec4" ); + accuColor->setName( "accuColor" ); + LangElement *colorAccuDecl = new DecOp( accuColor ); + + // plc (placement) + Var *accuPlc = new Var; + accuPlc->setType( "vec4" ); + accuPlc->setName( "plc" ); + LangElement *plcAccu = new DecOp( accuPlc ); + + // accu constants + Var *accuScale = (Var*)LangElement::find( "accuScale" ); + if ( !accuScale ) { + accuScale = new Var; + accuScale->setType( "float" ); + accuScale->setName( "accuScale" ); + accuScale->uniform = true; + accuScale->sampler = false; + accuScale->constSortPos = cspPotentialPrimitive; + } + Var *accuDirection = (Var*)LangElement::find( "accuDirection" ); + if ( !accuDirection ) { + accuDirection = new Var; + accuDirection->setType( "float" ); + accuDirection->setName( "accuDirection" ); + accuDirection->uniform = true; + accuDirection->sampler = false; + accuDirection->constSortPos = cspPotentialPrimitive; + } + Var *accuStrength = (Var*)LangElement::find( "accuStrength" ); + if ( !accuStrength ) { + accuStrength = new Var; + accuStrength->setType( "float" ); + accuStrength->setName( "accuStrength" ); + accuStrength->uniform = true; + accuStrength->sampler = false; + accuStrength->constSortPos = cspPotentialPrimitive; + } + Var *accuCoverage = (Var*)LangElement::find( "accuCoverage" ); + if ( !accuCoverage ) { + accuCoverage = new Var; + accuCoverage->setType( "float" ); + accuCoverage->setName( "accuCoverage" ); + accuCoverage->uniform = true; + accuCoverage->sampler = false; + accuCoverage->constSortPos = cspPotentialPrimitive; + } + Var *accuSpecular = (Var*)LangElement::find( "accuSpecular" ); + if ( !accuSpecular ) { + accuSpecular = new Var; + accuSpecular->setType( "float" ); + accuSpecular->setName( "accuSpecular" ); + accuSpecular->uniform = true; + accuSpecular->sampler = false; + accuSpecular->constSortPos = cspPotentialPrimitive; + } + + Var *inTex = getInTexCoord( "texCoord", "vec2", true, componentList ); + Var *accuVec = getInTexCoord( "accuVec", "vec3", true, componentList ); + Var *bumpNorm = (Var *)LangElement::find( "bumpSample" ); + if( bumpNorm == NULL ) { + bumpNorm = (Var *)LangElement::find( "bumpNormal" ); + if (!bumpNorm) + { + output = new GenOp(" //NULL bumpNormal!"); + return; + } + } + + // get the accu pixel color + meta->addStatement( new GenOp( " @ = tex2D(@, @ * @);\r\n", colorAccuDecl, accuMap, inTex, accuScale ) ); + + // scale up normals + meta->addStatement( new GenOp( " @.xyz = @.xyz * 2.0 - 0.5;\r\n", bumpNorm, bumpNorm ) ); + + // assign direction + meta->addStatement( new GenOp( " @.z *= @*2.0;\r\n", accuVec, accuDirection ) ); + + // saturate based on strength + meta->addStatement( new GenOp( " @ = saturate( float4(dot( float3(@), @.xyz * pow(@, 5) ) ));\r\n", plcAccu, bumpNorm, accuVec, accuStrength ) ); + + // add coverage + meta->addStatement( new GenOp( " @.a += (2 * pow(@/2, 5)) - 0.5;\r\n", accuPlc, accuCoverage ) ); + + // clamp to a sensible value + meta->addStatement( new GenOp( " @.a = clamp(@.a, 0, 1);\r\n", accuPlc, accuPlc ) ); + + // light + Var *lightColor = (Var*) LangElement::find( "d_lightcolor" ); + if(lightColor != NULL) + meta->addStatement( new GenOp( " @ *= float4(@, 1.0);\r\n\r\n", accuColor, lightColor ) ); + + // lerp with current pixel - use the accu alpha as well + meta->addStatement( new GenOp( " @ = mix( @, @, @.a * @.a);\r\n", color, color, accuColor, accuPlc, accuColor ) ); + + // the result should always be opaque + meta->addStatement( new GenOp( " @.a = 1.0;\r\n", color ) ); +} + +void AccuTexFeatGLSL::setTexData(Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ) +{ + //GFXTextureObject *tex = stageDat.getTex( MFT_AccuMap ); + //if ( tex ) + //{ + passData.mSamplerNames[texIndex] = "accuMap"; + passData.mTexType[ texIndex++ ] = Material::AccuMap; + //passData.mTexSlot[ texIndex++ ].texObject = tex; + //} +} + + +void AccuTexFeatGLSL::getAccuVec(MultiLine *meta, LangElement *accuVec) +{ + // Get the transform to world space. + Var *objTrans = (Var*)LangElement::find( "objTrans" ); + if ( !objTrans ) + { + objTrans = new Var; + objTrans->setType( "float4x4" ); + objTrans->setName( "objTrans" ); + objTrans->uniform = true; + objTrans->constSortPos = cspPrimitive; + } + + // accu obj trans + Var *aobjTrans = new Var; + aobjTrans->setType( "float4x4" ); + aobjTrans->setName( "accuObjTrans" ); + LangElement *accuObjTransDecl = new DecOp( aobjTrans ); + + Var *outObjToTangentSpace = (Var*)LangElement::find( "objToTangentSpace" ); + + Var *tav = new Var; + tav->setType( "float4" ); + tav->setName( "tAccuVec" ); + LangElement *tavDecl = new DecOp( tav ); + + meta->addStatement( new GenOp( " @ = float4(0,0,1,0);\r\n", tavDecl ) ); + meta->addStatement( new GenOp( " @ = transpose(@);\r\n", accuObjTransDecl, objTrans ) ); + meta->addStatement( new GenOp( " @ = tMul(@, @);\r\n", tav, aobjTrans, tav ) ); + meta->addStatement( new GenOp( " @.xyz = tMul(@, @.xyz);\r\n", tav, outObjToTangentSpace, tav ) ); + meta->addStatement( new GenOp( " @.y *= -1;\r\n", tav ) ); + meta->addStatement( new GenOp( " @ = @.xyz;\r\n", accuVec, tav ) ); +} + +Var* AccuTexFeatGLSL::addOutAccuVec(Vector &componentList, MultiLine *meta) +{ + Var *outAccuVec = (Var*)LangElement::find( "accuVec" ); + if ( !outAccuVec ) + { + // Setup the connector. + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + outAccuVec = connectComp->getElement( RT_TEXCOORD ); + outAccuVec->setName( "accuVec" ); + outAccuVec->setStructName( "OUT" ); + outAccuVec->setType( "float3" ); + outAccuVec->mapsToSampler = false; + + getAccuVec( meta, outAccuVec ); + } + + return outAccuVec; +} \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/accuFeatureGLSL.h b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.h new file mode 100644 index 000000000..046f065c9 --- /dev/null +++ b/Engine/source/shaderGen/GLSL/accuFeatureGLSL.h @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#ifndef _ACCUFEATUREGLSL_H_ +#define _ACCUFEATUREGLSL_H_ + +#ifndef _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_ +#include "shaderGen/GLSL/shaderFeatureGLSL.h" +#endif +#ifndef _LANG_ELEMENT_H_ +#include "shaderGen/langElement.h" +#endif +#ifndef _GFXDEVICE_H_ +#include "gfx/gfxDevice.h" +#endif +#ifndef _FEATUREMGR_H_ +#include "shaderGen/featureMgr.h" +#endif +#ifndef _MATERIALFEATURETYPES_H_ +#include "materials/materialFeatureTypes.h" +#endif +#ifndef _MATERIALFEATUREDATA_H_ +#include "materials/materialFeatureData.h" +#endif + +/// Accu texture +class AccuTexFeatGLSL : public ShaderFeatureGLSL +{ +public: + + //**************************************************************************** + // Accu Texture + //**************************************************************************** + virtual void processVert( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + void getAccuVec( MultiLine *meta, LangElement *accuVec ); + + Var* addOutAccuVec( Vector &componentList, MultiLine *meta ); + + virtual Material::BlendOp getBlendOp(){ return Material::LerpAlpha; } + + virtual Resources getResources( const MaterialFeatureData &fd ) + { + Resources res; + res.numTex = 1; + res.numTexReg = 1; + return res; + } + + virtual void setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ); + + virtual String getName() + { + return "Accu Texture"; + } +}; + +class AccuScaleFeature : public ShaderFeatureGLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuScale = (Var *)( LangElement::find("accuScale") ); + if( accuScale == NULL ) + { + accuScale = new Var; + accuScale->setType( "float" ); + accuScale->setName( "accuScale" ); + accuScale->constSortPos = cspPotentialPrimitive; + accuScale->uniform = true; + } + } + + virtual String getName() { return "Accu Scale"; } +}; + +class AccuDirectionFeature : public ShaderFeatureGLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuDirection = (Var *)( LangElement::find("accuDirection") ); + if( accuDirection == NULL ) + { + accuDirection = new Var; + accuDirection->setType( "float" ); + accuDirection->setName( "accuDirection" ); + accuDirection->constSortPos = cspPotentialPrimitive; + accuDirection->uniform = true; + } + } + + virtual String getName() { return "Accu Direction"; } +}; + +class AccuStrengthFeature : public ShaderFeatureGLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuStrength = (Var *)( LangElement::find("accuStrength") ); + if( accuStrength == NULL ) + { + accuStrength = new Var; + accuStrength->setType( "float" ); + accuStrength->setName( "accuStrength" ); + accuStrength->constSortPos = cspPotentialPrimitive; + accuStrength->uniform = true; + } + } + + virtual String getName() { return "Accu Strength"; } +}; + +class AccuCoverageFeature : public ShaderFeatureGLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuCoverage = (Var *)( LangElement::find("accuCoverage") ); + if( accuCoverage == NULL ) + { + accuCoverage = new Var; + accuCoverage->setType( "float" ); + accuCoverage->setName( "accuCoverage" ); + accuCoverage->constSortPos = cspPotentialPrimitive; + accuCoverage->uniform = true; + } + } + + virtual String getName() { return "Accu Coverage"; } +}; + + +class AccuSpecularFeature : public ShaderFeatureGLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuSpecular = (Var *)( LangElement::find("accuSpecular") ); + if( accuSpecular == NULL ) + { + accuSpecular = new Var; + accuSpecular->setType( "float" ); + accuSpecular->setName( "accuSpecular" ); + accuSpecular->constSortPos = cspPotentialPrimitive; + accuSpecular->uniform = true; + } + } + + virtual String getName() { return "Accu Specular"; } +}; + +#endif \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp index 38b8602bf..3c4065d44 100644 --- a/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp +++ b/Engine/source/shaderGen/GLSL/shaderGenGLSLInit.cpp @@ -32,6 +32,7 @@ #include "shaderGen/GLSL/paraboloidGLSL.h" #include "materials/materialFeatureTypes.h" #include "core/module.h" +#include "shaderGen/GLSL/accuFeatureGLSL.h" static ShaderGen::ShaderGenInitDelegate sInitDelegate; @@ -62,6 +63,7 @@ void _initShaderGenGLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_CubeMap, new ReflectCubeFeatGLSL ); FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularGLSL ); FEATUREMGR->registerFeature( MFT_SpecularMap, new SpecularMapGLSL ); + FEATUREMGR->registerFeature( MFT_AccuMap, new AccuTexFeatGLSL ); FEATUREMGR->registerFeature( MFT_GlossMap, new NamedFeatureGLSL( "Gloss Map" ) ); FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureGLSL( "Translucent" ) ); FEATUREMGR->registerFeature( MFT_Visibility, new VisibilityFeatGLSL ); diff --git a/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp new file mode 100644 index 000000000..63161c258 --- /dev/null +++ b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.cpp @@ -0,0 +1,238 @@ +//----------------------------------------------------------------------------- +// 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 "shaderGen/HLSL/accuFeatureHLSL.h" +#include "shaderGen/shaderFeature.h" +#include "shaderGen/shaderOp.h" +#include "shaderGen/featureMgr.h" +#include "materials/materialFeatureTypes.h" +#include "gfx/gfxDevice.h" +#include "materials/processedMaterial.h" + +//**************************************************************************** +// Accu Texture +//**************************************************************************** +void AccuTexFeatHLSL::processVert( Vector &componentList, + const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + getOutTexCoord( "texCoord", + "float2", + true, + false, + meta, + componentList ); + + getOutObjToTangentSpace( componentList, meta, fd ); + addOutAccuVec( componentList, meta ); + + output = meta; +} + +void AccuTexFeatHLSL::processPix( Vector &componentList, + const MaterialFeatureData &fd ) +{ + MultiLine *meta = new MultiLine; + + output = meta; + + // OUT.col + Var *color = (Var*) LangElement::find( "col" ); + if (!color) + { + output = new GenOp(" //NULL COLOR!"); + return; + } + + // accu map + Var *accuMap = new Var; + accuMap->setType( "sampler2D" ); + accuMap->setName( "accuMap" ); + accuMap->uniform = true; + accuMap->sampler = true; + accuMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + // accuColor var + Var *accuColor = new Var; + accuColor->setType( "float4" ); + accuColor->setName( "accuColor" ); + LangElement *colorAccuDecl = new DecOp( accuColor ); + + // plc (placement) + Var *accuPlc = new Var; + accuPlc->setType( "float4" ); + accuPlc->setName( "plc" ); + LangElement *plcAccu = new DecOp( accuPlc ); + + // accu constants + Var *accuScale = (Var*)LangElement::find( "accuScale" ); + if ( !accuScale ) { + accuScale = new Var; + accuScale->setType( "float" ); + accuScale->setName( "accuScale" ); + accuScale->uniform = true; + accuScale->sampler = false; + accuScale->constSortPos = cspPotentialPrimitive; + } + Var *accuDirection = (Var*)LangElement::find( "accuDirection" ); + if ( !accuDirection ) { + accuDirection = new Var; + accuDirection->setType( "float" ); + accuDirection->setName( "accuDirection" ); + accuDirection->uniform = true; + accuDirection->sampler = false; + accuDirection->constSortPos = cspPotentialPrimitive; + } + Var *accuStrength = (Var*)LangElement::find( "accuStrength" ); + if ( !accuStrength ) { + accuStrength = new Var; + accuStrength->setType( "float" ); + accuStrength->setName( "accuStrength" ); + accuStrength->uniform = true; + accuStrength->sampler = false; + accuStrength->constSortPos = cspPotentialPrimitive; + } + Var *accuCoverage = (Var*)LangElement::find( "accuCoverage" ); + if ( !accuCoverage ) { + accuCoverage = new Var; + accuCoverage->setType( "float" ); + accuCoverage->setName( "accuCoverage" ); + accuCoverage->uniform = true; + accuCoverage->sampler = false; + accuCoverage->constSortPos = cspPotentialPrimitive; + } + Var *accuSpecular = (Var*)LangElement::find( "accuSpecular" ); + if ( !accuSpecular ) { + accuSpecular = new Var; + accuSpecular->setType( "float" ); + accuSpecular->setName( "accuSpecular" ); + accuSpecular->uniform = true; + accuSpecular->sampler = false; + accuSpecular->constSortPos = cspPotentialPrimitive; + } + + Var *inTex = getInTexCoord( "texCoord", "float2", true, componentList ); + Var *accuVec = getInTexCoord( "accuVec", "float3", true, componentList ); + Var *bumpNorm = (Var *)LangElement::find( "bumpSample" ); + if( bumpNorm == NULL ) { + bumpNorm = (Var *)LangElement::find( "bumpNormal" ); + if (!bumpNorm) + return; + } + + // get the accu pixel color + meta->addStatement( new GenOp( " @ = tex2D(@, @ * @);\r\n", colorAccuDecl, accuMap, inTex, accuScale ) ); + + // scale up normals + meta->addStatement( new GenOp( " @.xyz = @.xyz * 2.0 - 0.5;\r\n", bumpNorm, bumpNorm ) ); + + // assign direction + meta->addStatement( new GenOp( " @.z *= @*2.0;\r\n", accuVec, accuDirection ) ); + + // saturate based on strength + meta->addStatement( new GenOp( " @ = saturate( dot( @, @.xyz * pow(@, 5) ) );\r\n", plcAccu, bumpNorm, accuVec, accuStrength ) ); + + // add coverage + meta->addStatement( new GenOp( " @.a += (2 * pow(@/2, 5)) - 0.5;\r\n", accuPlc, accuCoverage ) ); + + // clamp to a sensible value + meta->addStatement( new GenOp( " @.a = clamp(@.a, 0, 1);\r\n", accuPlc, accuPlc ) ); + + // light + Var *lightColor = (Var*) LangElement::find( "d_lightcolor" ); + if(lightColor != NULL) + meta->addStatement( new GenOp( " @ *= float4(@, 1.0);\r\n\r\n", accuColor, lightColor ) ); + + // lerp with current pixel - use the accu alpha as well + meta->addStatement( new GenOp( " @ = lerp( @, @, @.a * @.a);\r\n", color, color, accuColor, accuPlc, accuColor ) ); + + // the result should always be opaque + meta->addStatement( new GenOp( " @.a = 1.0;\r\n", color ) ); + +} + +void AccuTexFeatHLSL::setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ) +{ + //GFXTextureObject *tex = stageDat.getTex( MFT_AccuMap ); + //if ( tex ) + //{ + passData.mSamplerNames[ texIndex ] = "AccuMap"; + passData.mTexType[ texIndex++ ] = Material::AccuMap; + //} +} + + +void AccuTexFeatHLSL::getAccuVec( MultiLine *meta, LangElement *accuVec ) +{ + // Get the transform to world space. + Var *objTrans = (Var*)LangElement::find( "objTrans" ); + if ( !objTrans ) + { + objTrans = new Var; + objTrans->setType( "float4x4" ); + objTrans->setName( "objTrans" ); + objTrans->uniform = true; + objTrans->constSortPos = cspPrimitive; + } + + // accu obj trans + Var *aobjTrans = new Var; + aobjTrans->setType( "float4x4" ); + aobjTrans->setName( "accuObjTrans" ); + LangElement *accuObjTransDecl = new DecOp( aobjTrans ); + + Var *outObjToTangentSpace = (Var*)LangElement::find( "objToTangentSpace" ); + + Var *tav = new Var; + tav->setType( "float4" ); + tav->setName( "tAccuVec" ); + LangElement *tavDecl = new DecOp( tav ); + + meta->addStatement( new GenOp( " @ = float4(0,0,1,0);\r\n", tavDecl ) ); + meta->addStatement( new GenOp( " @ = transpose(@);\r\n", accuObjTransDecl, objTrans ) ); + meta->addStatement( new GenOp( " @ = mul(@, @);\r\n", tav, aobjTrans, tav ) ); + meta->addStatement( new GenOp( " @.xyz = mul(@, @.xyz);\r\n", tav, outObjToTangentSpace, tav ) ); + meta->addStatement( new GenOp( " @.y *= -1;\r\n", tav ) ); + meta->addStatement( new GenOp( " @ = @.xyz;\r\n", accuVec, tav ) ); +} + +Var* AccuTexFeatHLSL::addOutAccuVec( Vector &componentList, MultiLine *meta ) +{ + Var *outAccuVec = (Var*)LangElement::find( "accuVec" ); + if ( !outAccuVec ) + { + // Setup the connector. + ShaderConnector *connectComp = dynamic_cast( componentList[C_CONNECTOR] ); + outAccuVec = connectComp->getElement( RT_TEXCOORD ); + outAccuVec->setName( "accuVec" ); + outAccuVec->setStructName( "OUT" ); + outAccuVec->setType( "float3" ); + outAccuVec->mapsToSampler = false; + + getAccuVec( meta, outAccuVec ); + } + + return outAccuVec; +} diff --git a/Engine/source/shaderGen/HLSL/accuFeatureHLSL.h b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.h new file mode 100644 index 000000000..76ca93ae6 --- /dev/null +++ b/Engine/source/shaderGen/HLSL/accuFeatureHLSL.h @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +#ifndef _ACCUFEATUREHLSL_H_ +#define _ACCUFEATUREHLSL_H_ + +#ifndef _SHADERGEN_HLSL_SHADERFEATUREHLSL_H_ +#include "shaderGen/HLSL/shaderFeatureHLSL.h" +#endif +#ifndef _LANG_ELEMENT_H_ +#include "shaderGen/langElement.h" +#endif +#ifndef _GFXDEVICE_H_ +#include "gfx/gfxDevice.h" +#endif +#ifndef _FEATUREMGR_H_ +#include "shaderGen/featureMgr.h" +#endif +#ifndef _MATERIALFEATURETYPES_H_ +#include "materials/materialFeatureTypes.h" +#endif +#ifndef _MATERIALFEATUREDATA_H_ +#include "materials/materialFeatureData.h" +#endif + +/// Accu texture +class AccuTexFeatHLSL : public ShaderFeatureHLSL +{ +public: + + //**************************************************************************** + // Accu Texture + //**************************************************************************** + virtual void processVert( Vector &componentList, + const MaterialFeatureData &fd ); + + virtual void processPix( Vector &componentList, + const MaterialFeatureData &fd ); + + void getAccuVec( MultiLine *meta, LangElement *accuVec ); + + Var* addOutAccuVec( Vector &componentList, MultiLine *meta ); + + virtual Material::BlendOp getBlendOp(){ return Material::LerpAlpha; } + + virtual Resources getResources( const MaterialFeatureData &fd ) + { + Resources res; + res.numTex = 1; + res.numTexReg = 1; + return res; + } + + virtual void setTexData( Material::StageData &stageDat, + const MaterialFeatureData &fd, + RenderPassData &passData, + U32 &texIndex ); + + virtual String getName() + { + return "Accu Texture"; + } +}; + +class AccuScaleFeature : public ShaderFeatureHLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuScale = (Var *)( LangElement::find("accuScale") ); + if( accuScale == NULL ) + { + accuScale = new Var; + accuScale->setType( "float" ); + accuScale->setName( "accuScale" ); + accuScale->constSortPos = cspPotentialPrimitive; + accuScale->uniform = true; + } + } + + virtual String getName() { return "Accu Scale"; } +}; + +class AccuDirectionFeature : public ShaderFeatureHLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuDirection = (Var *)( LangElement::find("accuDirection") ); + if( accuDirection == NULL ) + { + accuDirection = new Var; + accuDirection->setType( "float" ); + accuDirection->setName( "accuDirection" ); + accuDirection->constSortPos = cspPotentialPrimitive; + accuDirection->uniform = true; + } + } + + virtual String getName() { return "Accu Direction"; } +}; + +class AccuStrengthFeature : public ShaderFeatureHLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuStrength = (Var *)( LangElement::find("accuStrength") ); + if( accuStrength == NULL ) + { + accuStrength = new Var; + accuStrength->setType( "float" ); + accuStrength->setName( "accuStrength" ); + accuStrength->constSortPos = cspPotentialPrimitive; + accuStrength->uniform = true; + } + } + + virtual String getName() { return "Accu Strength"; } +}; + +class AccuCoverageFeature : public ShaderFeatureHLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuCoverage = (Var *)( LangElement::find("accuCoverage") ); + if( accuCoverage == NULL ) + { + accuCoverage = new Var; + accuCoverage->setType( "float" ); + accuCoverage->setName( "accuCoverage" ); + accuCoverage->constSortPos = cspPotentialPrimitive; + accuCoverage->uniform = true; + } + } + + virtual String getName() { return "Accu Coverage"; } +}; + + +class AccuSpecularFeature : public ShaderFeatureHLSL +{ +public: + virtual void processPix( Vector &componentList, const MaterialFeatureData &fd ) + { + // Find the constant value + Var *accuSpecular = (Var *)( LangElement::find("accuSpecular") ); + if( accuSpecular == NULL ) + { + accuSpecular = new Var; + accuSpecular->setType( "float" ); + accuSpecular->setName( "accuSpecular" ); + accuSpecular->constSortPos = cspPotentialPrimitive; + accuSpecular->uniform = true; + } + } + + virtual String getName() { return "Accu Specular"; } +}; + +#endif \ No newline at end of file diff --git a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp index 3b2e34c41..c754e1b25 100644 --- a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp +++ b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp @@ -32,7 +32,7 @@ #include "shaderGen/HLSL/paraboloidHLSL.h" #include "materials/materialFeatureTypes.h" #include "core/module.h" - +#include "shaderGen/HLSL/accuFeatureHLSL.h" static ShaderGen::ShaderGenInitDelegate sInitDelegate; @@ -66,6 +66,7 @@ void _initShaderGenHLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_Visibility, new VisibilityFeatHLSL ); FEATUREMGR->registerFeature( MFT_Fog, new FogFeatHLSL ); FEATUREMGR->registerFeature( MFT_SpecularMap, new SpecularMapHLSL ); + FEATUREMGR->registerFeature( MFT_AccuMap, new AccuTexFeatHLSL ); FEATUREMGR->registerFeature( MFT_GlossMap, new NamedFeatureHLSL( "Gloss Map" ) ); FEATUREMGR->registerFeature( MFT_LightbufferMRT, new NamedFeatureHLSL( "Lightbuffer MRT" ) ); FEATUREMGR->registerFeature( MFT_RenderTarget1_Zero, new RenderTargetZeroHLSL( ShaderFeature::RenderTarget1 ) ); diff --git a/Engine/source/ts/tsMesh.cpp b/Engine/source/ts/tsMesh.cpp index 0ed173297..f046f45ae 100644 --- a/Engine/source/ts/tsMesh.cpp +++ b/Engine/source/ts/tsMesh.cpp @@ -165,6 +165,9 @@ void TSMesh::innerRender( TSMaterialList *materials, const TSRenderState &rdata, MeshRenderInst *coreRI = renderPass->allocInst(); coreRI->type = RenderPassManager::RIT_Mesh; + // Pass accumulation texture along. + coreRI->accuTex = rdata.getAccuTex(); + const MatrixF &objToWorld = GFX->getWorldMatrix(); // Sort by the center point or the bounds. diff --git a/Engine/source/ts/tsRenderState.cpp b/Engine/source/ts/tsRenderState.cpp index fab8f213c..27033ade0 100644 --- a/Engine/source/ts/tsRenderState.cpp +++ b/Engine/source/ts/tsRenderState.cpp @@ -33,7 +33,8 @@ TSRenderState::TSRenderState() mMaterialHint( NULL ), mCuller( NULL ), mLightQuery( NULL ), - mUseOriginSort( false ) + mUseOriginSort( false ), + mAccuTex( NULL ) { } diff --git a/Engine/source/ts/tsRenderState.h b/Engine/source/ts/tsRenderState.h index 3d74def15..25dce4729 100644 --- a/Engine/source/ts/tsRenderState.h +++ b/Engine/source/ts/tsRenderState.h @@ -27,7 +27,9 @@ #include "math/mMatrix.h" #endif - +#ifndef _GFXDEVICE_H_ +#include "gfx/gfxDevice.h" +#endif class SceneRenderState; class GFXCubemap; @@ -103,8 +105,14 @@ protected: /// are forward lit and need lights. LightQuery *mLightQuery; + // The accumulation texture provided by an accumulation + // volume. This is passed down per-object. + GFXTextureObject* mAccuTex; + public: + + TSRenderState(); TSRenderState( const TSRenderState &state ); @@ -147,6 +155,10 @@ public: void setLightQuery( LightQuery *query ) { mLightQuery = query; } LightQuery* getLightQuery() const { return mLightQuery; } + ///@see mAccuTex + void setAccuTex( GFXTextureObject* query ) { mAccuTex = query; } + GFXTextureObject* getAccuTex() const { return mAccuTex; } + /// @} }; diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index d8722b6f9..821e02dba 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -39,7 +39,6 @@ #include "gfx/gfxDrawUtil.h" #include "core/module.h" - MODULE_BEGIN( TSShapeInstance ) MODULE_INIT @@ -783,3 +782,16 @@ void TSShapeInstance::prepCollision() } } +// Returns true is the shape contains any materials with accumulation enabled. +bool TSShapeInstance::hasAccumulation() +{ + bool result = false; + for ( U32 i = 0; i < mMaterialList->size(); ++i ) + { + BaseMatInstance* mat = mMaterialList->getMaterialInst(i); + if ( mat->hasAccumulation() ) + result = true; + } + return result; +} + diff --git a/Engine/source/ts/tsShapeInstance.h b/Engine/source/ts/tsShapeInstance.h index 7f83851c4..744346850 100644 --- a/Engine/source/ts/tsShapeInstance.h +++ b/Engine/source/ts/tsShapeInstance.h @@ -671,6 +671,12 @@ protected: void *mData; ///< available for use by app...initialized to 0 void prepCollision(); + +//------------------------------------------------------------------------------------- +// accumulation +//------------------------------------------------------------------------------------- + + bool hasAccumulation(); }; diff --git a/Engine/source/util/imposterCapture.cpp b/Engine/source/util/imposterCapture.cpp index a34182232..fb0786390 100644 --- a/Engine/source/util/imposterCapture.cpp +++ b/Engine/source/util/imposterCapture.cpp @@ -121,6 +121,7 @@ void ImposterCaptureMaterialHook::init( BaseMatInstance *inMat ) features.addFeature( MFT_IsDXTnm ); features.addFeature( MFT_NormalMap ); features.addFeature( MFT_NormalsOut ); + features.addFeature( MFT_AccuMap ); mNormalsMatInst = MATMGR->createMatInstance( matName ); mNormalsMatInst->getFeaturesDelegate().bind( &ImposterCaptureMaterialHook::_overrideFeatures ); mNormalsMatInst->init( features, inMat->getVertexFormat() ); diff --git a/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 90298419b..b4b006904 100644 --- a/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -654,7 +654,6 @@ bitmap = "tools/gui/images/delete"; }; }; - }; }; new GuiRolloutCtrl(advancedTextureMapsRollout) { @@ -1483,6 +1482,482 @@ }; }; }; + new GuiRolloutCtrl() { + class = "BehaviorQuickEditRollout"; + superclass = LBQuickEditRollout; + Profile = "GuiRolloutProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "195 0"; + Caption = "Accumulation Properties"; + Margin = "-1 0 0 0"; + DragSizable = false; + container = true; + parentRollout = %this.rollout; + object = %behavior; + + new GuiStackControl() { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "0"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "1 3"; + Extent = "195 16"; + MinExtent = "16 16"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiContainer(){ // enable/disable + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiCheckBoxCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuCheckbox"; + Enabled = "1"; + isContainer = "0"; + Profile = "ToolsGuiCheckBoxProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 7"; + Extent = "57 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateAccuCheckbox($ThisControl.getValue());"; + tooltipprofile = "ToolsGuiDefaultProfile"; + ToolTip = "Enables the use of Pixel Specular for this layer."; + hovertime = "1000"; + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + useInactiveState = "0"; + }; + }; + + new GuiContainer(){ // scale + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Scale"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuScaleSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuScale[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuScale[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the scale of the accu map."; + hovertime = "1000"; + range = "0.03125 32"; + ticks = "0"; + value = "1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuScaleTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuScale[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "1"; + maxLength = "3"; + }; + }; + }; + + new GuiContainer(){ // direction + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Direction"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuDirectionSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuDirection[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuDirection[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the direction of the accu map."; + hovertime = "1000"; + range = "-1 1"; + ticks = "0"; + value = "-1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuDirectionTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuDirection[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "-1"; + maxLength = "3"; + }; + }; + }; + new GuiContainer(){ // strength + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Strength"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuStrengthSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuStrength[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuStrength[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the strength of the accu map."; + hovertime = "1000"; + range = "0 1"; + ticks = "0"; + value = "0.6"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuStrengthTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuStrength[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "0.6"; + maxLength = "3"; + }; + }; + }; + new GuiContainer(){ // coverage + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Coverage"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuCoverageSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuCoverage[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuCoverage[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the coverage of the accu map."; + hovertime = "1000"; + range = "0 2"; + ticks = "0"; + value = "1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuCoverageTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuCoverage[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "1"; + maxLength = "3"; + }; + }; + }; + new GuiContainer(){ // specular + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Specular scale"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuSpecularSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuSpecular[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuSpecular[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the specular scale over the accu map."; + hovertime = "1000"; + range = "0 2"; + ticks = "0"; + value = "1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuSpecularTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuSpecular[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "1"; + maxLength = "3"; + }; + }; + }; + + }; + }; new GuiRolloutCtrl() { class = "BehaviorQuickEditRollout"; superclass = LBQuickEditRollout; diff --git a/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs index ec1020fa4..6b055d05c 100644 --- a/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -886,6 +886,17 @@ function MaterialEditorGui::guiSync( %this, %material ) MaterialEditorPropertiesWindow-->specMapDisplayBitmap.setBitmap( (%material).specularMap[%layer] ); } + MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]); + MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]); + MaterialEditorPropertiesWindow-->accuDirectionTextEdit.setText((%material).accuDirection[%layer]); + MaterialEditorPropertiesWindow-->accuDirectionTextEdit.setText((%material).accuDirection[%layer]); + MaterialEditorPropertiesWindow-->accuStrengthTextEdit.setText((%material).accuStrength[%layer]); + MaterialEditorPropertiesWindow-->accuStrengthTextEdit.setText((%material).accuStrength[%layer]); + MaterialEditorPropertiesWindow-->accuCoverageTextEdit.setText((%material).accuCoverage[%layer]); + MaterialEditorPropertiesWindow-->accuCoverageTextEdit.setText((%material).accuCoverage[%layer]); + MaterialEditorPropertiesWindow-->accuSpecularTextEdit.setText((%material).accuSpecular[%layer]); + MaterialEditorPropertiesWindow-->accuSpecularTextEdit.setText((%material).accuSpecular[%layer]); + MaterialEditorPropertiesWindow-->detailScaleTextEdit.setText( getWord((%material).detailScale[%layer], 0) ); MaterialEditorPropertiesWindow-->detailNormalStrengthTextEdit.setText( getWord((%material).detailNormalMapStrength[%layer], 0) ); @@ -966,6 +977,9 @@ function MaterialEditorGui::guiSync( %this, %material ) MaterialEditorPropertiesWindow-->SequenceSliderFPS.setValue( (%material).sequenceFramePerSec[%layer] ); MaterialEditorPropertiesWindow-->SequenceSliderSSS.setValue( %numFrames ); + // Accumulation + MaterialEditorPropertiesWindow-->accuCheckbox.setValue((%material).accuEnabled[%layer]); + %this.preventUndo = false; } @@ -2249,3 +2263,10 @@ function MaterialEditorMapThumbnail::onRightClick( %this ) %popup.showPopup( Canvas ); } + +// Accumulation +function MaterialEditorGui::updateAccuCheckbox(%this, %value) +{ + MaterialEditorGui.updateActiveMaterial("accuEnabled[" @ MaterialEditorGui.currentLayer @ "]", %value); + MaterialEditorGui.guiSync( materialEd_previewMaterial ); +} diff --git a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs index 75d41eb53..f1992c8df 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -83,6 +83,7 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "SpawnSphere", "Observer Spawn Sphere", "ObserverDropPoint" ); %this.registerMissionObject( "SFXSpace", "Sound Space" ); %this.registerMissionObject( "OcclusionVolume", "Occlusion Volume" ); + %this.registerMissionObject( "AccumulationVolume", "Accumulation Volume" ); %this.registerMissionObject("NavMesh", "Navigation mesh"); %this.registerMissionObject("NavPath", "Path"); diff --git a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 90298419b..b4b006904 100644 --- a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -654,7 +654,6 @@ bitmap = "tools/gui/images/delete"; }; }; - }; }; new GuiRolloutCtrl(advancedTextureMapsRollout) { @@ -1483,6 +1482,482 @@ }; }; }; + new GuiRolloutCtrl() { + class = "BehaviorQuickEditRollout"; + superclass = LBQuickEditRollout; + Profile = "GuiRolloutProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "0 0"; + Extent = "195 0"; + Caption = "Accumulation Properties"; + Margin = "-1 0 0 0"; + DragSizable = false; + container = true; + parentRollout = %this.rollout; + object = %behavior; + + new GuiStackControl() { + StackingType = "Vertical"; + HorizStacking = "Left to Right"; + VertStacking = "Top to Bottom"; + Padding = "0"; + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "1"; + Profile = "GuiDefaultProfile"; + HorizSizing = "width"; + VertSizing = "bottom"; + Position = "1 3"; + Extent = "195 16"; + MinExtent = "16 16"; + canSave = "1"; + isDecoy = "0"; + Visible = "1"; + tooltipprofile = "GuiToolTipProfile"; + hovertime = "1000"; + + new GuiContainer(){ // enable/disable + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiCheckBoxCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuCheckbox"; + Enabled = "1"; + isContainer = "0"; + Profile = "ToolsGuiCheckBoxProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 7"; + Extent = "57 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateAccuCheckbox($ThisControl.getValue());"; + tooltipprofile = "ToolsGuiDefaultProfile"; + ToolTip = "Enables the use of Pixel Specular for this layer."; + hovertime = "1000"; + text = "Enable"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + useInactiveState = "0"; + }; + }; + + new GuiContainer(){ // scale + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Scale"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuScaleSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuScale[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuScale[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the scale of the accu map."; + hovertime = "1000"; + range = "0.03125 32"; + ticks = "0"; + value = "1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuScaleTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuScale[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "1"; + maxLength = "3"; + }; + }; + }; + + new GuiContainer(){ // direction + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Direction"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuDirectionSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuDirection[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuDirection[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the direction of the accu map."; + hovertime = "1000"; + range = "-1 1"; + ticks = "0"; + value = "-1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuDirectionTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuDirection[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "-1"; + maxLength = "3"; + }; + }; + }; + new GuiContainer(){ // strength + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Strength"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuStrengthSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuStrength[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuStrength[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the strength of the accu map."; + hovertime = "1000"; + range = "0 1"; + ticks = "0"; + value = "0.6"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuStrengthTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuStrength[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "0.6"; + maxLength = "3"; + }; + }; + }; + new GuiContainer(){ // coverage + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Coverage"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuCoverageSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuCoverage[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuCoverage[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the coverage of the accu map."; + hovertime = "1000"; + range = "0 2"; + ticks = "0"; + value = "1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuCoverageTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuCoverage[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "1"; + maxLength = "3"; + }; + }; + }; + new GuiContainer(){ // specular + profile="GuiTransparentProfile"; + isContainer = "1"; + position = "0 0"; + Extent = "195 24"; + HorizSizing = "width"; + + new GuiTextCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextRightProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "8 3"; + Extent = "54 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + hovertime = "1000"; + Margin = "0 0 0 0"; + Padding = "0 0 0 0"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "Specular scale"; + maxLength = "1024"; + }; + + new GuiControl() { + class = "AggregateControl"; + position = "70 3"; + Extent = "96 20"; + + new GuiSliderCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuSpecularSlider"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiSliderProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "0 2"; + Extent = "61 14"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.updateActiveMaterial(\"accuSpecular[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, true);"; + AltCommand = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuSpecular[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue(), true, false);"; + tooltipprofile = "GuiDefaultProfile"; + ToolTip = "Sets the specular scale over the accu map."; + hovertime = "1000"; + range = "0 2"; + ticks = "0"; + value = "1"; + }; + new GuiTextEditCtrl() { + canSaveDynamicFields = "0"; + internalName = "accuSpecularTextEdit"; + Enabled = "1"; + isContainer = "0"; + Profile = "GuiTextEditProfile"; + HorizSizing = "right"; + VertSizing = "bottom"; + position = "64 0"; + Extent = "29 18"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "$ThisControl.getParent().updateFromChild($ThisControl); MaterialEditorGui.updateActiveMaterial(\"accuSpecular[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());"; + hovertime = "1000"; + AnchorTop = "1"; + AnchorBottom = "0"; + AnchorLeft = "1"; + AnchorRight = "0"; + text = "1"; + maxLength = "3"; + }; + }; + }; + + }; + }; new GuiRolloutCtrl() { class = "BehaviorQuickEditRollout"; superclass = LBQuickEditRollout; diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs index ec1020fa4..6b055d05c 100644 --- a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -886,6 +886,17 @@ function MaterialEditorGui::guiSync( %this, %material ) MaterialEditorPropertiesWindow-->specMapDisplayBitmap.setBitmap( (%material).specularMap[%layer] ); } + MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]); + MaterialEditorPropertiesWindow-->accuScaleTextEdit.setText((%material).accuScale[%layer]); + MaterialEditorPropertiesWindow-->accuDirectionTextEdit.setText((%material).accuDirection[%layer]); + MaterialEditorPropertiesWindow-->accuDirectionTextEdit.setText((%material).accuDirection[%layer]); + MaterialEditorPropertiesWindow-->accuStrengthTextEdit.setText((%material).accuStrength[%layer]); + MaterialEditorPropertiesWindow-->accuStrengthTextEdit.setText((%material).accuStrength[%layer]); + MaterialEditorPropertiesWindow-->accuCoverageTextEdit.setText((%material).accuCoverage[%layer]); + MaterialEditorPropertiesWindow-->accuCoverageTextEdit.setText((%material).accuCoverage[%layer]); + MaterialEditorPropertiesWindow-->accuSpecularTextEdit.setText((%material).accuSpecular[%layer]); + MaterialEditorPropertiesWindow-->accuSpecularTextEdit.setText((%material).accuSpecular[%layer]); + MaterialEditorPropertiesWindow-->detailScaleTextEdit.setText( getWord((%material).detailScale[%layer], 0) ); MaterialEditorPropertiesWindow-->detailNormalStrengthTextEdit.setText( getWord((%material).detailNormalMapStrength[%layer], 0) ); @@ -966,6 +977,9 @@ function MaterialEditorGui::guiSync( %this, %material ) MaterialEditorPropertiesWindow-->SequenceSliderFPS.setValue( (%material).sequenceFramePerSec[%layer] ); MaterialEditorPropertiesWindow-->SequenceSliderSSS.setValue( %numFrames ); + // Accumulation + MaterialEditorPropertiesWindow-->accuCheckbox.setValue((%material).accuEnabled[%layer]); + %this.preventUndo = false; } @@ -2249,3 +2263,10 @@ function MaterialEditorMapThumbnail::onRightClick( %this ) %popup.showPopup( Canvas ); } + +// Accumulation +function MaterialEditorGui::updateAccuCheckbox(%this, %value) +{ + MaterialEditorGui.updateActiveMaterial("accuEnabled[" @ MaterialEditorGui.currentLayer @ "]", %value); + MaterialEditorGui.guiSync( materialEd_previewMaterial ); +} diff --git a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs index 75d41eb53..f1992c8df 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -83,6 +83,7 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "SpawnSphere", "Observer Spawn Sphere", "ObserverDropPoint" ); %this.registerMissionObject( "SFXSpace", "Sound Space" ); %this.registerMissionObject( "OcclusionVolume", "Occlusion Volume" ); + %this.registerMissionObject( "AccumulationVolume", "Accumulation Volume" ); %this.registerMissionObject("NavMesh", "Navigation mesh"); %this.registerMissionObject("NavPath", "Path");