@@ -0,0 +1,113 @@
//-----------------------------------------------------------------------------
// 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 _EnvVolume_H_
#define _EnvVolume_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

#ifndef _CUBEMAPDATA_H_
#include "gfx/sim/cubemapData.h"
#endif

#ifndef _REFLECTOR_H_
#include "scene/reflector.h"
#endif

/// A volume in space that blocks visibility.
class EnvVolume : public ScenePolyhedralSpace
{
public:

typedef ScenePolyhedralSpace Parent;

protected:

/// 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;

mutable Vector< SceneObject* > mVolumeQueryList;

// Name (path) of the area environment cube map.
String mAreaEnvMapName;

// reflector
String cubeDescName;
U32 cubeDescId;
ReflectorDesc *reflectorDesc;
CubeReflector mCubeReflector;

// SceneSpace.
virtual void _renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat );

public:

// Area environment cube map handle.
CubemapData *mAreaEnvMap;

EnvVolume();
~EnvVolume();

// SimObject.
DECLARE_CONOBJECT( EnvVolume );
DECLARE_DESCRIPTION( "Allows objects in an area to have a given envoronment map applied." );
DECLARE_CATEGORY( "3D Scene" );

virtual bool onAdd();
virtual void onRemove();
void inspectPostApply();
void setTexture( const String& name );
void refreshVolume();

// Static Functions.
static void consoleInit();
static void initPersistFields();
static Vector< SimObjectPtr<SceneObject> > smProbedObjects;
static Vector< SimObjectPtr<EnvVolume> > smEnvVolumes;
static void addObject(SimObjectPtr<SceneObject> object);
static void removeObject(SimObjectPtr<SceneObject> object);
static void refreshVolumes();
static void updateObject(SceneObject* object);

// Network
U32 packUpdate( NetConnection *, U32 mask, BitStream *stream );
void unpackUpdate( NetConnection *, BitStream *stream );

// SceneObject.
virtual void setTransform( const MatrixF& mat );
};

#endif // !_EnvVolume_H_
@@ -34,6 +34,8 @@
#include "scene/sceneManager.h"
#include "scene/sceneRenderState.h"

extern GFXCubemap * gLevelEnvMap;

// GuiMaterialPreview
GuiMaterialPreview::GuiMaterialPreview()
: mMouseState(None),
@@ -383,7 +385,7 @@ void GuiMaterialPreview::renderWorld(const RectI &updateRect)
// Set up our TS render state here.
TSRenderState rdata;
rdata.setSceneState( &state );

rdata.setCubemap(gLevelEnvMap);
// We might have some forward lit materials
// so pass down a query to gather lights.
LightQuery query;
@@ -69,6 +69,8 @@ extern ColorI gCanvasClearColor;
/// @see DecalManager
extern F32 gDecalBias;

/// @see LightProbeVolume
extern GFXCubemap * gLevelEnvMap;
/// @see AccumulationVolume
extern GFXTexHandle gLevelAccuMap;

@@ -97,13 +99,17 @@ LevelInfo::LevelInfo()

mNetFlags.set( ScopeAlways | Ghostable );

mAdvancedLightmapSupport = false;
mAdvancedLightmapSupport = true;
mAccuTextureName = "";
mAccuTexture = NULL;

// Register with the light manager activation signal, and we need to do it first
// so the advanced light bin manager can be instructed about MRT lightmaps
LightManager::smActivateSignal.notify(this, &LevelInfo::_onLMActivate, 0.01f);

// Accumulation Texture.
mLevelEnvMapName = "";
mLevelEnvMap = NULL;
}

//-----------------------------------------------------------------------------
@@ -163,8 +169,11 @@ void LevelInfo::initPersistFields()
addField( "ambientLightBlendCurve", TypeEaseF, Offset( mAmbientLightBlendCurve, LevelInfo ),
"Interpolation curve to use for blending from one ambient light color to a different one." );

addField( "advancedLightmapSupport", TypeBool, Offset( mAdvancedLightmapSupport, LevelInfo ),
"Enable expanded support for mixing static and dynamic lighting (more costly)" );
//addField( "advancedLightmapSupport", TypeBool, Offset( mAdvancedLightmapSupport, LevelInfo ),
//"Enable expanded support for mixing static and dynamic lighting (more costly)");

addField("LevelEnvMap", TypeCubemapName, Offset(mLevelEnvMapName, LevelInfo),
"Environment map applied to objects for a given area.");

addProtectedField("AccuTexture", TypeStringFilename, Offset(mAccuTextureName, LevelInfo),
&_setLevelAccuTexture, &defaultProtectedGetFn, "Accumulation texture.");
@@ -216,7 +225,10 @@ U32 LevelInfo::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
sfxWrite( stream, mSoundAmbience );
stream->writeInt( mSoundDistanceModel, 1 );

stream->write(mLevelEnvMapName);

stream->write(mAccuTextureName);

return retMask;
}

@@ -261,6 +273,10 @@ void LevelInfo::unpackUpdate(NetConnection *conn, BitStream *stream)

SFX->setDistanceModel( mSoundDistanceModel );
}

stream->read(&mLevelEnvMapName);
setLevelEnvMap(mLevelEnvMapName);

stream->read(&mAccuTextureName);
setLevelAccuTexture(mAccuTextureName);
}
@@ -358,6 +374,23 @@ void LevelInfo::_onLMActivate(const char *lm, bool enable)
#endif
}

void LevelInfo::setLevelEnvMap(const String& name)
{
mLevelEnvMapName = name;
if (isClientObject() && mLevelEnvMapName.isNotEmpty())
{
Sim::findObject(mLevelEnvMapName, mLevelEnvMap);
if (!mLevelEnvMap)
Con::warnf("LightProbeVolume::setTexture - Unable to load cubemap: %s", mLevelEnvMapName.c_str());
else
{
if (!mLevelEnvMap->mCubemap)
mLevelEnvMap->createMap();
gLevelEnvMap = mLevelEnvMap->mCubemap;
}
}
}

bool LevelInfo::_setLevelAccuTexture(void *object, const char *index, const char *data)
{
LevelInfo* volume = reinterpret_cast< LevelInfo* >(object);
@@ -35,7 +35,9 @@
#ifndef _SFXCOMMON_H_
#include "sfx/sfxCommon.h"
#endif

#ifndef _CUBEMAPDATA_H_
#include "gfx/sim/cubemapData.h"
#endif
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
@@ -104,6 +106,11 @@ class LevelInfo : public NetObject
// Name (path) of the accumulation texture.
String mAccuTextureName;

// Name (path) of the area environment cube map.
String mLevelEnvMapName;

// Level environment cube map handle.
CubemapData *mLevelEnvMap;
public:

LevelInfo();
@@ -141,6 +148,7 @@ class LevelInfo : public NetObject

virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );
virtual void unpackUpdate( NetConnection *conn, BitStream *stream );
void setLevelEnvMap(const String& name);
static bool _setLevelAccuTexture(void *object, const char *index, const char *data);
void setLevelAccuTexture(const String& name);
/// @}
@@ -68,6 +68,7 @@
#include "renderInstance/renderOcclusionMgr.h"
#include "core/stream/fileStream.h"
#include "T3D/accumulationVolume.h"
#include "T3D/envVolume.h"

IMPLEMENT_CO_DATABLOCK_V1(ShapeBaseData);

@@ -1157,9 +1158,11 @@ bool ShapeBase::onAdd()
if(mDataBlock->cloakTexName != StringTable->EmptyString())
mCloakTexture = TextureHandle(mDataBlock->cloakTexName, MeshTexture, false);
*/

// Accumulation and environment mapping
if (isClientObject() && mShapeInstance)
{
EnvVolume::addObject(this);
AccumulationVolume::addObject(this);
}
return true;
@@ -1176,6 +1179,14 @@ void ShapeBase::onRemove()
for (S32 i = 0; i < MaxSoundThreads; i++)
stopAudio(i);

// Accumulation and environment mapping
if (isClientObject() && mShapeInstance)
{
if (mShapeInstance->hasAccumulation())
AccumulationVolume::removeObject(this);
EnvVolume::removeObject(this);
}

