Help needed with RenderBins
by Konrad Kiss · in Torque 3D Professional · 06/10/2009 (3:17 pm) · 17 replies
Hi. I tried to create a special renderbin which has only one object rendered into it including all its meshes. At least that's the idea.
I've taken the code from the prepass bin manager. When I add my new bin manager to renderManager.cs (to render before RenderMeshDynamicLightingMgr) all shaders that are used throw me the following:
That's a water example, but its not related to water. As far as I can tell, the shader with the same name is being generated (since I think the chances of two different names with the same hash is negligible), but I have no idea what to look for, and why this is being generated by the new bin - it's supposed to use a differently named material, though defined just like DefaultPrePassMaterial (empty material, different name).
Any help would be greatly appreciated!
I've taken the code from the prepass bin manager. When I add my new bin manager to renderManager.cs (to render before RenderMeshDynamicLightingMgr) all shaders that are used throw me the following:
Quote:
Error compiling shader: E_FAIL: An undetermined error occurred (80004005)
Shader shaders/common/water/waterV.hlsl: shadergen:/autogenConditioners.h(65,15): error X3003: redefinition of 'autogenCondition_55070f7a'
That's a water example, but its not related to water. As far as I can tell, the shader with the same name is being generated (since I think the chances of two different names with the same hash is negligible), but I have no idea what to look for, and why this is being generated by the new bin - it's supposed to use a differently named material, though defined just like DefaultPrePassMaterial (empty material, different name).
Any help would be greatly appreciated!
About the author
http://about.me/konrad.kiss
#2
Edit: probably RenderMeshMgr
06/10/2009 (11:26 pm)
Thanks James. Which RenderBin do you think would be a good a template for making a new bin?Edit: probably RenderMeshMgr
#3
06/11/2009 (5:40 am)
Yea... if all you need to do is render a DTS... then RenderMeshMgr is where you should start.
#4
I want to use that texture to use the outline postfx (thanks Mike J.!) on it following your directions.
This is my first time deep in render code, so I'm still somewhat lost, but it's really interesting, and things are now starting to snap in place.
06/11/2009 (5:57 am)
Thanks Tom. I need to render a DTS to a render target. I want to use that texture to use the outline postfx (thanks Mike J.!) on it following your directions.
This is my first time deep in render code, so I'm still somewhat lost, but it's really interesting, and things are now starting to snap in place.
#5
1. What is the best starting point to create a render bin that renders to a render target. I need one that I can later reference in the outline shader as a sampler (such as "#selection") - instead of #prepass? Are MatTextureTarget::registerTarget and MatTextureTarget::unregisterTarget enough to do the binding?
2. What are conditioners and unconditioners for? I know I need them, I just don't know why. I couldn't find any information on this yet.
3. Do I need to set up a new RenderInstType to render an object in a new bin that already has a RenderInstType? (its a mesh)
Sorry for being a bother guys, any help would be very much appreciated!
06/11/2009 (7:40 am)
Hmm.. I'll need to rephrase my question(s) to get a better idea, I'd lost my grip on this..1. What is the best starting point to create a render bin that renders to a render target. I need one that I can later reference in the outline shader as a sampler (such as "#selection") - instead of #prepass? Are MatTextureTarget::registerTarget and MatTextureTarget::unregisterTarget enough to do the binding?
2. What are conditioners and unconditioners for? I know I need them, I just don't know why. I couldn't find any information on this yet.
3. Do I need to set up a new RenderInstType to render an object in a new bin that already has a RenderInstType? (its a mesh)
Sorry for being a bother guys, any help would be very much appreciated!
#6
I cut some stuff out, but this should be what you need.
The header...
06/11/2009 (11:14 am)
In beta 3 the best example of how to do this would be RenderGlowMgr which i completely rewrote. It derives from RenderTexTargetBinManager and renders selected MeshRenderInst which have glow on their materials.I cut some stuff out, but this should be what you need.
The header...
#ifndef _TEXTARGETBIN_MGR_H_
#include "renderInstance/renderTexTargetBinManager.h"
#endif
class PostEffect;
class RenderGlowMgr : public RenderTexTargetBinManager
{
typedef RenderTexTargetBinManager Parent;
public:
RenderGlowMgr();
virtual ~RenderGlowMgr();
/// Returns true if the glow post effect is
/// enabled and the glow buffer should be updated.
bool isGlowEnabled();
// RenderBinManager
virtual RenderBinManager::AddInstResult addElement( RenderInst *inst );
virtual void render( SceneState *state );
// ConsoleObject
DECLARE_CONOBJECT( RenderGlowMgr );
protected:
SimObjectPtr<PostEffect> mGlowEffect;
};
#7
And the source file...
This should get you started.
06/11/2009 (11:14 am)
And the source file...
#include "platform/platform.h"
#include "renderInstance/renderGlowMgr.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "materials/sceneData.h"
#include "materials/matInstance.h"
#include "materials/materialFeatureTypes.h"
#include "materials/processedMaterial.h"
#include "postFx/postEffect.h"
#include "gfx/gfxTransformSaver.h"
#include "gfx/gfxDebugEvent.h"
IMPLEMENT_CONOBJECT( RenderGlowMgr );
RenderGlowMgr::RenderGlowMgr()
: RenderTexTargetBinManager( RenderPassManager::RIT_Mesh,
1.0f,
1.0f,
GFXFormatR8G8B8A8,
Point2I( 512, 512 ) )
{
mTargetSizeType = WindowSize;
MatTextureTarget::registerTarget( "glowbuffer", this );
}
RenderGlowMgr::~RenderGlowMgr()
{
MatTextureTarget::unregisterTarget( "glowbuffer", this );
}
bool RenderGlowMgr::isGlowEnabled()
{
if ( !mGlowEffect )
mGlowEffect = dynamic_cast<PostEffect*>( Sim::findObject( "GlowPostFx" ) );
return mGlowEffect && mGlowEffect->isEnabled();
}
RenderBinManager::AddInstResult RenderGlowMgr::addElement( RenderInst *inst )
{
// Skip out if we don't have the glow post
// effect enabled at this time.
if ( !isGlowEnabled() )
return RenderBinManager::arSkipped;
// TODO: We need to get the scene state here in a more reliable
// manner so we can skip glow in a non-diffuse render pass.
//if ( !mParentManager->getSceneManager()->getSceneState()->isDiffusePass() )
//return RenderBinManager::arSkipped;
BaseMatInstance* matInst = getMaterial(inst);
bool hasGlow = matInst && matInst->hasGlow();
if ( !hasGlow )
return RenderBinManager::arSkipped;
internalAddElement(inst);
return RenderBinManager::arAdded;
}
void RenderGlowMgr::render( SceneState *state )
{
PROFILE_SCOPE( RenderGlowMgr_Render );
// Don't allow non-diffuse passes.
if ( !state->isDiffusePass() )
return;
GFXDEBUGEVENT_SCOPE( RenderGlowMgr_Render, ColorI::GREEN );
GFXTransformSaver saver;
// Tell the superclass we're about to render, preserve contents
const bool isRenderingToTarget = _onPreRender( state, true );
// Clear all the buffers to black.
GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0);
// init loop data
SceneGraphData sgData;
U32 binSize = mElementList.size();
for( U32 j=0; j<binSize; )
{
MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);
// temp fix - these shouldn't submit glow ri's...
if(ri->dynamicLight)
{
j++;
continue;
}
setupSGData( ri, sgData );
sgData.binType = SceneGraphData::GlowBin;
BaseMatInstance *mat = ri->matInst;
U32 matListEnd = j;
while( mat->setupPass( state, sgData ) )
{
U32 a;
for( a=j; a<binSize; a++ )
{
MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);
if (newPassNeeded(mat, passRI))
break;
mat->setTransforms(*passRI->objectToWorld, *passRI->worldToCamera, *passRI->projection);
mat->setEyePosition(*passRI->objectToWorld, state->getCameraPosition());
mat->setBuffers(passRI->vertBuff, passRI->primBuff);
if ( passRI->prim )
GFX->drawPrimitive( *passRI->prim );
else
GFX->drawPrimitive( passRI->primBuffIndex );
}
matListEnd = a;
}
// force increment if none happened, otherwise go to end of batch
j = ( j == matListEnd ) ? j+1 : matListEnd;
}
// Finish up.
if ( isRenderingToTarget )
_onPostRender();
}This should get you started.
#8
For example there is a prepassConditioner which takes a normal and depth and then encodes the normal into a spherical format and writes 16bits of the depth into the blue channel and 16bits of the depth into the alpha channel.
There is a prepassUncondition which does the opposite.
In general you don't need to write one for your own buffers unless you have some really complex encoding to it. And even then... you don't really have to.
06/11/2009 (11:19 am)
Quote:2. What are conditioners and unconditioners for?Those are for writing and reading data that is encoded into a specialized format, so that your shaders don't need to know how to do it themselves.
For example there is a prepassConditioner which takes a normal and depth and then encodes the normal into a spherical format and writes 16bits of the depth into the blue channel and 16bits of the depth into the alpha channel.
There is a prepassUncondition which does the opposite.
In general you don't need to write one for your own buffers unless you have some really complex encoding to it. And even then... you don't really have to.
#9
06/11/2009 (11:35 am)
This is exactly what I need! Thank you! I'll let you know how it goes! I have lost count of the beers I owe you. :)
#11
06/11/2009 (11:55 am)
@Greg: Tom's right, glow really is exactly what we need. And there's no need to pass ids to meshes and such, I think the best way to go is to make a boolean in the material instance that shows whether the mesh must be selected or not! I'm in for another sleepless night! :)
#12
In tsMesh.cpp, there's a function executed at the very end of innerRender():
It checks every renderBin's addElement() to see if the renderInst fits for them, is that means if I define a material for a dts, and set the material's glow to true, then the renderInst for this dts's mesh would be inserted both into meshRenderbin and glowRenderbin? And the mesh will first be drawn by meshRenderbin, then drawn again by glowRenderbin?
Is that a cpu waste, or there are some other consideration in it?
07/04/2009 (8:26 am)
@Tom & @Konrad, I got puzzled at one point.In tsMesh.cpp, there's a function executed at the very end of innerRender():
state->getRenderPass()->addInst(ri);
It checks every renderBin's addElement() to see if the renderInst fits for them, is that means if I define a material for a dts, and set the material's glow to true, then the renderInst for this dts's mesh would be inserted both into meshRenderbin and glowRenderbin? And the mesh will first be drawn by meshRenderbin, then drawn again by glowRenderbin?
Is that a cpu waste, or there are some other consideration in it?
#13
07/04/2009 (8:30 am)
I think it's the fastest possible way. Tom knows a LOT more about this than I do, so I'll stay quiet and listen in. ;)
#14
It puts objects in multiple bins because objects often need to render several times. For instance when in Advanced Lighting a TSMesh can potentially go into 3 bins... RenderPrePassMgr, RenderMeshMgr, and RenderGlowMgr if it has glow enabled.
I agree it looks like a potential performance problem... but so far the binning process has not appeared in profiles.
07/06/2009 (2:28 am)
@HuanIt puts objects in multiple bins because objects often need to render several times. For instance when in Advanced Lighting a TSMesh can potentially go into 3 bins... RenderPrePassMgr, RenderMeshMgr, and RenderGlowMgr if it has glow enabled.
I agree it looks like a potential performance problem... but so far the binning process has not appeared in profiles.
#15
I just tried the glow effect, I set ForgeSoldier's 'medium' material's glow[0] to true, it looks fantarstic in advanced lighing mode, but doesn't take effects in basic lighting mode, did I miss something, or it is just the way it works.
07/06/2009 (8:30 am)
Thanks for the explainations.I just tried the glow effect, I set ForgeSoldier's 'medium' material's glow[0] to true, it looks fantarstic in advanced lighing mode, but doesn't take effects in basic lighting mode, did I miss something, or it is just the way it works.
#16
07/06/2009 (1:21 pm)
@Huan - I didn't know this... but the PostEffect system was hard coded to disable when in BL mode in beta 2 and 3. In beta 4 i hope to solve that issue and get it re-enabled so that effects like glow work in BL again.
#17
And @Konrad, waiting for your new resource, good luck!
07/06/2009 (6:26 pm)
@Tom, thanks again for your patience.And @Konrad, waiting for your new resource, good luck!
Associate James Ford
Sickhead Games
You probably don't want to use the prepass as an example as it is doing a lot of stuff that you likely do not need.