00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_RENDER_H__
00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_RENDER_H__
00021
00026 #include "csplugincommon/rendermanager/posteffects.h"
00027 #include "csplugincommon/rendermanager/operations.h"
00028 #include "csplugincommon/rendermanager/rendertree.h"
00029 #include "csplugincommon/rendermanager/svarrayholder.h"
00030 #include "csplugincommon/rendermanager/occluvis.h"
00031
00032 #include "ivideo/graph2d.h"
00033 #include "iengine/sector.h"
00034
00035 namespace CS
00036 {
00037 namespace RenderManager
00038 {
00043 class BeginFinishDrawScope
00044 {
00045 public:
00046 BeginFinishDrawScope (iGraphics3D* g3d, int drawFlags, bool finishOnEnd = true)
00047 : g3d (g3d), finishOnEnd (finishOnEnd)
00048 {
00049 g3d->BeginDraw (drawFlags);
00050 }
00051
00052 ~BeginFinishDrawScope ()
00053 {
00054 if (finishOnEnd)
00055 g3d->FinishDraw ();
00056 }
00057
00058 private:
00059 iGraphics3D* g3d;
00060 bool finishOnEnd;
00061 };
00062
00063
00067 template<typename ContextType>
00068 class ContextTargetSetup
00069 {
00070 public:
00071 ContextTargetSetup (iGraphics3D* g3d)
00072 : g3d (g3d)
00073 {
00074 }
00075
00076 ~ContextTargetSetup ()
00077 {
00078 g3d->FinishDraw ();
00079 }
00080
00081 void operator() (const ContextType& context)
00082 {
00083 g3d->FinishDraw ();
00084 for (int a = 0; a < rtaNumAttachments; a++)
00085 {
00086
00087
00088 if ((csRenderTargetAttachment (a) == rtaColor0)
00089 && (context.postEffects.IsValid()))
00090 {
00091 context.postEffects->SetEffectsOutputTarget (
00092 context.renderTargets[a].texHandle);
00093 g3d->SetRenderTarget (
00094 context.postEffects->GetScreenTarget (), false,
00095 context.renderTargets[a].subtexture,
00096 csRenderTargetAttachment (a));
00097 }
00098 else
00099 g3d->SetRenderTarget (context.renderTargets[a].texHandle, false,
00100 context.renderTargets[a].subtexture, csRenderTargetAttachment (a));
00101 }
00102 }
00103
00104 private:
00105 iGraphics3D* g3d;
00106 };
00107
00109 template<typename RenderTree>
00110 class RenderCommon
00111 {
00112 public:
00113 void SetLayer (size_t layer)
00114 {
00115 currentLayer = layer;
00116 }
00117 protected:
00118 iGraphics3D* g3d;
00119 iShaderManager* shaderMgr;
00120 size_t currentLayer;
00121
00122 RenderCommon (iGraphics3D* g3d, iShaderManager* shaderMgr)
00123 : g3d (g3d), shaderMgr (shaderMgr), currentLayer (0) {}
00124
00125 void RenderMeshes (typename RenderTree::ContextNode& context,
00126 const typename RenderTree::MeshNode::MeshArrayType& meshes,
00127 iShader* shader, size_t ticket,
00128 size_t firstMesh, size_t lastMesh)
00129 {
00130 if (firstMesh == lastMesh)
00131 return;
00132
00133
00134 if (!shader)
00135 return;
00136
00137 csShaderVariableStack& svStack = shaderMgr->GetShaderVariableStack ();
00138
00139 const size_t numPasses = shader->GetNumberOfPasses (ticket);
00140
00141 for (size_t p = 0; p < numPasses; ++p)
00142 {
00143 if (!shader->ActivatePass (ticket, p)) continue;
00144
00145 for (size_t m = firstMesh; m < lastMesh; ++m)
00146 {
00147 const typename RenderTree::MeshNode::SingleMesh& mesh = meshes.Get (m);
00148 context.svArrays.SetupSVStack (svStack, currentLayer, mesh.contextLocalId);
00149
00150 csRenderMeshModes modes (*mesh.renderMesh);
00151 if (!shader->SetupPass (ticket, mesh.renderMesh, modes, svStack)) continue;
00152 modes.z_buf_mode = mesh.zmode;
00153
00154 g3d->DrawMesh (mesh.renderMesh, modes, svStack);
00155
00156 shader->TeardownPass (ticket);
00157 }
00158 shader->DeactivatePass (ticket);
00159 }
00160 }
00161 };
00162
00169 template<typename RenderTree>
00170 class SimpleContextRender : public RenderCommon<RenderTree>
00171 {
00172 public:
00173 SimpleContextRender (iGraphics3D* g3d, iShaderManager* shaderMgr)
00174 : RenderCommon<RenderTree> (g3d, shaderMgr)
00175 {}
00176
00177 void operator() (typename RenderTree::MeshNode* node)
00178 {
00179 typename RenderTree::ContextNode& context = node->GetOwner();
00180 const size_t layerOffset = context.totalRenderMeshes*this->currentLayer;
00181
00182 iShader* lastShader = 0;
00183 size_t lastTicket = ~0;
00184 size_t lastRenderedMesh = 0;
00185
00186 for (size_t m = 0; m < node->meshes.GetSize (); ++m)
00187 {
00188 typename RenderTree::MeshNode::SingleMesh& mesh = node->meshes.Get (m);
00189 iShader* shader = context.shaderArray[mesh.contextLocalId+layerOffset];
00190
00191 size_t ticket = context.ticketArray[mesh.contextLocalId+layerOffset];
00192
00193 if (shader != lastShader || ticket != lastTicket
00194 || (mesh.preCopyNum != 0))
00195 {
00196
00197 RenderMeshes (context, node->meshes, lastShader, lastTicket, lastRenderedMesh, m);
00198 lastRenderedMesh = m;
00199
00200 lastShader = shader;
00201 lastTicket = ticket;
00202 }
00203
00204 if (mesh.preCopyNum != 0)
00205 {
00206 this->g3d->CopyFromRenderTargets (mesh.preCopyNum,
00207 mesh.preCopyAttachments, mesh.preCopyTextures);
00208 }
00209 }
00210
00211 RenderMeshes (context, node->meshes, lastShader, lastTicket, lastRenderedMesh, node->meshes.GetSize ());
00212 }
00213 };
00214
00218 template<typename RenderTree>
00219 class SimpleContextRenderByMesh : public RenderCommon<RenderTree>
00220 {
00221 public:
00222 SimpleContextRenderByMesh (iGraphics3D* g3d, iShaderManager* shaderMgr)
00223 : RenderCommon<RenderTree> (g3d, shaderMgr)
00224 {}
00225
00226 void operator() (typename RenderTree::MeshNode* node)
00227 {
00228 typename RenderTree::ContextNode& context = node->GetOwner();
00229 for (size_t m = 0; m < node->meshes.GetSize (); ++m)
00230 {
00231 typename RenderTree::MeshNode::SingleMesh& mesh = node->meshes.Get (m);
00232 if (mesh.preCopyNum != 0)
00233 {
00234 this->g3d->CopyFromRenderTargets (mesh.preCopyNum,
00235 mesh.preCopyAttachments, mesh.preCopyTextures);
00236 }
00237 for (size_t layer = 0; layer < context.svArrays.GetNumLayers(); layer++)
00238 {
00239 this->SetLayer (layer);
00240 const size_t layerOffset = context.totalRenderMeshes*layer;
00241
00242 iShader* shader = context.shaderArray[mesh.contextLocalId+layerOffset];
00243
00244 size_t ticket = context.ticketArray[mesh.contextLocalId+layerOffset];
00245 RenderMeshes (context, node->meshes, shader, ticket, m, m+1);
00246 }
00247 }
00248 }
00249 };
00250
00251 template<typename RenderTree>
00252 struct OperationTraits<SimpleContextRender<RenderTree> >
00253 {
00254 typedef OperationUnordered Ordering;
00255 };
00256
00278 template<typename RenderTree>
00279 class SimpleTreeRenderer
00280 {
00281 public:
00282 SimpleTreeRenderer (iGraphics3D* g3di, iShaderManager* shaderMgri)
00283 : targetSetup (g3di),
00284 meshRender (g3di, shaderMgri),
00285 meshRenderByMesh (g3di, shaderMgri),
00286 g3d (g3di), shaderMgr (shaderMgri), lastRenderView (0)
00287 {
00288 memset (lastTarget, 0, sizeof (lastTarget));
00289 memset (lastSubtexture, 0, sizeof (lastSubtexture));
00290 }
00291
00292 ~SimpleTreeRenderer ()
00293 {
00294
00295 RenderContextStack ();
00296 }
00297
00298 void operator() (size_t i, typename RenderTree::ContextNode* context)
00299 {
00300
00301 if (IsNew (*context))
00302 {
00303
00304 RenderContextStack ();
00305 for (int a = 0; a < rtaNumAttachments; a++)
00306 {
00307 lastTarget[a] = context->renderTargets[a].texHandle;
00308 lastSubtexture[a] = context->renderTargets[a].subtexture;
00309 }
00310 lastRenderView = context->renderView;
00311 }
00312
00313
00314 contextStack.Push (context);
00315 }
00316
00317 private:
00318
00324 void RenderContextStack ()
00325 {
00326 if (contextStack.IsEmpty ())
00327 return;
00328
00329
00330 typename RenderTree::ContextNode* context = contextStack.Get (0);
00331
00332 targetSetup (*context);
00333
00334 RenderView* rview = context->renderView;
00335
00336 int drawFlags = CSDRAW_3DGRAPHICS;
00337 drawFlags |= context->drawFlags;
00338
00339 iCamera* cam = rview->GetCamera ();
00340 iClipper2D* clipper = rview->GetClipper ();
00341
00342 if (context->owner.IsDebugClearEnabled())
00343 {
00344 iGraphics2D* G2D = g3d->GetDriver2D();
00345 g3d->BeginDraw (CSDRAW_2DGRAPHICS | CSDRAW_CLEARZBUFFER);
00346 int bgcolor_clear = G2D->FindRGB (0, 255, 255);
00347 G2D->Clear (bgcolor_clear);
00348 }
00349
00350
00351 g3d->SetProjectionMatrix (
00352 context->perspectiveFixup * cam->GetProjectionMatrix ());
00353 g3d->SetClipper (clipper, CS_CLIPPER_TOPLEVEL);
00354
00355 BeginFinishDrawScope bd (g3d, drawFlags);
00356
00357
00358 csArray<iSector*> sectors;
00359 for (size_t c = 0; c < contextStack.GetSize (); ++c)
00360 {
00361 typename RenderTree::ContextNode* ctx = contextStack[c];
00362
00363 size_t numSectors = sectors.GetSize ();
00364 if (sectors.PushSmart (ctx->sector) == numSectors)
00365 {
00366 g3d->SetWorldToCamera (ctx->cameraTransform.GetInverse ());
00367 ctx->sector->GetVisibilityCuller ()->RenderViscull (rview, ctx->shadervars);
00368 }
00369 }
00370
00371
00372 size_t firstContext = 0;
00373 CS::RenderPriorityGrouping lastGrouping = CS::rpgByLayer;
00374 for (size_t c = 0; c < contextStack.GetSize (); ++c)
00375 {
00376 if (contextStack[c]->renderGrouping != lastGrouping)
00377 {
00378
00379 if (lastGrouping == CS::rpgByMesh)
00380 RenderGroupedByMesh (rview, firstContext, c);
00381 else
00382 RenderGroupedByLayer (rview, firstContext, c);
00383 firstContext = c;
00384 lastGrouping = contextStack[c]->renderGrouping;
00385 }
00386 }
00387 if (lastGrouping == CS::rpgByMesh)
00388 RenderGroupedByMesh (rview, firstContext, contextStack.GetSize ());
00389 else
00390 RenderGroupedByLayer (rview, firstContext, contextStack.GetSize ());
00391
00392
00393
00394
00395
00396 g3d->SetClipper (0, CS_CLIPPER_TOPLEVEL);
00397
00398 contextStack.Empty ();
00399
00400 if (context->postEffects.IsValid())
00401 context->postEffects->DrawPostEffects (context->owner);
00402 }
00403
00404 void RenderGroupedByLayer (RenderView* rview, size_t firstContext, size_t lastContext)
00405 {
00406
00407
00408 size_t maxLayer = 0;
00409 for (size_t i = firstContext; i < lastContext; ++i)
00410 {
00411 maxLayer = csMax (maxLayer,
00412 contextStack[i]->svArrays.GetNumLayers());
00413 }
00414
00415
00416 for (size_t layer = 0; layer < maxLayer; ++layer)
00417 {
00418 meshRender.SetLayer (layer);
00419
00420 for (size_t i = firstContext; i < lastContext; ++i)
00421 {
00422 typename RenderTree::ContextNode* context = contextStack.Get (i);
00423
00424
00425 if (layer >= context->svArrays.GetNumLayers()) continue;
00426 g3d->SetWorldToCamera (context->cameraTransform.GetInverse ());
00427 ForEachMeshNode (*context, meshRender);
00428 }
00429 }
00430 }
00431
00432 void RenderGroupedByMesh (RenderView* rview, size_t firstContext, size_t lastContext)
00433 {
00434 for (size_t i = firstContext; i < lastContext; ++i)
00435 {
00436 typename RenderTree::ContextNode* context = contextStack.Get (i);
00437 g3d->SetWorldToCamera (context->cameraTransform.GetInverse ());
00438 ForEachMeshNode (*context, meshRenderByMesh);
00439 }
00440 }
00441
00442
00443 bool IsNew (const typename RenderTree::ContextNode& context)
00444 {
00445 for (int a = 0; a < rtaNumAttachments; a++)
00446 {
00447 if ((lastTarget[a] != context.renderTargets[a].texHandle)
00448 || (lastSubtexture[a] != context.renderTargets[a].subtexture))
00449 return true;
00450 }
00451 return context.renderView != lastRenderView;
00452 }
00453
00454 ContextTargetSetup<typename RenderTree::ContextNode> targetSetup;
00455 SimpleContextRender<RenderTree> meshRender;
00456 SimpleContextRenderByMesh<RenderTree> meshRenderByMesh;
00457
00458 iGraphics3D* g3d;
00459 iShaderManager* shaderMgr;
00460
00461 iTextureHandle* lastTarget[rtaNumAttachments];
00462 int lastSubtexture[rtaNumAttachments];
00463 RenderView* lastRenderView;
00464
00465 csArray<typename RenderTree::ContextNode*> contextStack;
00466 };
00467
00468 template<typename RenderTree>
00469 struct OperationTraits<SimpleTreeRenderer<RenderTree> >
00470 {
00471 typedef OperationNumbered Ordering;
00472 };
00473
00474
00475
00476 }
00477 }
00478
00479 #endif