if ( isClientObject() )
{
mCubeReflector.unregisterReflector();
@@ -1219,122 +1230,122 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload )
// Even if loadShape succeeds, there may not actually be
// a shape assigned to this object.
if (bool(mDataBlock->mShape)) {
delete mShapeInstance;
if (isClientObject() && mDataBlock->txr_tag_remappings.size() > 0)
{
// temporarily substitute material tags with alternates
TSMaterialList* mat_list = mDataBlock->mShape->materialList;
if (mat_list)
{
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
{
ShapeBaseData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
for (S32 j = 0; j < mat_names.size(); j++)
{
if (mat_names[j].compare(remap->old_tag, dStrlen(remap->old_tag), String::NoCase) == 0)
{
mat_names[j] = String(remap->new_tag);
mat_names[j].insert(0,'#');
break;
}
}
}
}
}
mShapeInstance = new TSShapeInstance(mDataBlock->mShape, isClientObject());
if (isClientObject())
{
mShapeInstance->cloneMaterialList();

// restore the material tags to original form
if (mDataBlock->txr_tag_remappings.size() > 0)
{
TSMaterialList* mat_list = mDataBlock->mShape->materialList;
if (mat_list)
{
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
{
ShapeBaseData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
for (S32 j = 0; j < mat_names.size(); j++)
{
String::SizeType len = mat_names[j].length();
if (len > 1)
{
String temp_name = mat_names[j].substr(1,len-1);
if (temp_name.compare(remap->new_tag, dStrlen(remap->new_tag)) == 0)
{
mat_names[j] = String(remap->old_tag);
break;
}
}
}
}
}
}
}

mObjBox = mDataBlock->mShape->bounds;
resetWorldBox();

// Set the initial mesh hidden state.
mMeshHidden.setSize( mDataBlock->mShape->objects.size() );
mMeshHidden.clear();

// Initialize the threads
for (U32 i = 0; i < MaxScriptThreads; i++) {
Thread& st = mScriptThread[i];
if (st.sequence != -1) {
// TG: Need to see about suppressing non-cyclic sounds
// if the sequences were activated before the object was
// ghosted.
// TG: Cyclic animations need to have a random pos if
// they were started before the object was ghosted.

// If there was something running on the old shape, the thread
// needs to be reset. Otherwise we assume that it's been
// initialized either by the constructor or from the server.
bool reset = st.thread != 0;
st.thread = 0;

// New datablock/shape may not actually HAVE this sequence.
// In that case stop playing it.

AssertFatal( prevDB != NULL, "ShapeBase::onNewDataBlock - how did you have a sequence playing without a prior datablock?" );

const TSShape *prevShape = prevDB->mShape;
const TSShape::Sequence &prevSeq = prevShape->sequences[st.sequence];
const String &prevSeqName = prevShape->names[prevSeq.nameIndex];

st.sequence = mDataBlock->mShape->findSequence( prevSeqName );

if ( st.sequence != -1 )
{
setThreadSequence( i, st.sequence, reset );
}
}
}

if (mDataBlock->damageSequence != -1) {
mDamageThread = mShapeInstance->addThread();
mShapeInstance->setSequence(mDamageThread,
mDataBlock->damageSequence,0);
}
if (mDataBlock->hulkSequence != -1) {
mHulkThread = mShapeInstance->addThread();
mShapeInstance->setSequence(mHulkThread,
mDataBlock->hulkSequence,0);
}

if( isGhost() )
{
// Reapply the current skin
mAppliedSkinName = "";
reSkin();
}
delete mShapeInstance;
if (isClientObject() && mDataBlock->txr_tag_remappings.size() > 0)
{
// temporarily substitute material tags with alternates
TSMaterialList* mat_list = mDataBlock->mShape->materialList;
if (mat_list)
{
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
{
ShapeBaseData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
for (S32 j = 0; j < mat_names.size(); j++)
{
if (mat_names[j].compare(remap->old_tag, dStrlen(remap->old_tag), String::NoCase) == 0)
{
mat_names[j] = String(remap->new_tag);
mat_names[j].insert(0, '#');
break;
}
}
}
}
}
mShapeInstance = new TSShapeInstance(mDataBlock->mShape, isClientObject());
if (isClientObject())
{
mShapeInstance->setUserObject(this);
mShapeInstance->cloneMaterialList();

// restore the material tags to original form
if (mDataBlock->txr_tag_remappings.size() > 0)
{
TSMaterialList* mat_list = mDataBlock->mShape->materialList;
if (mat_list)
{
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
{
ShapeBaseData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
for (S32 j = 0; j < mat_names.size(); j++)
{
String::SizeType len = mat_names[j].length();
if (len > 1)
{
String temp_name = mat_names[j].substr(1, len - 1);
if (temp_name.compare(remap->new_tag, dStrlen(remap->new_tag)) == 0)
{
mat_names[j] = String(remap->old_tag);
break;
}
}
}
}
}
}
}

mObjBox = mDataBlock->mShape->bounds;
resetWorldBox();

// Set the initial mesh hidden state.
mMeshHidden.setSize(mDataBlock->mShape->objects.size());
mMeshHidden.clear();

// Initialize the threads
for (U32 i = 0; i < MaxScriptThreads; i++) {
Thread& st = mScriptThread[i];
if (st.sequence != -1) {
// TG: Need to see about suppressing non-cyclic sounds
// if the sequences were activated before the object was
// ghosted.
// TG: Cyclic animations need to have a random pos if
// they were started before the object was ghosted.

// If there was something running on the old shape, the thread
// needs to be reset. Otherwise we assume that it's been
// initialized either by the constructor or from the server.
bool reset = st.thread != 0;
st.thread = 0;

// New datablock/shape may not actually HAVE this sequence.
// In that case stop playing it.

AssertFatal(prevDB != NULL, "ShapeBase::onNewDataBlock - how did you have a sequence playing without a prior datablock?");

const TSShape *prevShape = prevDB->mShape;
const TSShape::Sequence &prevSeq = prevShape->sequences[st.sequence];
const String &prevSeqName = prevShape->names[prevSeq.nameIndex];

st.sequence = mDataBlock->mShape->findSequence(prevSeqName);

if (st.sequence != -1)
{
setThreadSequence(i, st.sequence, reset);
}
}
}

if (mDataBlock->damageSequence != -1) {
mDamageThread = mShapeInstance->addThread();
mShapeInstance->setSequence(mDamageThread,
mDataBlock->damageSequence, 0);
}
if (mDataBlock->hulkSequence != -1) {
mHulkThread = mShapeInstance->addThread();
mShapeInstance->setSequence(mHulkThread,
mDataBlock->hulkSequence, 0);
}

if (isGhost())
{
// Reapply the current skin
mAppliedSkinName = "";
reSkin();
}
}

//
mEnergy = 0;
mDamage = 0;
@@ -2716,9 +2727,16 @@ void ShapeBase::prepBatchRender(SceneRenderState* state, S32 mountedImageIndex )

// Set up our TS render state.
TSRenderState rdata;
rdata.setSceneState( state );
if ( mCubeReflector.isEnabled() )
rdata.setCubemap( mCubeReflector.getCubemap() );
rdata.setSceneState(state);

//area or per object cubemapping
if (mCubeReflector.isEnabled())
rdata.setCubemap(mCubeReflector.getCubemap());
else
if (mEnvMap)
rdata.setCubemap(mEnvMap);

rdata.setMaterialDamage(getDamageValue());
rdata.setFadeOverride( (1.0f - mCloakLevel) * mFadeVal );

// We might have some forward lit materials
@@ -3723,6 +3741,19 @@ void ShapeBase::setCurrentWaterObject( WaterObject *obj )
mCurrentWaterObject = obj;
}

void ShapeBase::setTransform(const MatrixF & mat)
{
Parent::setTransform(mat);

// Accumulation and environment mapping
if (isClientObject() && mShapeInstance)
{
if (mShapeInstance->hasAccumulation())
AccumulationVolume::updateObject(this);
EnvVolume::updateObject(this);
}
}

void ShapeBase::notifyCollisionCallbacks(SceneObject* obj, const VectorF& vel)
{
for (S32 i = 0; i < collision_callbacks.size(); i++)
@@ -1842,7 +1842,7 @@ class ShapeBase : public GameBase, public ISceneLight
virtual WaterObject* getCurrentWaterObject();

void setCurrentWaterObject( WaterObject *obj );

void setTransform(const MatrixF & mat);
virtual F32 getMass() const { return mMass; }

/// @name Network
@@ -2314,7 +2314,10 @@ void ShapeBase::setImage( U32 imageSlot,
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
{
if (image.dataBlock->shapeIsValid[i])
{
image.shapeInstance[i] = new TSShapeInstance(image.dataBlock->shape[i], isClientObject());
image.shapeInstance[i]->setUserObject(this);
}
}

if (isClientObject())
@@ -54,7 +54,7 @@
#include "materials/materialFeatureTypes.h"
#include "console/engineAPI.h"
#include "T3D/accumulationVolume.h"

#include "T3D/envVolume.h"
using namespace Torque;

extern bool gEditingMission;
@@ -333,8 +333,9 @@ bool TSStatic::onAdd()
_updateShouldTick();

// Accumulation and environment mapping
if (isClientObject() && mShapeInstance)
if ( isClientObject() && mShapeInstance )
{
EnvVolume::addObject(this);
AccumulationVolume::addObject(this);
}

@@ -377,6 +378,11 @@ bool TSStatic::_createShape()
resetWorldBox();

mShapeInstance = new TSShapeInstance( mShape, isClientObject() );
if (isClientObject())
{
mShapeInstance->setUserObject( this );
mShapeInstance->cloneMaterialList();
}

if (isClientObject())
mShapeInstance->cloneMaterialList();
@@ -479,12 +485,13 @@ void TSStatic::_updatePhysics()
void TSStatic::onRemove()
{
SAFE_DELETE( mPhysicsRep );

// Accumulation
if ( isClientObject() && mShapeInstance )
// Accumulation and environment mapping
if (isClientObject() && mShapeInstance)
{
if ( mShapeInstance->hasAccumulation() )
if (mShapeInstance->hasAccumulation())
AccumulationVolume::removeObject(this);
EnvVolume::removeObject(this);
}

mConvexList->nukeList();
@@ -665,8 +672,12 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
rdata.setFadeOverride( 1.0f );
rdata.setOriginSort( mUseOriginSort );

//area or per object cubemapping
if ( mCubeReflector.isEnabled() )
rdata.setCubemap( mCubeReflector.getCubemap() );
else
if (mEnvMap)
rdata.setCubemap(mEnvMap);

// Acculumation
rdata.setAccuTex(mAccuTex);
@@ -777,12 +788,13 @@ void TSStatic::setTransform(const MatrixF & mat)

if ( mPhysicsRep )
mPhysicsRep->setTransform( mat );

// Accumulation
if ( isClientObject() && mShapeInstance )
// Accumulation and environment mapping
if (isClientObject() && mShapeInstance)
{
if ( mShapeInstance->hasAccumulation() )
if (mShapeInstance->hasAccumulation())
AccumulationVolume::updateObject(this);
EnvVolume::updateObject(this);
}

// Since this is a static it's render transform changes 1
@@ -341,6 +341,5 @@ class EngineFunctionInfo : public EngineExport
EngineFunctionCallout | EngineFunctionFlags( flags ) \
); \
}


#endif // !_ENGINEFUNCTIONS_H_
@@ -207,6 +207,7 @@ void GFXD3D11Cubemap::initStatic(DDSFile *dds)
{
AssertFatal(false, "GFXD3D11Cubemap::initStatic(DDSFile *dds) - CreateTexture2D call failure");
}

}

void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
@@ -165,7 +165,7 @@ class GFXD3D11Device : public GFXDevice

