Distance Fading
by Adam Larson · 08/29/2008 (7:19 am) · 4 comments
Download Code File
Object Distance Fading Resource
The object fading resource provides the ability to have objects fade based on their distance from the camera. This can be useful for several things, but the most obvious example is that of already heavily transparent objects, like sun beams or foliage. In stock Torque, an object is always rendered as long as it is within the view frustum. This allows you to stop rendering objects long before they are beyond the view distance, and transition nicely to that state. Of course, rendering fewer objects means an increased framerate.
Because it forces an object to be translucent, it may not always be a win for normally opaque objects since they will have to have blending enabled.
This resource enables fading for everything that uses ShapeBase for rendering (Item, StaticShape), TSStatic, and particle effects (via the datablock or emitter node). To use it, simply edit the enableDistanceFade, distanceFadeNear, and distanceFadeFar variables in the editor.
For particle emitters that aren't attached to an emitter node, the field values must be set on the emitter datablock.
enableDistanceFade Enables fading on the object.
distanceFadeNear specifies the distance from the camera an object must be before it starts to fade out.
distanceFadeFar specifies the distance from the camera at which the object is fully transparent.
The fading is linear, so an object will be 50% visible when the camera is halfway between the near and far distance.
Note, it does not work for Player or Vehicle because they define their own renderImage method. It is trivial to add, however I can't imagine it being of much use. LODs should be used for these instead of forcing them to be translucent.
The changes:
In SceneObject.h:
Line 264 (replace the line reading NextFreeMask = BIT(1) with this)
Line 367 (at the end of the SceneObject constructor)
Line 2176 (after the getDamageState if block in ShapeBase::prepRenderImage)
Line 177 (end of ParticleEmitterData declaration)
Line 93 (end of ParticleEmitterData constructor)
Line 132 (after mEmitter = pEmitter in ParticleEmitterNode::onAdd)
Line 187 (after setLastState in TSStatic::prepRenderImage)
Object Distance Fading Resource
The object fading resource provides the ability to have objects fade based on their distance from the camera. This can be useful for several things, but the most obvious example is that of already heavily transparent objects, like sun beams or foliage. In stock Torque, an object is always rendered as long as it is within the view frustum. This allows you to stop rendering objects long before they are beyond the view distance, and transition nicely to that state. Of course, rendering fewer objects means an increased framerate.
Because it forces an object to be translucent, it may not always be a win for normally opaque objects since they will have to have blending enabled.
This resource enables fading for everything that uses ShapeBase for rendering (Item, StaticShape), TSStatic, and particle effects (via the datablock or emitter node). To use it, simply edit the enableDistanceFade, distanceFadeNear, and distanceFadeFar variables in the editor.
For particle emitters that aren't attached to an emitter node, the field values must be set on the emitter datablock.
enableDistanceFade Enables fading on the object.
distanceFadeNear specifies the distance from the camera an object must be before it starts to fade out.
distanceFadeFar specifies the distance from the camera at which the object is fully transparent.
The fading is linear, so an object will be 50% visible when the camera is halfway between the near and far distance.
Note, it does not work for Player or Vehicle because they define their own renderImage method. It is trivial to add, however I can't imagine it being of much use. LODs should be used for these instead of forcing them to be translucent.
The changes:
In SceneObject.h:
Line 264 (replace the line reading NextFreeMask = BIT(1) with this)
// --------------------------------------------------------------------------
// Object Fade Resource
//NextFreeMask = BIT(1)
FadeMask = BIT(1),
NextFreeMask = BIT(2)
// --------------------------------------------------------------------------Line 805 (at the end of the SceneObject declaration) // -----------------------------------------------------------------------------
// Object Fade Resource
public:
void setDistanceFade(bool fade, F32 nearDistance = 0.0f, F32 farDistance = 0.0f)
{
mEnableDistanceFade = fade;
mDistanceFadeNear = nearDistance;
mDistanceFadeFar = farDistance;
setMaskBits(FadeMask);
}
F32 getDistanceFadeAlpha(Point3F cameraPosition)
{
mLastDistanceFadeValue = 1.0f;
if (!mEnableDistanceFade)
return mLastDistanceFadeValue;
F32 distance = (cameraPosition - getRenderPosition()).len();
if (distance < mDistanceFadeNear)
mLastDistanceFadeValue = 1.0f;
else if (distance > mDistanceFadeFar)
mLastDistanceFadeValue = 0.0f;
else
mLastDistanceFadeValue = 1.0f - ((distance - mDistanceFadeNear) / (mDistanceFadeFar - mDistanceFadeNear));
return mLastDistanceFadeValue;
}
protected:
bool mEnableDistanceFade;
F32 mDistanceFadeNear;
F32 mDistanceFadeFar;
F32 mLastDistanceFadeValue;
// -----------------------------------------------------------------------------In SceneObject.cpp:Line 367 (at the end of the SceneObject constructor)
// -------------------------------------------------------------------------- // Object Fade Resource mEnableDistanceFade = false; mDistanceFadeNear = 0.0f; mDistanceFadeFar = 0.0f; mLastDistanceFadeValue = 1.0f; // --------------------------------------------------------------------------Line 563 (after the setScale call)
// --------------------------------------------------------------------------
// Object Fade Resource
setMaskBits(FadeMask);
// --------------------------------------------------------------------------Line 666 (at the end of SceneObject::initPersistFields)// --------------------------------------------------------------------------
// Object Fade Resource
addGroup("Distance Fade");
addField("enableDistanceFade", TypeBool, Offset(mEnableDistanceFade, SceneObject));
addField("nearDistance", TypeF32, Offset(mDistanceFadeNear, SceneObject));
addField("farDistance", TypeF32, Offset(mDistanceFadeFar, SceneObject));
endGroup("Distance Fade");
// --------------------------------------------------------------------------In ShapeBase.cpp (leave this out if you don't need the functionality on ShapeBase objects:Line 2176 (after the getDamageState if block in ShapeBase::prepRenderImage)
// --------------------------------------------------------------------------
// Object Fade Resource
float distanceFade = getDistanceFadeAlpha(state->getCameraPosition());
if (distanceFade < 0.001f)
return false;
// --------------------------------------------------------------------------Line 2226 (replace the line reading if (mCloakLevel == 0.0f && ...) with this)// --------------------------------------------------------------------------
// Object Fade Resource
//if (mCloakLevel == 0.0f && image.shapeInstance->hasSolid() && mFadeVal == 1.0f)
if (mCloakLevel == 0.0f && image.shapeInstance->hasSolid() && mFadeVal == 1.0f && (distanceFade > 0.999f))
// --------------------------------------------------------------------------Line 2237 (replace the line reading if ((mCloakLevel != 0.0f || ...) with this)// --------------------------------------------------------------------------
// Object Fade Resource
//if ((mCloakLevel != 0.0f || mFadeVal != 1.0f || mShapeInstance->hasTranslucency()) ||
if ((mCloakLevel != 0.0f || mFadeVal != 1.0f || mShapeInstance->hasTranslucency() || (distanceFade < 1.0f)) ||
// --------------------------------------------------------------------------Line 2254 (replace the line reading if (mCloakLevel == 0.0f && ...) with this)// --------------------------------------------------------------------------
// Object Fade Resource
//if (mCloakLevel == 0.0f && mShapeInstance->hasSolid() && mFadeVal == 1.0f)
if (mCloakLevel == 0.0f && mShapeInstance->hasSolid() && mFadeVal == 1.0f && (distanceFade > 0.999f))
// --------------------------------------------------------------------------Line 2263 (replace the line reading if ((mCloakLevel != 0.0f || ...) with this)// --------------------------------------------------------------------------
// Object Fade Resource
//if ((mCloakLevel != 0.0f || mFadeVal != 1.0f || mShapeInstance->hasTranslucency()) ||
if ((mCloakLevel != 0.0f || mFadeVal != 1.0f || mShapeInstance->hasTranslucency() || (distanceFade < 1.0f)) ||
// --------------------------------------------------------------------------Line 2321 (replace the line reading if (mCloakLevel == 0.0f && ...) with this)// -------------------------------------------------------------------------- // Object Fade Resource //if (mCloakLevel == 0.0f && mFadeVal == 1.0f) if (mCloakLevel == 0.0f && mFadeVal == 1.0f && (mLastDistanceFadeValue > 0.999f)) // --------------------------------------------------------------------------Line 2498 (between the if (mCloakLevel != 0.0) and else block in ShapeBase::renderImage)
// --------------------------------------------------------------------------
// Object Fade Resource
else if (mLastDistanceFadeValue < 1.0f) {
mShapeInstance->setAlphaAlways(mLastDistanceFadeValue);
}
// --------------------------------------------------------------------------Line 2874 (after the first if block in ShapeBase::packUpdate)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->writeFlag(mask & FadeMask))
{
if (stream->writeFlag(mEnableDistanceFade))
{
stream->write(mDistanceFadeNear);
stream->write(mDistanceFadeFar);
}
}
// --------------------------------------------------------------------------Line 2990 (after the line reading mLastRenderFrame = ... in ShapeBase::unpackUpdate)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->readFlag())
{
mEnableDistanceFade = stream->readFlag();
if (mEnableDistanceFade)
{
stream->read(&mDistanceFadeNear);
stream->read(&mDistanceFadeFar);
}
}
// --------------------------------------------------------------------------In ParticleEngine.hLine 177 (end of ParticleEmitterData declaration)
// -------------------------------------------------------------------------- // Object Fade Resource bool enableDistanceFade; F32 distanceFadeNear; F32 distanceFadeFar; // --------------------------------------------------------------------------In ParticleEngine.cpp (leave this out if you don't need the functionality on particle emitters:
Line 93 (end of ParticleEmitterData constructor)
// -------------------------------------------------------------------------- // Object Fade Resource enableDistanceFade = false; distanceFadeNear = 0.0f; distanceFadeFar = 0.0f; // --------------------------------------------------------------------------Line 121 (end of ParticleEmitterData::initPersistFields)
// --------------------------------------------------------------------------
// Object Fade Resource
addField("enableDistanceFade", TypeBool, Offset(enableDistanceFade, ParticleEmitterData));
addField("distanceFadeNear", TypeF32, Offset(distanceFadeNear, ParticleEmitterData));
addField("distanceFadeFar", TypeF32, Offset(distanceFadeFar, ParticleEmitterData));
// --------------------------------------------------------------------------Line 157 (end of ParticleEmitterData::packData)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->writeFlag(enableDistanceFade))
{
stream->write(distanceFadeNear);
stream->write(distanceFadeFar);
}
// --------------------------------------------------------------------------Line 197 (end of ParticleEmitterData::UnpackData)// --------------------------------------------------------------------------
// Object Fade Resource
enableDistanceFade = stream->readFlag();
if (enableDistanceFade)
{
stream->read(&distanceFadeNear);
stream->read(&distanceFadeFar);
}
// --------------------------------------------------------------------------Line 806 (end of ParticleEmitter::onNewDatablock)// --------------------------------------------------------------------------
// Object Fade Resource
if (mDataBlock->enableDistanceFade)
setDistanceFade(mDataBlock->enableDistanceFade, mDataBlock->distanceFadeNear, mDataBlock->distanceFadeFar);
// --------------------------------------------------------------------------Line 819 (after setLastState in ParticleEmitter::prepRenderImage)// --------------------------------------------------------------------------
// Object Fade Resource
Point3F centerPosition;
mObjBox.getCenter(¢erPosition);
if (getDistanceFadeAlpha(state->getCameraPosition() - centerPosition) < 0.001f)
return false;
// --------------------------------------------------------------------------Line 1061 (beginning of ParticleEmitter::lightParticle)// -------------------------------------------------------------------------- // Object Fade Resource ColorF color = part.color; color.alpha *= mLastDistanceFadeValue; // --------------------------------------------------------------------------Line 1075 (replace the line containing glColor4f(0.5f, 0.5f, 0.5f, 1.0f) with this)
// -------------------------------------------------------------------------- // Object Fade Resource //glColor4f(0.5f, 0.5f, 0.5f, 1.0f); glColor4f(0.5f, 0.5f, 0.5f, mLastDistanceFadeValue); // --------------------------------------------------------------------------Line 1082 (replace the line containing glColor4fv(part.color) with this)
// -------------------------------------------------------------------------- // Object Fade Resource //glColor4fv(part.color); glColor4fv(color); // --------------------------------------------------------------------------In ParticleEmitter.cpp (leave this out if you don't need the functionality on particle emitter nodes:
Line 132 (after mEmitter = pEmitter in ParticleEmitterNode::onAdd)
// -----------------------------------------------------------------------
// Object Fade Resource
if (mEmitter)
mEmitter->setDistanceFade(mEnableDistanceFade, mDistanceFadeNear, mDistanceFadeFar);
// -----------------------------------------------------------------------Line 207 (end of ParticleEmitterNode::packUpdate)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->writeFlag(mask & FadeMask))
{
if (stream->writeFlag(mEnableDistanceFade))
{
stream->write(mDistanceFadeNear);
stream->write(mDistanceFadeFar);
}
}
// --------------------------------------------------------------------------Line 229 (end of ParticleEmitterNode::unpackUpdate)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->readFlag())
{
mEnableDistanceFade = stream->readFlag();
if (mEnableDistanceFade)
{
stream->read(&mDistanceFadeNear);
stream->read(&mDistanceFadeFar);
}
if (mEmitter)
mEmitter->setDistanceFade(mEnableDistanceFade, mDistanceFadeNear, mDistanceFadeFar);
}
// --------------------------------------------------------------------------In TSStatic.cpp:Line 187 (after setLastState in TSStatic::prepRenderImage)
// --------------------------------------------------------------------------
// Object Fade Resource
F32 distanceFade = getDistanceFadeAlpha(state->getCameraPosition());
if (distanceFade < 0.001f)
return false;
// --------------------------------------------------------------------------Line 206 (replace the line reading if (mShapeInstance->hasSolid()) with this)// --------------------------------------------------------------------------
// Object Fade Resource
//if (mShapeInstance->hasSolid())
if (mShapeInstance->hasSolid() && (distanceFade > 0.999f))
// --------------------------------------------------------------------------Line 215 (replace the line reading if (mShapeInstance->hasTranslucency()) with this)// --------------------------------------------------------------------------
// Object Fade Resource
//if (mShapeInstance->hasTranslucency())
if (mShapeInstance->hasTranslucency() || (distanceFade < 1.0f))
// --------------------------------------------------------------------------Line 285 (replace the line reading mShapeInstance->setAlphaAlways(1.0); with this)// -------------------------------------------------------------------------- // Object Fade Resource //mShapeInstance->setAlphaAlways(1.0); mShapeInstance->setAlphaAlways(mLastDistanceFadeValue); // --------------------------------------------------------------------------Line 292 (before the line reading if (image->isTranslucent == true))
// --------------------------------------------------------------------------
// Object Fade Resource
if (mLastDistanceFadeValue < 1.0f)
{
TSShapeInstance::smNoRenderNonTranslucent = false;
TSShapeInstance::smNoRenderTranslucent = false;
}
else
// --------------------------------------------------------------------------Line 394 (at the end of TSStatic::packUpdate)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->writeFlag(mask & FadeMask))
{
if (stream->writeFlag(mEnableDistanceFade))
{
stream->write(mDistanceFadeNear);
stream->write(mDistanceFadeFar);
}
}
// --------------------------------------------------------------------------Line 430 (at the end of TSStatic::unpackUpdate)// --------------------------------------------------------------------------
// Object Fade Resource
if (stream->readFlag())
{
mEnableDistanceFade = stream->readFlag();
if (mEnableDistanceFade)
{
stream->read(&mDistanceFadeNear);
stream->read(&mDistanceFadeFar);
}
}
// --------------------------------------------------------------------------About the author
Recent Blogs
• Particle Alignment• On Our Best Behaviors
• Meet the T2D Level Builder
• Plan for Adam Larson
• Plan for Adam Larson
#2
08/29/2008 (3:18 pm)
Any screens?
#3
Well done.
08/29/2008 (8:16 pm)
Nice resource. It is pretty much an upgrade/update to the Alpha LOD resource.Well done.
#4
11/25/2008 (2:02 am)
nice. is there a tgea version? 
Torque Owner asmaloney (Andy)
Default Studio Name
[Edit: Rating doesn't work for me otherwise I'd give it a 5.]
[Edit: Rating doesn't work on my FF 3 on Windows - Mac works though.]