adress #1914
[Torque-3d.git] / Engine / source / renderInstance / renderMeshMgr.cpp
blobce27a09c2da051e94bedf2934f6686f9e69a439e
1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 // IN THE SOFTWARE.
21 //-----------------------------------------------------------------------------
23 #include "platform/platform.h"
24 #include "renderInstance/renderMeshMgr.h"
26 #include "console/consoleTypes.h"
27 #include "gfx/gfxTransformSaver.h"
28 #include "gfx/gfxPrimitiveBuffer.h"
29 #include "materials/sceneData.h"
30 #include "materials/processedMaterial.h"
31 #include "materials/materialManager.h"
32 #include "scene/sceneRenderState.h"
33 #include "gfx/gfxDebugEvent.h"
34 #include "math/util/matrixSet.h"
37 IMPLEMENT_CONOBJECT(RenderMeshMgr);
39 ConsoleDocClass( RenderMeshMgr,
40 "@brief A render bin for mesh rendering.\n\n"
41 "This is the primary render bin in Torque which does most of the "
42 "work of rendering DTS shapes and arbitrary mesh geometry. It knows "
43 "how to render mesh instances using materials and supports hardware mesh "
44 "instancing.\n\n"
45 "@ingroup RenderBin\n" );
48 RenderMeshMgr::RenderMeshMgr()
49 : RenderBinManager(RenderPassManager::RIT_Mesh, 1.0f, 1.0f)
53 RenderMeshMgr::RenderMeshMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
54 : RenderBinManager(riType, renderOrder, processAddOrder)
58 void RenderMeshMgr::init()
60 GFXStateBlockDesc d;
62 d.cullDefined = true;
63 d.cullMode = GFXCullCCW;
64 d.samplersDefined = true;
65 d.samplers[0] = GFXSamplerStateDesc::getWrapLinear();
67 mNormalSB = GFX->createStateBlock(d);
69 d.cullMode = GFXCullCW;
70 mReflectSB = GFX->createStateBlock(d);
73 void RenderMeshMgr::initPersistFields()
75 Parent::initPersistFields();
78 //-----------------------------------------------------------------------------
79 // add element
80 //-----------------------------------------------------------------------------
81 void RenderMeshMgr::addElement( RenderInst *inst )
83 // If this instance is translucent handle it in RenderTranslucentMgr
84 if (inst->translucentSort)
85 return;
87 AssertFatal( inst->defaultKey != 0, "RenderMeshMgr::addElement() - Got null sort key... did you forget to set it?" );
89 internalAddElement(inst);
92 //-----------------------------------------------------------------------------
93 // render
94 //-----------------------------------------------------------------------------
95 void RenderMeshMgr::render(SceneRenderState * state)
97 PROFILE_SCOPE(RenderMeshMgr_render);
99 // Early out if nothing to draw.
100 if(!mElementList.size())
101 return;
104 GFXDEBUGEVENT_SCOPE( RenderMeshMgr_Render, ColorI::GREEN );
106 // Automagically save & restore our viewport and transforms.
107 GFXTransformSaver saver;
109 // Restore transforms
110 MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
111 matrixSet.restoreSceneViewProjection();
113 // init loop data
114 GFXTextureObject *lastLM = NULL;
115 GFXCubemap *lastCubemap = NULL;
116 GFXTextureObject *lastReflectTex = NULL;
117 GFXTextureObject *lastMiscTex = NULL;
118 GFXTextureObject *lastAccuTex = NULL;
120 SceneData sgData;
121 sgData.init( state );
123 U32 binSize = mElementList.size();
125 for( U32 j=0; j<binSize; )
127 MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);
129 setupSGData( ri, sgData );
130 BaseMatInstance *mat = ri->matInst;
132 // If we have an override delegate then give it a
133 // chance to swap the material with another.
134 if ( mMatOverrideDelegate )
136 mat = mMatOverrideDelegate( mat );
137 if ( !mat )
139 j++;
140 continue;
144 if( !mat )
145 mat = MATMGR->getWarningMatInstance();
147 // Check if bin is disabled in advanced lighting.
148 // Allow forward rendering pass on custom materials.
150 if ( ( MATMGR->getPrePassEnabled() && mBasicOnly && !mat->isCustomMaterial() ) )
152 j++;
153 continue;
156 U32 matListEnd = j;
157 lastMiscTex = sgData.miscTex;
158 U32 a;
160 while( mat && mat->setupPass(state, sgData ) )
162 for( a=j; a<binSize; a++ )
164 MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);
166 // Check to see if we need to break this batch.
167 if ( newPassNeeded( ri, passRI ) ||
168 lastMiscTex != passRI->miscTex )
170 lastLM = NULL;
171 break;
174 matrixSet.setWorld(*passRI->objectToWorld);
175 matrixSet.setView(*passRI->worldToCamera);
176 matrixSet.setProjection(*passRI->projection);
177 mat->setTransforms(matrixSet, state);
179 // Setup HW skinning transforms if applicable
180 if (mat->usesHardwareSkinning())
182 mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
185 setupSGData( passRI, sgData );
186 mat->setSceneInfo( state, sgData );
188 // If we're instanced then don't render yet.
189 if ( mat->isInstanced() )
191 // Let the material increment the instance buffer, but
192 // break the batch if it runs out of room for more.
193 if ( !mat->stepInstance() )
195 a++;
196 break;
199 continue;
202 // TODO: This could proably be done in a cleaner way.
204 // This section of code is dangerous, it overwrites the
205 // lightmap values in sgData. This could be a problem when multiple
206 // render instances use the same multi-pass material. When
207 // the first pass is done, setupPass() is called again on
208 // the material, but the lightmap data has been changed in
209 // sgData to the lightmaps in the last renderInstance rendered.
211 // This section sets the lightmap data for the current batch.
212 // For the first iteration, it sets the same lightmap data,
213 // however the redundancy will be caught by GFXDevice and not
214 // actually sent to the card. This is done for simplicity given
215 // the possible condition mentioned above. Better to set always
216 // than to get bogged down into special case detection.
217 //-------------------------------------
218 bool dirty = false;
220 // set the lightmaps if different
221 if( passRI->lightmap && passRI->lightmap != lastLM )
223 sgData.lightmap = passRI->lightmap;
224 lastLM = passRI->lightmap;
225 dirty = true;
228 // set the cubemap if different.
229 if ( passRI->cubemap != lastCubemap )
231 sgData.cubemap = passRI->cubemap;
232 lastCubemap = passRI->cubemap;
233 dirty = true;
236 if ( passRI->reflectTex != lastReflectTex )
238 sgData.reflectTex = passRI->reflectTex;
239 lastReflectTex = passRI->reflectTex;
240 dirty = true;
243 // Update accumulation texture if it changed.
244 // Note: accumulation texture can be NULL, and must be updated.
245 if ( passRI->accuTex != lastAccuTex )
247 sgData.accuTex = passRI->accuTex;
248 lastAccuTex = passRI->accuTex;
249 dirty = true;
252 if ( dirty )
253 mat->setTextureStages( state, sgData );
255 // Setup the vertex and index buffers.
256 mat->setBuffers( passRI->vertBuff, passRI->primBuff );
258 // Render this sucker.
259 if ( passRI->prim )
260 GFX->drawPrimitive( *passRI->prim );
261 else
262 GFX->drawPrimitive( passRI->primBuffIndex );
265 // Draw the instanced batch.
266 if ( mat->isInstanced() )
268 // Sets the buffers including the instancing stream.
269 mat->setBuffers( ri->vertBuff, ri->primBuff );
271 // Render the instanced stream.
272 if ( ri->prim )
273 GFX->drawPrimitive( *ri->prim );
274 else
275 GFX->drawPrimitive( ri->primBuffIndex );
278 matListEnd = a;
281 // force increment if none happened, otherwise go to end of batch
282 j = ( j == matListEnd ) ? j+1 : matListEnd;