virtual GFXD3D11VertexBuffer* findVBPool( const GFXVertexFormat *vertexFormat, U32 numVertsNeeded );
virtual GFXD3D11VertexBuffer* createVBPool( const GFXVertexFormat *vertexFormat, U32 vertSize );

// State overrides
// {

@@ -255,7 +255,7 @@ class GFXD3D11Device : public GFXDevice
virtual void setClipRect( const RectI &rect );
virtual const RectI& getClipRect() const { return mClipRect; }

// }
// }



@@ -325,7 +325,7 @@ class GFXD3D11Device : public GFXDevice

// grab the sampler map
const SamplerMap &getSamplersMap() const { return mSamplersMap; }
SamplerMap &getSamplersMap() { return mSamplersMap; }
SamplerMap &getSamplersMap(){ return mSamplersMap; }
};

#endif
@@ -31,8 +31,7 @@
#endif

GFXD3D11OcclusionQuery::GFXD3D11OcclusionQuery(GFXDevice *device)
: GFXOcclusionQuery(device),
mQuery(NULL)
: GFXOcclusionQuery(device), mQuery(NULL), mTesting(false)
{
#ifdef TORQUE_GATHER_METRICS
mTimer = PlatformTimer::create();
@@ -74,7 +73,11 @@ bool GFXD3D11OcclusionQuery::begin()
}

// Add a begin marker to the command buffer queue.
if (!mTesting)
{
D3D11DEVICECONTEXT->Begin(mQuery);
mTesting = true;
}

#ifdef TORQUE_GATHER_METRICS
mBeginFrame = GuiTSCtrl::getFrameCount();
@@ -90,6 +93,7 @@ void GFXD3D11OcclusionQuery::end()

// Add an end marker to the command buffer queue.
D3D11DEVICECONTEXT->End(mQuery);
mTesting = false;

#ifdef TORQUE_GATHER_METRICS
AssertFatal( mBeginFrame == GuiTSCtrl::getFrameCount(), "GFXD3D11OcclusionQuery::end - ended query on different frame than begin!" );
@@ -34,7 +34,7 @@ class GFXD3D11OcclusionQuery : public GFXOcclusionQuery
{
private:
mutable ID3D11Query *mQuery;

bool mTesting;
#ifdef TORQUE_GATHER_METRICS
U32 mBeginFrame;
U32 mTimeSinceEnd;
@@ -638,7 +638,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB
if(mVertexConstBuffer->isDirty())
{
const Vector<ConstSubBufferDesc> &subBuffers = mVertexConstBufferLayout->getSubBufferDesc();
// TODO: This is not very effecient updating the whole lot, re-implement the dirty system to work with multiple constant buffers.
// TODO: This is not very efficient updating the whole lot, re-implement the dirty system to work with multiple constant buffers.
// TODO: Implement DX 11.1 UpdateSubresource1 which supports updating ranges with constant buffers
buf = mVertexConstBuffer->getEntireBuffer();
for (U32 i = 0; i < subBuffers.size(); ++i)
@@ -656,7 +656,7 @@ void GFXD3D11ShaderConstBuffer::activate( GFXD3D11ShaderConstBuffer *prevShaderB
if(mPixelConstBuffer->isDirty())
{
const Vector<ConstSubBufferDesc> &subBuffers = mPixelConstBufferLayout->getSubBufferDesc();
// TODO: This is not very effecient updating the whole lot, re-implement the dirty system to work with multiple constant buffers.
// TODO: This is not very efficient updating the whole lot, re-implement the dirty system to work with multiple constant buffers.
// TODO: Implement DX 11.1 UpdateSubresource1 which supports updating ranges with constant buffers
buf = mPixelConstBuffer->getEntireBuffer();
for (U32 i = 0; i < subBuffers.size(); ++i)
@@ -859,6 +859,8 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath,
U32 flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_OPTIMIZATION_LEVEL3;
#endif



#ifdef D3D11_DEBUG_SPEW
Con::printf( "Compiling Shader: '%s'", filePath.getFullPath().c_str() );
#endif
@@ -193,6 +193,8 @@ GFXD3D11StateBlock::GFXD3D11StateBlock(const GFXStateBlockDesc& desc)
{
mSamplerStates[i] = itr->value;
}


}
}

@@ -80,8 +80,10 @@ class GFXD3D11WindowTarget : public GFXWindowTarget

/// Maximum size we can render to.
Point2I mSize;

/// D3D presentation info.
DXGI_SWAP_CHAIN_DESC mPresentationParams;

/// Internal interface that notifies us we need to reset our video mode.
void resetMode();

@@ -21,7 +21,6 @@
//-----------------------------------------------------------------------------

#include "gfx/bitmap/bitmapUtils.h"

#include "platform/platform.h"


@@ -0,0 +1,336 @@
//-----------------------------------------------------------------------------
// 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 "gfx/bitmap/cubemapSaver.h"
#include "platform/platform.h"
#include "gfx/bitmap/ddsFile.h"
#include "gfx/bitmap/imageUtils.h"
#include "gfx/gfxDevice.h"
#include "gfx/gfxTransformSaver.h"
#include "gfx/gfxTextureManager.h"
#include "materials/shaderData.h"
#include "core/stream/fileStream.h"
#include "math/mathUtils.h"
#include "math/mTransform.h"


namespace CubemapSaver
{
const U32 CubeFaces = 6;

void _setConstBuffer(GFXShaderConstHandle* handle, GFXShaderConstBuffer *cbuf, const VectorF &vLookatPt, const VectorF &vUpVec)
{
VectorF cross = mCross(vUpVec, vLookatPt);
cross.normalizeSafe();

MatrixF matView(true);
matView.setColumn(0, cross);
matView.setColumn(1, vLookatPt);
matView.setColumn(2, vUpVec);
matView.setPosition(VectorF(0.0f, 0.0f, 1.0f));
matView.inverse();

if (handle->isValid())
cbuf->set(handle, matView);
else
Con::errorf("CubemapSaver: Failed to set a shader constant handle.");
}

bool save(GFXCubemapHandle cubemap, const Torque::Path &path, GFXFormat compressionFormat)
{
if (!cubemap.isValid())
{
Con::errorf("CubemapSaver: cubemap handle is not valid");
return false;
}

// This can sometimes occur outside a begin/end scene.
const bool sceneBegun = GFX->canCurrentlyRender();
if (!sceneBegun)
GFX->beginScene();

GFXCubemap *pCubemap = cubemap.getPointer();
U32 faceSize = pCubemap->getSize();

ShaderData *shaderData = nullptr;
GFXShaderRef shader = Sim::findObject("CubemapSaveShader", shaderData) ? shaderData->getShader() : nullptr;
if (!shader)
{
Con::errorf("CubemapSaver::save - could not find CubemapSaveShader");
return false;
}

GFXShaderConstHandle *matHandles[CubeFaces];

matHandles[0] = shader->getShaderConstHandle("$matrix0");
matHandles[1] = shader->getShaderConstHandle("$matrix1");
matHandles[2] = shader->getShaderConstHandle("$matrix2");
matHandles[3] = shader->getShaderConstHandle("$matrix3");
matHandles[4] = shader->getShaderConstHandle("$matrix4");
matHandles[5] = shader->getShaderConstHandle("$matrix5");

GFXShaderConstBufferRef cbuffer = shader->allocConstBuffer();

GFXTextureTarget *pTarget = GFX->allocRenderToTextureTarget();
GFX->pushActiveRenderTarget();

GFXFormat renderTargetFmt = GFXFormatR8G8B8A8;
//setup render targets
GFXTexHandle pTextures[CubeFaces];
for (U32 i = 0; i < CubeFaces; i++)
{
pTextures[i].set(faceSize, faceSize, renderTargetFmt,
&GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
1, GFXTextureManager::AA_MATCH_BACKBUFFER);

pTarget->attachTexture(GFXTextureTarget::RenderSlot(GFXTextureTarget::Color0 + i), pTextures[i]);
}

//create stateblock
GFXStateBlockDesc desc;
desc.setZReadWrite(false, false);
desc.samplersDefined = true;
desc.samplers[0].addressModeU = GFXAddressClamp;
desc.samplers[0].addressModeV = GFXAddressClamp;
desc.samplers[0].addressModeW = GFXAddressClamp;
desc.samplers[0].magFilter = GFXTextureFilterLinear;
desc.samplers[0].minFilter = GFXTextureFilterLinear;
desc.samplers[0].mipFilter = GFXTextureFilterLinear;

//yep funky order and rotations with t3d z up
_setConstBuffer(matHandles[0], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(-1.0f, 0.0f, 0.0f));
_setConstBuffer(matHandles[1], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(1.0f, 0.0f, 0.0f));
_setConstBuffer(matHandles[2], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, -1.0f));
_setConstBuffer(matHandles[3], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, 1.0f));
_setConstBuffer(matHandles[4], cbuffer, VectorF(0.0f, 0.0f, -1.0f), VectorF(0.0f, -1.0f, 0.0f));
_setConstBuffer(matHandles[5], cbuffer, VectorF(0.0f, 0.0f, 1.0f), VectorF(0.0f, 1.0f, 0.0f));

GFXTransformSaver saver;
GFX->setActiveRenderTarget(pTarget);
GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
GFX->setStateBlockByDesc(desc);
GFX->setWorldMatrix(MatrixF::Identity);
GFX->setProjectionMatrix(MatrixF::Identity);
GFX->setCubeTexture(0, pCubemap);
GFX->setShaderConstBuffer(cbuffer);
GFX->setShader(shader);
GFX->drawPrimitive(GFXTriangleList, 0, 3);
pTarget->resolve();

GBitmap *pBitmaps[CubeFaces];
bool error = false;
const bool compressedFormat = ImageUtil::isCompressedFormat(compressionFormat);
for (U32 i = 0; i < CubeFaces; i++)
{
pBitmaps[i] = new GBitmap(faceSize, faceSize, false, renderTargetFmt);
bool result = pTextures[i].copyToBmp(pBitmaps[i]);
if (!result)
{
Con::errorf("CubemapSaver: cubemap number %u failed to copy", i);
error = true;
}
//gen mip maps
pBitmaps[i]->extrudeMipLevels();
}

if (!error)
{
DDSFile *pDds = DDSFile::createDDSCubemapFileFromGBitmaps(pBitmaps);
if (pDds)
{
// non compressed format needs swizzling
if (!compressedFormat)
ImageUtil::swizzleDDS(pDds, Swizzles::bgra);

if(compressedFormat)
ImageUtil::ddsCompress(pDds, compressionFormat);

FileStream stream;
stream.open(path, Torque::FS::File::Write);

if (stream.getStatus() == Stream::Ok)
pDds->write(stream);
else
Con::errorf("CubemapSaver: failed to open file stream for file %s", path.getFullPath().c_str());

SAFE_DELETE(pDds);
}
}

for (U32 i = 0; i < CubeFaces; i++)
SAFE_DELETE(pBitmaps[i]);

//cleaup
GFX->popActiveRenderTarget();
GFX->setTexture(0, NULL);
GFX->setShader(NULL);
GFX->setShaderConstBuffer(NULL);
GFX->setVertexBuffer(NULL);

// End it if we begun it.
if (!sceneBegun)
GFX->endScene();


return true;
}

bool getBitmaps(GFXCubemapHandle cubemap, GFXFormat compressionFormat, GBitmap* faceBitmaps[6])
{
if (!cubemap.isValid())
{
Con::errorf("CubemapSaver: cubemap handle is not valid");
return false;
}

// This can sometimes occur outside a begin/end scene.
const bool sceneBegun = GFX->canCurrentlyRender();
if (!sceneBegun)
GFX->beginScene();

GFXCubemap *pCubemap = cubemap.getPointer();
U32 faceSize = pCubemap->getSize();

ShaderData *shaderData = nullptr;
GFXShaderRef shader = Sim::findObject("CubemapSaveShader", shaderData) ? shaderData->getShader() : nullptr;
if (!shader)
{
Con::errorf("CubemapSaver::save - could not find CubemapSaveShader");
return false;
}

GFXShaderConstHandle *matHandles[CubeFaces];

matHandles[0] = shader->getShaderConstHandle("$matrix0");
matHandles[1] = shader->getShaderConstHandle("$matrix1");
matHandles[2] = shader->getShaderConstHandle("$matrix2");
matHandles[3] = shader->getShaderConstHandle("$matrix3");
matHandles[4] = shader->getShaderConstHandle("$matrix4");
matHandles[5] = shader->getShaderConstHandle("$matrix5");

GFXShaderConstBufferRef cbuffer = shader->allocConstBuffer();

GFXTextureTarget *pTarget = GFX->allocRenderToTextureTarget();
GFX->pushActiveRenderTarget();

GFXFormat renderTargetFmt = GFXFormatR8G8B8A8;
//setup render targets
GFXTexHandle pTextures[CubeFaces];
for (U32 i = 0; i < CubeFaces; i++)
{
pTextures[i].set(faceSize, faceSize, renderTargetFmt,
&GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
1, GFXTextureManager::AA_MATCH_BACKBUFFER);

pTarget->attachTexture(GFXTextureTarget::RenderSlot(GFXTextureTarget::Color0 + i), pTextures[i]);
}

//create stateblock
GFXStateBlockDesc desc;
desc.setZReadWrite(false, false);
desc.samplersDefined = true;
desc.samplers[0].addressModeU = GFXAddressClamp;
desc.samplers[0].addressModeV = GFXAddressClamp;
desc.samplers[0].addressModeW = GFXAddressClamp;
desc.samplers[0].magFilter = GFXTextureFilterLinear;
desc.samplers[0].minFilter = GFXTextureFilterLinear;
desc.samplers[0].mipFilter = GFXTextureFilterLinear;

//yep funky order and rotations with t3d z up
_setConstBuffer(matHandles[0], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(-1.0f, 0.0f, 0.0f));
_setConstBuffer(matHandles[1], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(1.0f, 0.0f, 0.0f));
_setConstBuffer(matHandles[2], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, -1.0f));
_setConstBuffer(matHandles[3], cbuffer, VectorF(0.0f, 1.0f, 0.0f), VectorF(0.0f, 0.0f, 1.0f));
_setConstBuffer(matHandles[4], cbuffer, VectorF(0.0f, 0.0f, -1.0f), VectorF(0.0f, -1.0f, 0.0f));
_setConstBuffer(matHandles[5], cbuffer, VectorF(0.0f, 0.0f, 1.0f), VectorF(0.0f, 1.0f, 0.0f));

GFXTransformSaver saver;
GFX->setActiveRenderTarget(pTarget);
GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
GFX->setStateBlockByDesc(desc);
GFX->setWorldMatrix(MatrixF::Identity);
GFX->setProjectionMatrix(MatrixF::Identity);
GFX->setCubeTexture(0, pCubemap);
GFX->setShaderConstBuffer(cbuffer);
GFX->setShader(shader);
GFX->drawPrimitive(GFXTriangleList, 0, 3);
pTarget->resolve();

bool error = false;
const bool compressedFormat = ImageUtil::isCompressedFormat(compressionFormat);
for (U32 i = 0; i < CubeFaces; i++)
{
//faceBitmaps[i] = new GBitmap(faceSize, faceSize, false, renderTargetFmt);
bool result = pTextures[i].copyToBmp(faceBitmaps[i]);
if (!result)
{
Con::errorf("CubemapSaver: cubemap number %u failed to copy", i);
error = true;
}
//gen mip maps
faceBitmaps[i]->extrudeMipLevels();
}

/*if (!error)
{
DDSFile *pDds = DDSFile::createDDSCubemapFileFromGBitmaps(pBitmaps);
if (pDds)
{
// non compressed format needs swizzling
if (!compressedFormat)
ImageUtil::swizzleDDS(pDds, Swizzles::bgra);
if (compressedFormat)
ImageUtil::ddsCompress(pDds, compressionFormat);
FileStream stream;
stream.open(path, Torque::FS::File::Write);
if (stream.getStatus() == Stream::Ok)
pDds->write(stream);
else
Con::errorf("CubemapSaver: failed to open file stream for file %s", path.getFullPath().c_str());
SAFE_DELETE(pDds);
}
}
for (U32 i = 0; i < CubeFaces; i++)
SAFE_DELETE(pBitmaps[i]);*/

//cleaup
GFX->popActiveRenderTarget();
GFX->setTexture(0, NULL);
GFX->setShader(NULL);
GFX->setShaderConstBuffer(NULL);
GFX->setVertexBuffer(NULL);

// End it if we begun it.
if (!sceneBegun)
GFX->endScene();

if (error)
return false;

return true;
}
}
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
// Copyright (c) 2016 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
@@ -20,19 +20,22 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

