Torque3D/Engine/source/renderInstance/renderBinManager.cpp

194 lines
6.3 KiB
C++
Raw Normal View History

2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "renderInstance/renderBinManager.h"
#include "console/consoleTypes.h"
#include "materials/matInstance.h"
#include "scene/sceneManager.h"
#include "console/engineAPI.h"
IMPLEMENT_CONOBJECT(RenderBinManager);
RenderBinManager::RenderBinManager( const RenderInstType& ritype, F32 renderOrder, F32 processAddOrder ) :
mProcessAddOrder( processAddOrder ),
mRenderOrder( renderOrder ),
mRenderInstType( ritype ),
The final step (barring any overlooked missing bits, requested refactors, and of course, rolling in dependencies already submitted as PRs) consists of: renderPrePassMgr.cpp related: A) shifting .addFeature( MFT_XYZ); calls from ProcessedShaderMaterial::_determineFeatures to ProcessedPrePassMaterial::_determineFeatures B) mimicking the "// set the XXX if different" entries from RenderMeshMgr::render in RenderPrePassMgr::render C) fleshing out ProcessedPrePassMaterial::getNumStages() so that it shares a 1:1 correlation with ProcessedShaderMaterial::getNumStages() D) causing inline void Swizzle<T, mapLength>::ToBuffer( void *destination, const void *source, const dsize_t size ) to silently fail rather than fatally assert if a source or destination buffer is not yet ready to be filled. (support for #customTarget scripted render targets) Reflections: A) removing reflectRenderState.disableAdvancedLightingBins(true); entries. this would otherwise early out from prepass and provide no color data whatsoever. B) removing the fd.features.addFeature( MFT_ForwardShading ); entry forcing all materials to be forward lit when reflected. C) 2 things best described bluntly as working hacks: C1) when reflected, a scattersky is rotated PI along it's z then x axis in order to draw properly. C2) along similar lines, in terraincellmaterial, we shut off culling if it's a prepass material. Skies: scattersky is given a pair of rotations for reflection purposes, all sky objects are given a z value for depth testing.
2016-02-16 08:50:49 +00:00
mRenderPass( NULL ),
mBasicOnly ( false )
2012-09-19 15:15:01 +00:00
{
VECTOR_SET_ASSOCIATION( mElementList );
mElementList.reserve( 2048 );
}
ConsoleDocClass( RenderBinManager,
"@brief The abstract base for all render bins.\n\n"
"The render bins are used by the engine as a high level method to order and batch rendering "
"operations.\n"
"@ingroup RenderBin\n" );
void RenderBinManager::initPersistFields()
{
docsURL;
2012-09-19 15:15:01 +00:00
addField( "binType", TypeRealString, Offset(mRenderInstType.mName, RenderBinManager),
"Sets the render bin type which limits what render instances are added to this bin." );
2025-03-09 16:53:23 +00:00
addFieldV("renderOrder", TypeRangedF32, Offset(mRenderOrder, RenderBinManager), &CommonValidators::PositiveFloat,
2012-09-19 15:15:01 +00:00
"Defines the order for rendering in relation to other bins." );
2025-03-09 16:53:23 +00:00
addFieldV("processAddOrder", TypeRangedF32, Offset(mProcessAddOrder, RenderBinManager), &CommonValidators::PositiveFloat,
2012-09-19 15:15:01 +00:00
"Defines the order for adding instances in relation to other bins." );
The final step (barring any overlooked missing bits, requested refactors, and of course, rolling in dependencies already submitted as PRs) consists of: renderPrePassMgr.cpp related: A) shifting .addFeature( MFT_XYZ); calls from ProcessedShaderMaterial::_determineFeatures to ProcessedPrePassMaterial::_determineFeatures B) mimicking the "// set the XXX if different" entries from RenderMeshMgr::render in RenderPrePassMgr::render C) fleshing out ProcessedPrePassMaterial::getNumStages() so that it shares a 1:1 correlation with ProcessedShaderMaterial::getNumStages() D) causing inline void Swizzle<T, mapLength>::ToBuffer( void *destination, const void *source, const dsize_t size ) to silently fail rather than fatally assert if a source or destination buffer is not yet ready to be filled. (support for #customTarget scripted render targets) Reflections: A) removing reflectRenderState.disableAdvancedLightingBins(true); entries. this would otherwise early out from prepass and provide no color data whatsoever. B) removing the fd.features.addFeature( MFT_ForwardShading ); entry forcing all materials to be forward lit when reflected. C) 2 things best described bluntly as working hacks: C1) when reflected, a scattersky is rotated PI along it's z then x axis in order to draw properly. C2) along similar lines, in terraincellmaterial, we shut off culling if it's a prepass material. Skies: scattersky is given a pair of rotations for reflection purposes, all sky objects are given a z value for depth testing.
2016-02-16 08:50:49 +00:00
addField( "basicOnly", TypeBool, Offset(mBasicOnly, RenderBinManager),
"Limites the render bin to basic lighting only." );
2012-09-19 15:15:01 +00:00
Parent::initPersistFields();
}
void RenderBinManager::onRemove()
{
// Tell the render pass to remove us when
// we're being unregistered.
if ( mRenderPass )
mRenderPass->removeManager( this );
Parent::onRemove();
}
void RenderBinManager::notifyType( const RenderInstType &type )
{
// Avoid duplicate types.
if ( !type.isValid() ||
mRenderInstType == type ||
mOtherTypes.contains( type ) )
return;
mOtherTypes.push_back( type );
// Register for the signal if the pass
// has already been assigned.
if ( mRenderPass )
mRenderPass->getAddSignal(type).notify( this, &RenderBinManager::addElement, mProcessAddOrder );
}
void RenderBinManager::setRenderPass( RenderPassManager *rpm )
{
if ( mRenderPass )
{
if ( mRenderInstType.isValid() )
mRenderPass->getAddSignal(mRenderInstType).remove( this, &RenderBinManager::addElement );
for ( U32 i=0; i < mOtherTypes.size(); i++ )
mRenderPass->getAddSignal(mOtherTypes[i]).remove( this, &RenderBinManager::addElement );
}
mRenderPass = rpm;
if ( mRenderPass )
{
if ( mRenderInstType.isValid() )
mRenderPass->getAddSignal(mRenderInstType).notify( this, &RenderBinManager::addElement, mProcessAddOrder );
for ( U32 i=0; i < mOtherTypes.size(); i++ )
mRenderPass->getAddSignal(mOtherTypes[i]).notify( this, &RenderBinManager::addElement, mProcessAddOrder );
}
}
void RenderBinManager::addElement( RenderInst *inst )
{
internalAddElement(inst);
}
void RenderBinManager::internalAddElement(RenderInst* inst)
{
mElementList.increment();
MainSortElem &elem = mElementList.last();
elem.inst = inst;
elem.key = inst->defaultKey;
elem.key2 = inst->defaultKey2;
}
void RenderBinManager::clear()
{
mElementList.clear();
}
void RenderBinManager::sort()
{
dQsort( mElementList.address(), mElementList.size(), sizeof(MainSortElem), cmpKeyFunc);
}
S32 FN_CDECL RenderBinManager::cmpKeyFunc(const void* p1, const void* p2)
{
const MainSortElem* mse1 = (const MainSortElem*) p1;
const MainSortElem* mse2 = (const MainSortElem*) p2;
S32 test1 = S32(mse2->key) - S32(mse1->key);
return ( test1 == 0 ) ? S32(mse1->key2) - S32(mse2->key2) : test1;
}
2017-10-17 13:48:31 +00:00
void RenderBinManager::setupSGData(MeshRenderInst *ri, SceneData &data)
2012-09-19 15:15:01 +00:00
{
PROFILE_SCOPE( RenderBinManager_setupSGData );
// NOTE: We do not reset or clear the scene state
// here as the caller has initialized non-RI members
// himself and we must preserve them.
//
// It also saves a bunch of CPU as this is called for
// every MeshRenderInst in every pass.
dMemcpy( data.lights, ri->lights, sizeof( data.lights ) );
data.objTrans = ri->objectToWorld;
data.backBuffTex = ri->backBuffTex;
data.cubemap = ri->cubemap;
data.miscTex = ri->miscTex;
data.reflectTex = ri->reflectTex;
data.accuTex = ri->accuTex;
2012-09-19 15:15:01 +00:00
data.lightmap = ri->lightmap;
data.visibility = ri->visibility;
data.materialHint = ri->materialHint;
data.customShaderData.clear();
for (U32 i = 0; i < ri->mCustomShaderData.size(); i++)
{
data.customShaderData.push_back(&ri->mCustomShaderData[i]);
}
2012-09-19 15:15:01 +00:00
}
DefineEngineMethod( RenderBinManager, getBinType, const char*, (),,
"Returns the bin type string." )
{
return object->getRenderInstType().getName();
}
DefineEngineMethod(RenderBinManager, getRenderOrder, F32, (), ,
"Returns the bin render order.")
{
return object->getRenderOrder();
}