// dllmain.cpp : Implementation of DllMain.
#ifndef _CUBEMAP_SAVER_H_
#define _CUBEMAP_SAVER_H_

#include "stdafx.h"
#include "resource.h"
#include "IEWebGamePlugin_i.h"
#include "dllmain.h"
#include "../common/webCommon.h"
#ifndef _GFXCUBEMAP_H_
#include "gfx/gfxCubemap.h"
#endif
#ifndef __RESOURCE_H__
#include "core/resource.h"
#endif

CIEWebGamePluginModule _AtlModule;

// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
namespace CubemapSaver
{
WebCommon::gPluginModule = (HMODULE) hInstance;
return _AtlModule.DllMain(dwReason, lpReserved);
}
// save cubemap handle to a dds cubemap with optional compression
bool save(GFXCubemapHandle cubemap, const Torque::Path &path, GFXFormat compressionFormat = GFXFormat_FIRST);

bool getBitmaps(GFXCubemapHandle cubemap, GFXFormat compressionFormat, GBitmap* faceBitmaps[6]);
};

#endif
@@ -39,7 +39,6 @@
class Stream;
class GBitmap;


struct DDSFile
{
enum DDSFlags
@@ -297,6 +297,7 @@ void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool
case GFXFormatR8G8B8X8:
case GFXFormatR8G8B8A8: mBytesPerPixel = 4;
break;
case GFXFormatL16:
case GFXFormatR5G6B5:
case GFXFormatR5G5B5A1: mBytesPerPixel = 2;
break;
@@ -328,7 +329,6 @@ void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool
mNumMipLevels++;
allocPixels += currWidth * currHeight * mBytesPerPixel;
} while (currWidth != 1 || currHeight != 1);

U32 expectedMips = mFloor(mLog2(mMax(in_width, in_height))) + 1;
AssertFatal(mNumMipLevels == expectedMips, "GBitmap::allocateBitmap: mipmap count wrong");
}
@@ -371,6 +371,7 @@ void GBitmap::allocateBitmapWithMips(const U32 in_width, const U32 in_height, co
case GFXFormatR8G8B8X8:
case GFXFormatR8G8B8A8: mBytesPerPixel = 4;
break;
case GFXFormatL16:
case GFXFormatR5G6B5:
case GFXFormatR5G5B5A1: mBytesPerPixel = 2;
break;
@@ -679,6 +680,7 @@ bool GBitmap::checkForTransparency()
{
// Non-transparent formats
case GFXFormatL8:
case GFXFormatL16:
case GFXFormatR8G8B8:
case GFXFormatR5G6B5:
break;
@@ -714,31 +716,31 @@ bool GBitmap::checkForTransparency()
//------------------------------------------------------------------------------
LinearColorF GBitmap::sampleTexel(F32 u, F32 v) const
{
LinearColorF col(0.5f, 0.5f, 0.5f);
// normally sampling wraps all the way around at 1.0,
// but locking doesn't support this, and we seem to calc
// the uv based on a clamped 0 - 1...
Point2F max((F32)(getWidth()-1), (F32)(getHeight()-1));
Point2F posf;
posf.x = mClampF(((u) * max.x), 0.0f, max.x);
posf.y = mClampF(((v) * max.y), 0.0f, max.y);
Point2I posi((S32)posf.x, (S32)posf.y);

const U8 *buffer = getBits();
U32 lexelindex = ((posi.y * getWidth()) + posi.x) * mBytesPerPixel;

if(mBytesPerPixel == 2)
{
//U16 *buffer = (U16 *)lockrect->pBits;
}
else if(mBytesPerPixel > 2)
{
col.red = F32(buffer[lexelindex + 0]) / 255.0f;
LinearColorF col(0.5f, 0.5f, 0.5f);
// normally sampling wraps all the way around at 1.0,
// but locking doesn't support this, and we seem to calc
// the uv based on a clamped 0 - 1...
Point2F max((F32)(getWidth()-1), (F32)(getHeight()-1));
Point2F posf;
posf.x = mClampF(((u) * max.x), 0.0f, max.x);
posf.y = mClampF(((v) * max.y), 0.0f, max.y);
Point2I posi((S32)posf.x, (S32)posf.y);

const U8 *buffer = getBits();
U32 lexelindex = ((posi.y * getWidth()) + posi.x) * mBytesPerPixel;

if(mBytesPerPixel == 2)
{
//U16 *buffer = (U16 *)lockrect->pBits;
}
else if(mBytesPerPixel > 2)
{
col.red = F32(buffer[lexelindex + 0]) / 255.0f;
col.green = F32(buffer[lexelindex + 1]) / 255.0f;
col.blue = F32(buffer[lexelindex + 2]) / 255.0f;
}
col.blue = F32(buffer[lexelindex + 2]) / 255.0f;
}

return col;
return col;
}

//--------------------------------------------------------------------------
@@ -754,7 +756,8 @@ bool GBitmap::getColor(const U32 x, const U32 y, ColorI& rColor) const
case GFXFormatL8:
rColor.set( *pLoc, *pLoc, *pLoc, *pLoc );
break;

case GFXFormatL16:
rColor.set(U8(U16((pLoc[0] << 8) + pLoc[2])), 0, 0, 0);
case GFXFormatR8G8B8:
case GFXFormatR8G8B8X8:
rColor.set( pLoc[0], pLoc[1], pLoc[2], 255 );
@@ -803,6 +806,10 @@ bool GBitmap::setColor(const U32 x, const U32 y, const ColorI& rColor)
*pLoc = rColor.alpha;
break;

case GFXFormatL16:
dMemcpy(pLoc, &rColor, 2 * sizeof(U8));
break;

case GFXFormatR8G8B8:
dMemcpy( pLoc, &rColor, 3 * sizeof( U8 ) );
break;
@@ -1122,6 +1129,7 @@ bool GBitmap::read(Stream& io_rStream)
break;
case GFXFormatR8G8B8A8: mBytesPerPixel = 4;
break;
case GFXFormatL16:
case GFXFormatR5G6B5:
case GFXFormatR5G5B5A1: mBytesPerPixel = 2;
break;
@@ -240,7 +240,7 @@ static bool sReadPNG(Stream &stream, GBitmap *bitmap)
png_set_expand(png_ptr);

if (bit_depth == 16)
format = GFXFormatR5G6B5;
format = GFXFormatL16;
else
format = GFXFormatA8;
}
@@ -276,7 +276,7 @@ static bool sReadPNG(Stream &stream, GBitmap *bitmap)
AssertFatal(rowBytes == width * 4,
"Error, our rowbytes are incorrect for this transform... (4)");
}
else if (format == GFXFormatR5G6B5)
else if (format == GFXFormatL16)
{
AssertFatal(rowBytes == width * 2,
"Error, our rowbytes are incorrect for this transform... (2)");
@@ -401,7 +401,7 @@ static bool _writePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel, U32
NULL, // compression type
NULL); // filter type
}
else if (format == GFXFormatR5G6B5)
else if (format == GFXFormatR5G6B5)
{
png_set_IHDR(png_ptr, info_ptr,
width, height, // the width & height
@@ -339,9 +339,9 @@ inline void GenericConstBuffer::setDirty( bool dirty )

inline const U8* GenericConstBuffer::getDirtyBuffer( U32 *start, U32 *size )
{
AssertFatal( isDirty(), "GenericConstBuffer::getDirtyBuffer() - Buffer is not dirty!" );
AssertFatal( mDirtyEnd > mDirtyStart, "GenericConstBuffer::getDirtyBuffer() - Dirty range is invalid!" );
AssertFatal( mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!" );
AssertFatal(isDirty(), "GenericConstBuffer::getDirtyBuffer() - Buffer is not dirty!");
AssertFatal(mDirtyEnd > mDirtyStart, "GenericConstBuffer::getDirtyBuffer() - Dirty range is invalid!");
AssertFatal(mBuffer, "GenericConstBuffer::getDirtyBuffer() - Buffer is empty!");

// Use the area we calculated during internalSet.
*size = mDirtyEnd - mDirtyStart;
@@ -51,6 +51,7 @@ class GFXCubemap : public StrongRefBase, public GFXResource
U32 _zUpFaceIndex(const U32 index);

U32 mMipMapLevels;

public:

/// Create a static cubemap from a list of 6 face textures.
@@ -189,7 +189,7 @@ GFXDevice::GFXDevice()
#elif defined TORQUE_OS_MAC
GFXShader::addGlobalMacro( "TORQUE_OS_MAC" );
#elif defined TORQUE_OS_LINUX
GFXShader::addGlobalMacro( "TORQUE_OS_LINUX" );
GFXShader::addGlobalMacro( "TORQUE_OS_LINUX" );
#endif

mStereoTargets[0] = NULL;
@@ -809,7 +809,6 @@ class GFXDevice
virtual U32 getNumRenderTargets() const = 0;

virtual void setShader( GFXShader *shader, bool force = false ) {}
virtual void disableShaders( bool force = false ) {} // TODO Remove when T3D 4.0

/// Set the buffer! (Actual set happens on the next draw call, just like textures, state blocks, etc)
void setShaderConstBuffer(GFXShaderConstBuffer* buffer);
@@ -24,6 +24,9 @@
#define _GFXENUMS_H_

#include "core/util/fourcc.h"
#ifndef _PLATFORMASSERT_H_
#include "platform/platformAssert.h"
#endif

// These are for the enum translation. It will help with porting to other platforms
// and API's.
@@ -52,6 +52,11 @@ GFXTexHandle::GFXTexHandle( const String &texName, GFXTextureProfile *profile, c
set( texName, profile, desc );
}

GFXTexHandle::GFXTexHandle(const String &texNameR, const String &texNameG, const String &texNameB, const String &texNameA, U32 inputKey[4], GFXTextureProfile *profile, const String &desc)
{
set(texNameR, texNameG, texNameB, texNameA, inputKey, profile, desc);
}

bool GFXTexHandle::set( const String &texName, GFXTextureProfile *profile, const String &desc )
{
// Clear the existing texture first, so that
@@ -70,6 +75,24 @@ bool GFXTexHandle::set( const String &texName, GFXTextureProfile *profile, const
return isValid();
}

bool GFXTexHandle::set(const String &texNameR, const String &texNameG, const String &texNameB, const String &texNameA, U32 inputKey[4], GFXTextureProfile *profile, const String &desc)
{
// Clear the existing texture first, so that
// its memory is free for the new allocation.
free();

// Create and set the new texture.
AssertFatal( texNameR.isNotEmpty(), "Texture name is empty" );
StrongObjectRef::set( TEXMGR->createCompositeTexture( texNameR, texNameG, texNameB, texNameA, inputKey, profile ) );

#ifdef TORQUE_DEBUG
if ( getPointer() )
getPointer()->mDebugDescription = desc;
#endif

return isValid();
}

GFXTexHandle::GFXTexHandle( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc )
{
set( bmp, profile, deleteBmp, desc );
@@ -46,6 +46,10 @@ class GFXTexHandle : public StrongRefPtr<GFXTextureObject>
GFXTexHandle( const String &texName, GFXTextureProfile *profile, const String &desc );
bool set( const String &texName, GFXTextureProfile *profile, const String &desc );

// load composite
GFXTexHandle(const String &texNameR, const String &texNameG, const String &texNameB, const String &texNameA, U32 inputKey[4], GFXTextureProfile *profile, const String &desc);
bool set( const String &texNameR, const String &texNameG, const String &texNameB, const String &texNameA, U32 inputKey[4], GFXTextureProfile *profile, const String &desc );

// register texture
GFXTexHandle( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc );
bool set( GBitmap *bmp, GFXTextureProfile *profile, bool deleteBmp, const String &desc );
@@ -255,7 +255,7 @@ GFXTextureObject *GFXTextureManager::_lookupTexture( const char *hashName, const
if (ret && (ret->mProfile->compareFlags(*profile)))
return ret;
else if (ret)
Con::warnf("GFXTextureManager::_lookupTexture: Cached texture %s has a different profile flag", hashName);
Con::warnf("GFXTextureManager::_lookupTexture: Cached texture %s has different profile flags: (%s,%s) ", hashName, ret->mProfile->getName().c_str(), profile->getName().c_str());

return NULL;
}
@@ -1122,7 +1122,8 @@ GFXTextureObject *GFXTextureManager::createCompositeTexture(GBitmap*bmp[4], U32
}

U8 rChan, gChan, bChan, aChan;

GBitmap *outBitmap = new GBitmap();
outBitmap->allocateBitmap(bmp[0]->getWidth(), bmp[0]->getHeight(),false, GFXFormatR8G8B8A8);
//pack additional bitmaps into the origional
for (U32 x = 0; x < bmp[0]->getWidth(); x++)
{
@@ -1145,20 +1146,23 @@ GFXTextureObject *GFXTextureManager::createCompositeTexture(GBitmap*bmp[4], U32
else
aChan = 255;

bmp[0]->setColor(x, y, ColorI(rChan, gChan, bChan, aChan));
outBitmap->setColor(x, y, ColorI(rChan, gChan, bChan, aChan));
}
}

GFXTextureObject *cacheHit = _lookupTexture(resourceName, profile);
if (cacheHit != NULL)
{
// Con::errorf("Cached texture '%s'", (resourceName.isNotEmpty() ? resourceName.c_str() : "unknown"));
if (deleteBmp)
delete bmp[0];
if (deleteBmp)
{
delete outBitmap;
delete[] bmp;
}
return cacheHit;
}

return _createTexture(bmp[0], resourceName, profile, deleteBmp, NULL);
return _createTexture(outBitmap, resourceName, profile, deleteBmp, NULL);
}

GFXTextureObject* GFXTextureManager::_findPooledTexure( U32 width,
@@ -300,7 +300,6 @@ template<class T> inline const GFXVertexFormat* getGFXVertexFormat();

#define GFX_VERTEX_STRUCT struct


/// The vertex format declaration which is usally placed in your header
/// file. It should be used in conjunction with the implementation macro.
///
@@ -172,10 +172,10 @@ void GFXGLDevice::initGLState()
#endif

PlatformGL::setVSync(smDisableVSync ? 0 : 1);

//install vsync callback
Con::NotifyDelegate clbk(this, &GFXGLDevice::vsyncCallback);
Con::addVariableNotify("$pref::Video::disableVerticalSync", clbk);
Con::NotifyDelegate clbk( this, &GFXGLDevice::vsyncCallback );
Con::addVariableNotify( "$pref::Video::disableVerticalSync", clbk );

//OpenGL 3 need a binded VAO for render
GLuint vao;
@@ -240,6 +240,7 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
mModelViewProjSC[i] = NULL;

mOpenglStateCache = new GFXGLStateCache;

}

GFXGLDevice::~GFXGLDevice()
@@ -208,7 +208,7 @@ class GFXGLDevice : public GFXDevice
friend class GFXGLPrimitiveBuffer;
friend class GFXGLVertexBuffer;

static GFXAdapter::CreateDeviceInstanceDelegate mCreateDeviceInstance;
static GFXAdapter::CreateDeviceInstanceDelegate mCreateDeviceInstance;

U32 mAdapterIndex;

@@ -25,28 +25,40 @@
#include "gfx/gl/tGL/tGL.h"

GFXGLOcclusionQuery::GFXGLOcclusionQuery(GFXDevice* device) :
GFXOcclusionQuery(device), mQuery(-1)
GFXOcclusionQuery(device), mQuery(-1), mTesting(false)
{

}

GFXGLOcclusionQuery::~GFXGLOcclusionQuery()
{
glDeleteQueries(1, &mQuery);
glDeleteQueries(1, &mQuery);
}

bool GFXGLOcclusionQuery::begin()
{
if(mQuery == -1)
if (GFXDevice::getDisableOcclusionQuery())
return true;

if (!glIsQuery(mQuery))
glGenQueries(1, &mQuery);

if (!mTesting)
{
glBeginQuery(GL_SAMPLES_PASSED, mQuery);
mTesting = true;
}
return true;
}

void GFXGLOcclusionQuery::end()
{
if (GFXDevice::getDisableOcclusionQuery())
return;

if (!glIsQuery(mQuery))
return;
glEndQuery(GL_SAMPLES_PASSED);
mTesting = false;
}

GFXOcclusionQuery::OcclusionQueryStatus GFXGLOcclusionQuery::getStatus(bool block, U32* data)
@@ -55,14 +67,27 @@ GFXOcclusionQuery::OcclusionQueryStatus GFXGLOcclusionQuery::getStatus(bool bloc
// then your system is GPU bound.
PROFILE_SCOPE(GFXGLOcclusionQuery_getStatus);

if(mQuery == -1)
if (GFXDevice::getDisableOcclusionQuery())
return NotOccluded;

if (!glIsQuery(mQuery))
return NotOccluded;

GLint numPixels = 0;
GLint queryDone = false;

if (block)
queryDone = true;
while (!queryDone)
{
//If we're stalled out, proceed with worst-case scenario -BJR
if (GFX->mFrameTime->getElapsedMs()>4)
{
this->begin();
this->end();
return NotOccluded;
}
glGetQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &queryDone);
}
else
glGetQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &queryDone);

@@ -92,4 +117,4 @@ const String GFXGLOcclusionQuery::describeSelf() const
{
// We've got nothing
return String();
}
}
@@ -44,6 +44,7 @@ class GFXGLOcclusionQuery : public GFXOcclusionQuery

private:
U32 mQuery;
bool mTesting;
};

#endif // _GFX_GL_OCCLUSIONQUERY_H_
@@ -34,7 +34,6 @@

#define CHECK_AARG(pos, name) static StringTableEntry attr_##name = StringTable->insert(#name); if (argName == attr_##name) { glBindAttribLocation(mProgram, pos, attr_##name); continue; }


class GFXGLShaderConstHandle : public GFXShaderConstHandle
{
friend class GFXGLShader;
@@ -414,9 +413,9 @@ bool GFXGLShader::_init()
// Don't initialize empty shaders.
if ( mVertexFile.isEmpty() && mPixelFile.isEmpty() )
return false;

clearShaders();

mProgram = glCreateProgram();

// Set the macros and add the global ones.
@@ -438,15 +437,15 @@ bool GFXGLShader::_init()
// Compile the vertex and pixel shaders if specified.
if(!mVertexFile.isEmpty())
compiledVertexShader = initShader(mVertexFile, true, macros);

macros.last().name = "TORQUE_PIXEL_SHADER";
if(!mPixelFile.isEmpty())
compiledPixelShader = initShader(mPixelFile, false, macros);

// If either shader was present and failed to compile, bail.
if(!compiledVertexShader || !compiledPixelShader)
return false;

// Link it!
glLinkProgram( mProgram );

@@ -485,7 +484,7 @@ bool GFXGLShader::_init()
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord8, vTexCoord8);
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord9, vTexCoord9);
}

//always have OUT_col
glBindFragDataLocation(mProgram, 0, "OUT_col");
// Check OUT_colN
@@ -496,7 +495,7 @@ bool GFXGLShader::_init()
GLint location = glGetFragDataLocation(mProgram, buffer);
if(location>0)
glBindFragDataLocation(mProgram, i, buffer);

}

// Link it again!
@@ -520,34 +519,35 @@ bool GFXGLShader::_init()
{
Con::errorf( "GFXGLShader::init - Error linking shader!" );
Con::errorf( "Program %s / %s: %s",
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
}
}
else if ( smLogWarnings )
{
Con::warnf( "Program %s / %s: %s",
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
}
}


// If we failed to link, bail.
if ( linkStatus == GL_FALSE )
return false;

initConstantDescs();
initConstantDescs();
initHandles();

// Notify Buffers we might have changed in size.
// If this was our first init then we won't have any activeBuffers
// Notify Buffers we might have changed in size.
// If this was our first init then we won't have any activeBuffers
// to worry about unnecessarily calling.
Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
for ( ; biter != mActiveBuffers.end(); biter++ )
for ( ; biter != mActiveBuffers.end(); biter++ )
((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this );

return true;
}


void GFXGLShader::initConstantDescs()
{
mConstants.clear();
@@ -1017,7 +1017,7 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader,
const char *newLine = "\r\n";
buffers.push_back( dStrdup( newLine ) );
lengths.push_back( dStrlen( newLine ) );

// Now add all the macros.
for( U32 i = 0; i < macros.size(); i++ )
{
@@ -40,14 +40,14 @@ GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
mCachedHashValue(desc.getHashValue())
{
if( !GFXGL->mCapabilities.samplerObjects )
return;
return;

static Map<GFXSamplerStateDesc, U32> mSamplersMap;

for(int i = 0; i < TEXTURE_STAGE_COUNT; ++i)
{
GLuint &id = mSamplerObjects[i];
GFXSamplerStateDesc &ssd = mDesc.samplers[i];
for(int i = 0; i < TEXTURE_STAGE_COUNT; ++i)
{
GLuint &id = mSamplerObjects[i];
GFXSamplerStateDesc &ssd = mDesc.samplers[i];
Map<GFXSamplerStateDesc, U32>::Iterator itr = mSamplersMap.find(ssd);
if(itr == mSamplersMap.end())
{
@@ -58,7 +58,7 @@ GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);

//compare modes
const bool comparison = ssd.samplerFunc != GFXCmpNever;
glSamplerParameteri(id, GL_TEXTURE_COMPARE_MODE, comparison ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE );
@@ -71,7 +71,7 @@ GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
}
else
id = itr->value;
}
}
}

GFXGLStateBlock::~GFXGLStateBlock()
@@ -180,9 +180,9 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
{
if(!oldState || oldState->mSamplerObjects[i] != mSamplerObjects[i])
glBindSampler(i, mSamplerObjects[i] );
glBindSampler(i, mSamplerObjects[i] );
}
}
}

// TODO: states added for detail blend
}
@@ -368,12 +368,11 @@ void GFXGLWindowTarget::_makeContextCurrent()
{
HWND hwnd = GETHWND(getWindow());
HDC hdc = GetDC(hwnd);

if (!wglMakeCurrent(hdc, (HGLRC)mContext))
{
//HRESULT if needed for debug
//HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
AssertFatal(false, "GFXGLWindowTarget::_makeContextCurrent() - cannot make our context current.");
}

}
@@ -34,6 +34,7 @@
#include "scene/sceneManager.h"
#include "console/engineAPI.h"
#include "math/mathUtils.h"
#include "gfx/bitmap/cubemapSaver.h"

IMPLEMENT_CONOBJECT( CubemapData );

@@ -145,10 +146,10 @@ void CubemapData::updateFaces()
{
if (!mCubeFaceFile[i].isEmpty())
{
if (!mCubeFace[i].set(mCubeFaceFile[i], &GFXStaticTextureProfile, avar("%s() - mCubeFace[%d] (line %d)", __FUNCTION__, i, __LINE__)))
{
initSuccess = false;
Con::errorf("CubemapData::createMap - Failed to load texture '%s'", mCubeFaceFile[i].c_str());
if (!mCubeFace[i].set(mCubeFaceFile[i], &GFXStaticTextureProfile, avar("%s() - mCubeFace[%d] (line %d)", __FUNCTION__, i, __LINE__)))
{
initSuccess = false;
Con::errorf("CubemapData::createMap - Failed to load texture '%s'", mCubeFaceFile[i].c_str());
}
}
}
@@ -183,3 +184,18 @@ DefineEngineMethod( CubemapData, getFilename, const char*, (),,
{
return object->getFilename();
}

DefineEngineMethod(CubemapData, save, void, (const char* filename, const GFXFormat format), ("", GFXFormatBC1),
"Returns the script filename of where the CubemapData object was "
"defined. This is used by the material editor.")
{
if (filename == "")
filename = object->getName();

//add dds extension if needed
String finalName = String(filename);
if(!finalName.endsWith(".dds") || !finalName.endsWith(".DDS"))
finalName += String(".dds");

CubemapSaver::save(object->mCubemap, finalName, format);
}
@@ -344,7 +344,7 @@ DefineEngineFunction( stopVideoCapture, void, (),,

DefineEngineFunction( playJournalToVideo, void,
( const char *journalFile, const char *videoFile, const char *encoder, F32 framerate, Point2I resolution ),
( nullAsType<const char*>(), "THEORA", 30.0f, Point2I::Zero ),
( nullAsType<const char*>(), "THEORA", 30.0f, Point2I::Zero),
"Load a journal file and capture it video.\n"
"@ingroup Rendering\n" )
{
@@ -132,9 +132,9 @@ namespace
desc.setCullMode(GFXCullNone);
desc.setZReadWrite(false);
desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
GFX->setStateBlockByDesc( desc );

GFX->setupGenericShaders();
GFX->setStateBlockByDesc( desc );
GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
}
}
@@ -1830,7 +1830,7 @@ void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
if (GuiOffscreenCanvas::sList.size() != 0)
{
// Reset the entire state since oculus shit will have barfed it.
//GFX->disableShaders(true);

GFX->updateStates(true);

for (Vector<GuiOffscreenCanvas*>::iterator itr = GuiOffscreenCanvas::sList.begin(); itr != GuiOffscreenCanvas::sList.end(); itr++)
@@ -58,6 +58,7 @@ IMPLEMENT_CALLBACK( GuiShapeEdPreview, onThreadPosChanged, void, ( F32 pos, bool
"Called when the position of the active thread has changed, such as during "
"playback." );

extern GFXCubemap * gLevelEnvMap;

GuiShapeEdPreview::GuiShapeEdPreview()
: mOrbitDist( 5.0f ),
@@ -1367,6 +1368,7 @@ void GuiShapeEdPreview::renderWorld(const RectI &updateRect)
// Set up our TS render state here.
TSRenderState rdata;
rdata.setSceneState(&state);
rdata.setCubemap(gLevelEnvMap);

LIGHTMGR->unregisterAllLights();
LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mFakeSun );
@@ -41,8 +41,8 @@
#include "math/util/matrixSet.h"
#include "console/consoleTypes.h"

const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "LightInfo" );
const String AdvancedLightBinManager::smBufferName( "lightinfo" );
const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "directLighting" );
const String AdvancedLightBinManager::smBufferName( "directLighting" );

ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality;
bool AdvancedLightBinManager::smPSSMDebugRender = false;
@@ -130,7 +130,7 @@ AdvancedLightBinManager::AdvancedLightBinManager( AdvancedLightManager *lm /* =
// We want a full-resolution buffer
mTargetSizeType = RenderTexTargetBinManager::WindowSize;

mMRTLightmapsDuringDeferred = false;
mMRTLightmapsDuringDeferred = true;

Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials );
Con::addVariableNotify( "$pref::Shadows::filterMode", callback );
@@ -252,9 +252,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
if ( !_onPreRender( state ) )
return;

// Clear as long as there isn't MRT population of light buffer with lightmap data
if ( !MRTLightmapsDuringDeferred() )
GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);

// Restore transforms
MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
@@ -267,7 +265,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
sgData.init( state );

// There are cases where shadow rendering is disabled.
const bool disableShadows = /*state->isReflectPass() || */ShadowMapPass::smDisableShadows;
const bool disableShadows = state->isReflectPass() || ShadowMapPass::smDisableShadows;

// Pick the right material for rendering the sunlight... we only
// cast shadows when its enabled and we're not in a reflection.
@@ -183,6 +183,8 @@ class AdvancedLightBinManager : public RenderTexTargetBinManager
void setLightParameters( const LightInfo *light, const SceneRenderState* renderState, const MatrixF &worldViewOnly );
};



protected:

struct LightBinEntry
@@ -232,6 +234,7 @@ class AdvancedLightBinManager : public RenderTexTargetBinManager
GFXVertexBufferHandle<FarFrustumQuadVert> mFarFrustumQuadVerts;


protected:
//void _createMaterials();

void _setupPerFrameParameters( const SceneRenderState *state );
@@ -36,7 +36,7 @@ void DeferredRTLightingFeatGLSL::processPixMacros( Vector<GFXShaderMacro> &macro
const MaterialFeatureData &fd )
{
// Skip deferred features, and use forward shading instead
if ( fd.features[MFT_ForwardShading] )
if ( !fd.features[MFT_isDeferred] )
{
Parent::processPixMacros( macros, fd );
return;
@@ -56,7 +56,7 @@ void DeferredRTLightingFeatGLSL::processVert( Vector<ShaderComponent*> &compon
const MaterialFeatureData &fd )
{
// Skip deferred features, and use forward shading instead
if ( fd.features[MFT_ForwardShading] )
if ( !fd.features[MFT_isDeferred] )
{
Parent::processVert( componentList, fd );
return;
@@ -79,7 +79,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
const MaterialFeatureData &fd )
{
// Skip deferred features, and use forward shading instead
if ( fd.features[MFT_ForwardShading] )
if ( !fd.features[MFT_isDeferred] )
{
Parent::processPix( componentList, fd );
return;
@@ -98,7 +98,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
uvScene->setName( "uvScene" );
LangElement *uvSceneDecl = new DecOp( uvScene );

String rtParamName = String::ToString( "rtParams%s", "lightInfoBuffer" );
String rtParamName = String::ToString( "rtParams%s", "directLightingBuffer" );
Var *rtParams = (Var*) LangElement::find( rtParamName );
if( !rtParams )
{
@@ -121,7 +121,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
// create texture var
Var *lightInfoBuffer = new Var;
lightInfoBuffer->setType( "sampler2D" );
lightInfoBuffer->setName( "lightInfoBuffer" );
lightInfoBuffer->setName( "directLightingBuffer" );
lightInfoBuffer->uniform = true;
lightInfoBuffer->sampler = true;
lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
@@ -175,7 +175,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
ShaderFeature::Resources DeferredRTLightingFeatGLSL::getResources( const MaterialFeatureData &fd )
{
// Skip deferred features, and use forward shading instead
if ( fd.features[MFT_ForwardShading] )
if ( !fd.features[MFT_isDeferred] )
return Parent::getResources( fd );

// HACK: See DeferredRTLightingFeatGLSL::setTexData.
@@ -193,7 +193,7 @@ void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat,
U32 &texIndex )
{
// Skip deferred features, and use forward shading instead
if ( fd.features[MFT_ForwardShading] )
if ( !fd.features[MFT_isDeferred] )
{
Parent::setTexData( stageDat, fd, passData, texIndex );
return;
@@ -207,7 +207,7 @@ void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat,
mLastTexIndex = texIndex;

passData.mTexType[ texIndex ] = Material::TexTarget;
passData.mSamplerNames[ texIndex ]= "lightInfoBuffer";
passData.mSamplerNames[ texIndex ]= "directLightingBuffer";
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
}
}
@@ -227,7 +227,7 @@ void DeferredBumpFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis

const bool useTexAnim = fd.features[MFT_TexAnim];
// Make sure there are texcoords
if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap] )
if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap])
{

getOutTexCoord( "texCoord",
@@ -245,7 +245,7 @@ void DeferredBumpFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis
output = meta;
}
else if ( fd.materialFeatures[MFT_NormalsOut] ||
fd.features[MFT_ForwardShading] ||
!fd.features[MFT_isDeferred] ||
!fd.features[MFT_RTLighting] )
{
Parent::processVert( componentList, fd );
@@ -310,6 +310,47 @@ void DeferredBumpFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) );
}

if (fd.features.hasFeature(MFT_NormalDamage))
{
bumpMap = new Var;
bumpMap->setType("sampler2D");
bumpMap->setName("normalDamageMap");
bumpMap->uniform = true;
bumpMap->sampler = true;
bumpMap->constNum = Var::getTexUnitNum();

texCoord = getInTexCoord("texCoord", "vec2", componentList);
texOp = new GenOp("tex2D(@, @)", bumpMap, texCoord);

Var *damageBump = new Var;
damageBump->setName("damageBump");
damageBump->setType("vec4");
meta->addStatement(expandNormalMap(texOp, new DecOp(damageBump), damageBump, fd));

Var *damage = (Var*)LangElement::find("materialDamage");
if (!damage){
damage = new Var("materialDamage", "float");
damage->uniform = true;
damage->constSortPos = cspPrimitive;
}
Var *floor = (Var*)LangElement::find("materialDamageMin");
if (!floor){
floor = new Var("materialDamageMin", "float");
floor->uniform = true;
floor->constSortPos = cspPrimitive;
}

Var *damageResult = (Var*)LangElement::find("damageResult");
if (!damageResult){
damageResult = new Var("damageResult", "float");
meta->addStatement(new GenOp(" @ = max(@,@);\r\n", new DecOp(damageResult), floor, damage));
}
else
meta->addStatement(new GenOp(" @ = max(@,@);\r\n", damageResult, floor, damage));

meta->addStatement(new GenOp(" @.xyz = mix(@.xyz, @.xyz, @);\r\n", bumpNorm, bumpNorm, damageBump, damageResult));
}

// This var is read from GBufferConditionerGLSL and
// used in the deferred output.
//
@@ -382,7 +423,7 @@ void DeferredBumpFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
}
}
else if ( fd.materialFeatures[MFT_NormalsOut] ||
fd.features[MFT_ForwardShading] ||
!fd.features[MFT_isDeferred] ||
!fd.features[MFT_RTLighting] )
{
Parent::processPix( componentList, fd );
@@ -413,7 +454,7 @@ void DeferredBumpFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatureData &fd )
{
if ( fd.materialFeatures[MFT_NormalsOut] ||
fd.features[MFT_ForwardShading] ||
!fd.features[MFT_isDeferred] ||
fd.features[MFT_Parallax] ||
!fd.features[MFT_RTLighting] )
return Parent::getResources( fd );
@@ -432,7 +473,6 @@ ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatu
res.numTexReg += 1;
}
}

return res;
}

@@ -442,7 +482,7 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat,
U32 &texIndex )
{
if ( fd.materialFeatures[MFT_NormalsOut] ||
fd.features[MFT_ForwardShading] ||
!fd.features[MFT_isDeferred] ||
!fd.features[MFT_RTLighting] )
{
Parent::setTexData( stageDat, fd, passData, texIndex );
@@ -461,6 +501,13 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat,
passData.mSamplerNames[texIndex] = "detailBumpMap";
passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_DetailNormalMap);
}

if (fd.features.hasFeature(MFT_NormalDamage))
{
passData.mTexType[texIndex] = Material::Bump;
passData.mSamplerNames[texIndex] = "normalDamageMap";
passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_NormalDamage);
}
}
else if (!fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] &&
( fd.features[MFT_DeferredConditioner] ||
@@ -477,14 +524,21 @@ void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat,
passData.mSamplerNames[ texIndex ] = "detailBumpMap";
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap );
}

if (fd.features.hasFeature(MFT_NormalDamage))
{
passData.mTexType[texIndex] = Material::Bump;
passData.mSamplerNames[texIndex] = "normalDamageMap";
passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_NormalDamage);
}
}
}


void DeferredPixelSpecularGLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] )
{
Parent::processVert( componentList, fd );
return;
@@ -495,7 +549,7 @@ void DeferredPixelSpecularGLSL::processVert( Vector<ShaderComponent*> &component
void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] )
{
Parent::processPix( componentList, fd );
return;
@@ -518,26 +572,28 @@ void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &component
specCol->constSortPos = cspPotentialPrimitive;
}

Var *specPow = new Var;
specPow->setType( "float" );
specPow->setName( "specularPower" );

// If the gloss map flag is set, than the specular power is in the alpha
// channel of the specular map
if( fd.features[ MFT_GlossMap ] )
meta->addStatement( new GenOp( " @ = @.a * 255;\r\n", new DecOp( specPow ), specCol ) );
else
Var *smoothness = (Var*)LangElement::find("smoothness");
if (!smoothness)
{
specPow->uniform = true;
specPow->constSortPos = cspPotentialPrimitive;
smoothness = new Var("smoothness", "float");

// If the gloss map flag is set, than the specular power is in the alpha
// channel of the specular map
if (fd.features[MFT_GlossMap])
meta->addStatement(new GenOp(" @ = @.a;\r\n", new DecOp(smoothness), specCol));
else
{
smoothness->uniform = true;
smoothness->constSortPos = cspPotentialPrimitive;
}
}

Var *specStrength = (Var*)LangElement::find( "specularStrength" );
if (!specStrength)
Var *metalness = (Var*)LangElement::find("metalness");
if (!metalness)
{
specStrength = new Var( "specularStrength", "float" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
metalness = new Var("metalness", "float");
metalness->uniform = true;
metalness->constSortPos = cspPotentialPrimitive;
}

Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" );
@@ -557,7 +613,7 @@ void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &component
}
// (a^m)^n = a^(m*n)
meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n",
specDecl, d_specular, specPow, specStrength ) );
specDecl, d_specular, smoothness, metalness));

LangElement *specMul = new GenOp( "vec4( @.rgb, 0 ) * @", specCol, specular );
LangElement *final = specMul;
@@ -577,7 +633,7 @@ void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &component

ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const MaterialFeatureData &fd )
{
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] )
return Parent::getResources( fd );

Resources res;
@@ -588,7 +644,7 @@ ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const Material
ShaderFeature::Resources DeferredMinnaertGLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] )
if( fd.features[MFT_isDeferred] && fd.features[MFT_RTLighting] )
{
res.numTex = 1;
res.numTexReg = 1;
@@ -601,7 +657,7 @@ void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat,
RenderPassData &passData,
U32 &texIndex )
{
if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] )
if( fd.features[MFT_isDeferred] && fd.features[MFT_RTLighting] )
{
NamedTexTarget *texTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName);
if ( texTarget )
@@ -616,7 +672,7 @@ void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat,
void DeferredMinnaertGLSL::processPixMacros( Vector<GFXShaderMacro> &macros,
const MaterialFeatureData &fd )
{
if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] )
if( fd.features[MFT_isDeferred] && fd.features[MFT_RTLighting] )
{
// Pull in the uncondition method for the g buffer
NamedTexTarget *texTarget = NamedTexTarget::find( RenderDeferredMgr::BufferName );
@@ -633,7 +689,7 @@ void DeferredMinnaertGLSL::processVert( Vector<ShaderComponent*> &componentLis
const MaterialFeatureData &fd )
{
// If there is no deferred information, bail on this feature
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] )
{
output = NULL;
return;
@@ -650,7 +706,7 @@ void DeferredMinnaertGLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// If there is no deferred information, bail on this feature
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] )
{
output = NULL;
return;
@@ -695,12 +751,6 @@ void DeferredMinnaertGLSL::processPix( Vector<ShaderComponent*> &componentList,
void DeferredSubSurfaceGLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// If there is no deferred information, bail on this feature
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
{
output = NULL;
return;
}

Var *subSurfaceParams = new Var;
subSurfaceParams->setType( "vec4" );
@@ -712,9 +762,13 @@ void DeferredSubSurfaceGLSL::processPix( Vector<ShaderComponent*> &componentLis
Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" );

MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, @) - smoothstep(0.0, 1.0, @);\r\n", subSurfaceParams, d_NL_Att, d_NL_Att ) );
meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) );
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) );
if (fd.features[MFT_isDeferred])
{
Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget3));
meta->addStatement(new GenOp(" @.rgb += @.rgb*@.a;\r\n", targ, subSurfaceParams, subSurfaceParams));
output = meta;
return;
}

output = meta;
}
@@ -62,10 +62,24 @@ void DeferredSpecMapGLSL::processPix( Vector<ShaderComponent*> &componentList, c
specularMap->uniform = true;
specularMap->sampler = true;
specularMap->constNum = Var::getTexUnitNum();
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.b = dot(tex2D(@, @).rgb, vec3(0.3, 0.59, 0.11));\r\n", material, specularMap, texCoord));
meta->addStatement(new GenOp(" @.a = tex2D(@, @).a;\r\n", material, specularMap, texCoord));
LangElement *texOp = new GenOp( "tex2D(@, @)", specularMap, texCoord );

Var *specularColor = (Var*)LangElement::find("specularColor");
if (!specularColor) specularColor = new Var("specularColor", "vec4");
Var *metalness = (Var*)LangElement::find("metalness");
if (!metalness) metalness = new Var("metalness", "float");
Var *smoothness = (Var*)LangElement::find("smoothness");
if (!smoothness) smoothness = new Var("smoothness", "float");

meta->addStatement(new GenOp(" @ = @.r;\r\n", new DecOp(smoothness), texOp));
meta->addStatement(new GenOp(" @ = @.b;\r\n", new DecOp(metalness), texOp));

if (fd.features[MFT_InvertSmoothness])
meta->addStatement(new GenOp(" @ = 1.0-@;\r\n", smoothness, smoothness));

meta->addStatement(new GenOp(" @ = @.ggga;\r\n", new DecOp(specularColor), texOp));

meta->addStatement(new GenOp(" @.bga = vec3(@,@.g,@);\r\n", material, smoothness, specularColor, metalness));
output = meta;
}

@@ -145,44 +159,20 @@ void DeferredSpecVarsGLSL::processPix( Vector<ShaderComponent*> &componentList,
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName("OUT");
}

Var *metalness = new Var("metalness", "float");
metalness->uniform = true;
metalness->constSortPos = cspPotentialPrimitive;

Var *specStrength = new Var;
specStrength->setType( "float" );
specStrength->setName( "specularStrength" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;

Var *specPower = new Var;
specPower->setType("float");
specPower->setName("specularPower");
specPower->uniform = true;
specPower->constSortPos = cspPotentialPrimitive;
Var *smoothness = new Var("smoothness", "float");
smoothness->uniform = true;
smoothness->constSortPos = cspPotentialPrimitive;

MultiLine *meta = new MultiLine;
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.a = @/128;\r\n", material, specPower));
meta->addStatement(new GenOp(" @.b = @/5;\r\n", material, specStrength));
output = meta;
}

// Black -> Blue and Alpha of Color Buffer (representing no specular)
void DeferredEmptySpecGLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// search for material var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
if ( !material )
{
// create material var
material = new Var;
material->setType( "vec4" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName("OUT");
}

MultiLine * meta = new MultiLine;
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.ba = vec2(0.0);\r\n", material));
MultiLine *meta = new MultiLine;
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.b = @;\r\n", material, smoothness));
if (fd.features[MFT_InvertSmoothness])
meta->addStatement(new GenOp(" @ = 1.0-@;\r\n", smoothness, smoothness));
meta->addStatement(new GenOp(" @.a = @;\r\n", material, metalness));
output = meta;
}
@@ -70,16 +70,4 @@ class DeferredSpecVarsGLSL : public ShaderFeatureGLSL
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};


class DeferredEmptySpecGLSL : public ShaderFeatureGLSL
{
public:
virtual String getName() { return "Deferred Shading: Empty Specular"; }

virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );

virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};

#endif