00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_LIGHTSETUP_H__
00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_LIGHTSETUP_H__
00021
00026 #include "iengine/lightmgr.h"
00027 #include "iutil/object.h"
00028 #include "iutil/objreg.h"
00029 #include "ivideo/shader/shader.h"
00030
00031 #include "csgfx/lightsvcache.h"
00032 #include "csgfx/shadervarblockalloc.h"
00033 #include "csplugincommon/rendermanager/operations.h"
00034 #include "csplugincommon/rendermanager/rendertree.h"
00035
00036 class csShaderVariable;
00037
00038 namespace CS
00039 {
00040 namespace RenderManager
00041 {
00042 struct LayerHelperContextData
00043 {
00044 csArray<size_t> newLayerIndices;
00045 csArray<size_t> newLayerCounts;
00046 };
00047
00048 struct RenderTreeLightingTraits : public RenderTreeStandardTraits
00049 {
00050 struct ContextNodeExtraDataType
00051 {
00052 LayerHelperContextData layerHelperData;
00053 };
00054 };
00055
00062 template<typename RenderTree, typename LayerConfigType,
00063 typename NewLayersType>
00064 class LayerHelper
00065 {
00066 public:
00073 LayerHelper (LayerHelperContextData& contextData,
00074 const LayerConfigType& layerConfig,
00075 NewLayersType& newLayers) : contextData (contextData),
00076 layerConfig (layerConfig), newLayers (newLayers)
00077 {
00078 if (contextData.newLayerIndices.GetSize() == 0)
00079 {
00080 contextData.newLayerIndices.SetSize (layerConfig.GetLayerCount ());
00081 contextData.newLayerCounts.SetSize (layerConfig.GetLayerCount ());
00082 for (size_t l = 0; l < layerConfig.GetLayerCount (); l++)
00083 {
00084 contextData.newLayerIndices[l] = l;
00085 contextData.newLayerCounts[l] = 1;
00086 }
00087 }
00088 }
00089
00091 size_t GetNewLayerIndex (size_t layer, size_t subLayer) const
00092 {
00093 return contextData.newLayerIndices[layer] + subLayer;
00094 }
00095
00097 size_t GetSubLayerCount (size_t layer) const
00098 {
00099 return contextData.newLayerCounts[layer];
00100 }
00101
00107 void Ensure (size_t layer, size_t neededSubLayers,
00108 typename RenderTree::ContextNode& context)
00109 {
00110 if (neededSubLayers > contextData.newLayerCounts[layer])
00111 {
00112
00113
00114
00115 size_t insertLayerNum = neededSubLayers - contextData.newLayerCounts[layer];
00116
00117 for (size_t n = contextData.newLayerCounts[layer]; n < neededSubLayers; n++)
00118 {
00119 context.InsertLayer (contextData.newLayerIndices[layer] + n - 1);
00120 newLayers.InsertLayer (contextData.newLayerIndices[layer] + n - 1, layer);
00121 }
00122
00123 for (size_t l = layer+1; l < layerConfig.GetLayerCount (); l++)
00124 contextData.newLayerIndices[l] += insertLayerNum;
00125 contextData.newLayerCounts[layer] += insertLayerNum;
00126 }
00127 }
00128 protected:
00129 LayerHelperContextData& contextData;
00130 const LayerConfigType& layerConfig;
00131 NewLayersType& newLayers;
00132 };
00133
00139 struct LightSettings
00140 {
00142 csLightType type;
00144 csFlags lightFlags;
00145
00147 bool operator== (const LightSettings& other) const
00148 { return (type == other.type) && (lightFlags == other.lightFlags); }
00150 bool operator!= (const LightSettings& other) const
00151 { return (type != other.type) || (lightFlags != other.lightFlags); }
00152 };
00153
00158 class CS_CRYSTALSPACE_EXPORT LightingSorter
00159 {
00160 size_t lightLimit;
00161 public:
00163 struct LightInfo
00164 {
00166 iLight* light;
00168 bool isStatic;
00173 uint numSubLights;
00175 uint* subLights;
00177 LightSettings settings;
00178 };
00179
00185 struct PersistentData
00186 {
00187 csArray<LightInfo> lightTypeScratch;
00188 csArray<LightInfo> putBackLights;
00189 csMemoryPool sublightNumMem;
00190
00195 void UpdateNewFrame()
00196 {
00197 lightTypeScratch.DeleteAll();
00198 }
00199 };
00200
00205 LightingSorter (PersistentData& persist, size_t numLights);
00206
00214 void AddLight (const csLightInfluence& influence,
00215 uint numSubLights, const csFlags& lightFlagsMask);
00216
00218 size_t GetSize ()
00219 {
00220 csArray<LightInfo>& putBackLights = persist.putBackLights;
00221 return lightLimit + putBackLights.GetSize();
00222 }
00223
00225 void SetNumLights (size_t numLights);
00226
00228 void SetLightsLimit (size_t limit)
00229 {
00230 lightLimit = csMin (persist.lightTypeScratch.GetSize(), limit);
00231 }
00232
00234 bool GetNextLight (LightInfo& out);
00239 bool GetNextLight (const LightSettings& settings, LightInfo& out);
00240
00242 void PutInFront (LightInfo* lights, size_t num);
00243 protected:
00244 PersistentData& persist;
00245 };
00246
00250 class CS_CRYSTALSPACE_EXPORT LightingVariablesHelper
00251 {
00252 public:
00258 struct PersistentData
00259 {
00260 csShaderVarBlockAlloc<csBlockAllocatorDisposeLeaky<csShaderVariable> >
00261 svAlloc;
00262
00263
00264 csRefArray<csShaderVariable> svKeeper;
00265
00266 PersistentData() : svAlloc (32*1024) {}
00267
00272 void UpdateNewFrame ()
00273 {
00274 svKeeper.Empty();
00275 }
00276 };
00277
00279 LightingVariablesHelper (PersistentData& persist) : persist (persist) {}
00280
00289 bool MergeAsArrayItem (csShaderVariableStack& dst,
00290 csShaderVariable* sv, size_t index);
00291
00297 void MergeAsArrayItems (csShaderVariableStack& dst,
00298 const csRefArray<csShaderVariable>& allVars, size_t index);
00299
00301 csShaderVariable* CreateTempSV (CS::ShaderVarStringID name =
00302 CS::InvalidShaderVarStringID);
00303
00308 csShaderVariable* CreateVarOnStack (CS::ShaderVarStringID name,
00309 csShaderVariableStack& stack);
00310 protected:
00311 PersistentData& persist;
00312 };
00313
00315 template<typename RenderTree, typename LayerConfigType>
00316 class ShadowNone
00317 {
00318 public:
00320 struct CachedLightData
00321 {
00323 uint GetSublightNum() const { return 1; }
00325 void SetupFrame (RenderTree&, ShadowNone&, iLight*) {}
00327 void ClearFrameData() {}
00328 };
00332 struct PersistentData
00333 {
00337 void UpdateNewFrame () {}
00339 void Initialize (iObjectRegistry*,
00340 RenderTreeBase::DebugPersistent&) {}
00341 };
00343 struct ShadowParameters {};
00344
00345 ShadowNone() {}
00346 ShadowNone (PersistentData& persist,
00347 const LayerConfigType& layerConfig,
00348 typename RenderTree::MeshNode* node,
00349 ShadowParameters&) { }
00350
00352 template<typename _CachedLightData>
00353 uint HandleOneLight (typename RenderTree::MeshNode::SingleMesh& singleMesh,
00354 iLight* light, _CachedLightData& lightData,
00355 csShaderVariableStack* lightStacks,
00356 uint lightNum, uint sublight)
00357 { return 1; }
00358
00363 static bool NeedFinalHandleLight() { return false; }
00365 void FinalHandleLight (iLight*, CachedLightData&) { }
00366
00371 csFlags GetLightFlagsMask () const { return csFlags (CS_LIGHT_NOSHADOWS); }
00372
00374 size_t GetLightLayerSpread() const { return 1; }
00375 };
00376
00400 template<typename RenderTree, typename LayerConfigType,
00401 typename ShadowHandler = ShadowNone<RenderTree, LayerConfigType> >
00402 class LightSetup
00403 {
00404 public:
00405 class PostLightingLayers;
00406
00407 protected:
00409 struct CachedLightData : public ShadowHandler::CachedLightData
00410 {
00411 const csRefArray<csShaderVariable>* shaderVars;
00412 };
00413
00419 template<typename _ShadowHandler>
00420 size_t HandleLights (_ShadowHandler& shadows,
00421 size_t overallPass, LightingSorter& sortedLights,
00422 size_t layer, LayerHelper<RenderTree, LayerConfigType,
00423 PostLightingLayers>& layers, const LayerConfigType& layerConfig,
00424 typename RenderTree::MeshNode::SingleMesh& mesh,
00425 typename RenderTree::MeshNode* node)
00426 {
00427
00428
00429 iShader* shaderToUse =
00430 node->GetOwner().shaderArray[layers.GetNewLayerIndex (layer, 0)
00431 * node->GetOwner().totalRenderMeshes + mesh.contextLocalId];
00432 if (!shaderToUse) return 0;
00433
00434 UpdateMetadata (layer, shaderToUse);
00435 const csShaderMetadata& lastMetadata = metadataCache[layer].metadata;
00436 if ((lastMetadata.numberOfLights == 0)
00437 && !layerConfig.IsAmbientLayer (layer)) return 0;
00438
00439 LightingVariablesHelper lightVarsHelper (persist.varsHelperPersist);
00440
00441 size_t layerLights = csMin (sortedLights.GetSize (),
00442 layerConfig.GetMaxLightNum (layer));
00443 if (lastMetadata.numberOfLights == 0)
00444 layerLights = 0;
00445 if (layerLights == 0)
00446 {
00447 if (!layerConfig.IsAmbientLayer (layer)) return 0;
00448
00449
00450 layers.Ensure (layer, 1, node->GetOwner());
00451
00452 csShaderVariableStack localStack;
00453 node->GetOwner().svArrays.SetupSVStack (localStack,
00454 layers.GetNewLayerIndex (layer, 0),
00455 mesh.contextLocalId);
00456
00457 csShaderVariable* lightNum = lightVarsHelper.CreateVarOnStack (
00458 persist.svNames.GetDefaultSVId (
00459 csLightShaderVarCache::varLightCount), localStack);
00460 lightNum->SetValue ((int)0);
00461
00462 csShaderVariable* passNum = lightVarsHelper.CreateVarOnStack (
00463 persist.svPassNum, localStack);
00464 passNum->SetValue ((int)0);
00465
00466 return 0;
00467 }
00468 else
00469 {
00470 bool meshIsStaticLit = mesh.meshFlags.Check (CS_ENTITY_STATICLIT);
00471
00472
00473 CS_ALLOC_STACK_ARRAY(LightingSorter::LightInfo, renderLights, layerLights);
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 size_t remainingLights = layerLights;
00485 size_t totalWithSublights = 0;
00486 {
00487 size_t firstLight = 0;
00488
00489 while (firstLight < layerLights)
00490 {
00491 if (!sortedLights.GetNextLight (renderLights[firstLight]))
00492 break;
00493 size_t realNum = 1;
00494 LightSettings lightSettings;
00495 lightSettings = renderLights[firstLight].settings;
00496 totalWithSublights += renderLights[firstLight].numSubLights;
00497 size_t maxPassLights = lastMetadata.numberOfLights *
00498 layerConfig.GetMaxLightPasses (layer);
00499 maxPassLights = csMin (maxPassLights, remainingLights);
00500
00501 for (; realNum < maxPassLights; realNum++)
00502 {
00503
00504 if (!sortedLights.GetNextLight (lightSettings,
00505 renderLights[firstLight + realNum]))
00506 break;
00507 totalWithSublights += renderLights[firstLight + realNum].numSubLights;
00508 }
00509
00510 firstLight += realNum;
00511 remainingLights -= realNum;
00512 }
00513 remainingLights = firstLight;
00514 }
00515
00516
00517 CS_ALLOC_STACK_ARRAY(LightingSorter::LightInfo*, renderSublights,
00518 totalWithSublights);
00519 CS_ALLOC_STACK_ARRAY(uint, renderSublightNums, totalWithSublights);
00520 {
00521 size_t i = 0;
00522 for (size_t l = 0; l < remainingLights; l++)
00523 {
00524 LightingSorter::LightInfo& li = renderLights[l];
00525 for (uint s = 0; s < li.numSubLights; s++)
00526 {
00527 renderSublights[i] = &li;
00528 renderSublightNums[i] = li.subLights[s];
00529 i++;
00530 }
00531 }
00532 }
00533
00534
00535
00536
00537 size_t firstLight = 0;
00538 remainingLights = totalWithSublights;
00539 size_t totalLayers = 0;
00540 while (firstLight < totalWithSublights)
00541 {
00542 if (totalLayers >= layerConfig.GetMaxLightPasses (layer))
00543 break;
00544
00545
00546 size_t maxPassLights = lastMetadata.numberOfLights *
00547 layerConfig.GetMaxLightPasses (layer);
00548 maxPassLights = csMin (maxPassLights, remainingLights);
00549
00550
00551 size_t num = 1;
00552 LightSettings lightSettings = renderSublights[firstLight]->settings;
00553 for (; num < maxPassLights; num++)
00554 {
00555 if (renderSublights[firstLight + num]->settings != lightSettings)
00556 break;
00557 }
00558 size_t thisPassLayers;
00559 thisPassLayers = (num + lastMetadata.numberOfLights - 1)
00560 / lastMetadata.numberOfLights;
00561 thisPassLayers = csMin (totalLayers + thisPassLayers,
00562 layerConfig.GetMaxLightPasses (layer)) - totalLayers;
00563 if (thisPassLayers == 0)
00564
00565 break;
00566
00567 firstLight += num;
00568 remainingLights -= num;
00569 totalLayers += thisPassLayers * shadows.GetLightLayerSpread();
00570 }
00571 layers.Ensure (layer, totalLayers, node->GetOwner());
00572 if (remainingLights > 0)
00573 {
00574 renderSublights[firstLight]->subLights += renderSublightNums[firstLight];
00575 renderSublights[firstLight]->numSubLights -= renderSublightNums[firstLight];
00576 sortedLights.PutInFront (*(renderSublights + firstLight), 1);
00577 size_t l = firstLight + renderSublights[firstLight]->numSubLights;
00578 while (l < firstLight + remainingLights)
00579 {
00580 sortedLights.PutInFront (*(renderSublights + l), 1);
00581 l += renderSublights[l]->numSubLights;
00582 }
00583 }
00584
00585 csShaderVariableStack* localStacks =
00586 new csShaderVariableStack[shadows.GetLightLayerSpread()];
00587
00588
00589 remainingLights = firstLight;
00590 firstLight = 0;
00591 totalLayers = 0;
00592 while (firstLight < layerLights)
00593 {
00594 if (totalLayers >= layerConfig.GetMaxLightPasses (layer))
00595 break;
00596
00597 LightSettings lightSettings = renderSublights[firstLight]->settings;
00598 size_t num = 1;
00599 for (; num < remainingLights; num++)
00600 {
00601 if (renderSublights[firstLight+num]->settings != lightSettings)
00602 break;
00603 }
00604
00605
00606 size_t thisPassLayers;
00607 thisPassLayers = (num + lastMetadata.numberOfLights - 1)
00608 / lastMetadata.numberOfLights;
00609 thisPassLayers = csMin (totalLayers + thisPassLayers,
00610 layerConfig.GetMaxLightPasses (layer)) - totalLayers;
00611 if (thisPassLayers == 0)
00612
00613 break;
00614 size_t neededLayers = totalLayers
00615 + thisPassLayers*shadows.GetLightLayerSpread();
00616
00617
00618 for (size_t n = 0; n < thisPassLayers; n++)
00619 {
00620 if ((totalLayers != 0) || (n > 0))
00621 {
00622
00623
00624 node->GetOwner().CopyLayerShader (mesh.contextLocalId,
00625 layers.GetNewLayerIndex (layer, 0),
00626 layers.GetNewLayerIndex (layer, n*shadows.GetLightLayerSpread() + totalLayers));
00627 }
00628
00629 size_t thisNum = csMin (num,
00630 layerConfig.GetMaxLightNum (layer));
00631 thisNum = csMin (thisNum, (size_t)lastMetadata.numberOfLights);
00632
00633 for (size_t s = 0; s < shadows.GetLightLayerSpread(); s++)
00634 {
00635 node->GetOwner().svArrays.SetupSVStack (localStacks[s],
00636 layers.GetNewLayerIndex (layer,
00637 n*shadows.GetLightLayerSpread() + totalLayers) + s,
00638 mesh.contextLocalId);
00639
00640 csShaderVariable* lightNum = lightVarsHelper.CreateVarOnStack (
00641 persist.svNames.GetDefaultSVId (
00642 csLightShaderVarCache::varLightCount), localStacks[s]);
00643 lightNum->SetValue ((int)thisNum);
00644
00645 csShaderVariable* passNum = lightVarsHelper.CreateVarOnStack (
00646 persist.svPassNum, localStacks[s]);
00647 passNum->SetValue ((int)(n + totalLayers));
00648
00649 csShaderVariable* lightTypeSV = lightVarsHelper.CreateVarOnStack (
00650 persist.svNames.GetLightSVId (
00651 csLightShaderVarCache::lightType), localStacks[s]);
00652 lightTypeSV->SetValue ((int)(lightSettings.type));
00653 }
00654
00655 CachedLightData* thisLightSVs;
00656 iLight* light = 0;
00657 for (uint l = 0; l < thisNum; l++)
00658 {
00659 bool isStaticLight = renderSublights[firstLight + l]->isStatic;
00660 light = renderSublights[firstLight + l]->light;
00661 thisLightSVs = persist.lightDataCache.GetElementPointer (light);
00662
00663 uint lSpread = shadows.HandleOneLight (mesh, light, *thisLightSVs,
00664 localStacks, l, renderSublightNums[firstLight + l]);
00665 if (lSpread == 0) continue;
00666
00667 uint initialActualSpread = 0;
00668 if (node->sorting == CS_RENDPRI_SORT_BACK2FRONT)
00669 {
00670
00671
00672
00673
00674
00675 initialActualSpread = (uint)shadows.GetLightLayerSpread()
00676 - CS::Utility::BitOps::ComputeBitsSet (lSpread);
00677 }
00678 uint actualSpread = initialActualSpread;
00679 for (size_t s = 0; s < shadows.GetLightLayerSpread(); s++)
00680 {
00681 if (!(lSpread & (1 << s))) continue;
00682 if (actualSpread > 0)
00683 {
00684 node->GetOwner().CopyLayerShader (mesh.contextLocalId,
00685 layers.GetNewLayerIndex (layer, 0),
00686 layers.GetNewLayerIndex (layer,
00687 n*shadows.GetLightLayerSpread() + actualSpread + totalLayers));
00688 }
00689
00690 lightVarsHelper.MergeAsArrayItems (localStacks[actualSpread],
00691 *(thisLightSVs->shaderVars), l);
00692 if (isStaticLight && meshIsStaticLit
00693 && layerConfig.GetStaticLightsSettings ().specularOnly)
00694 {
00695 lightVarsHelper.MergeAsArrayItem (localStacks[actualSpread],
00696 persist.diffuseBlack, l);
00697 }
00698 actualSpread++;
00699 }
00700 if (initialActualSpread != 0)
00701 {
00702 node->GetOwner().shaderArray[layers.GetNewLayerIndex (layer,
00703 n*shadows.GetLightLayerSpread() + totalLayers)
00704 * node->GetOwner().totalRenderMeshes + mesh.contextLocalId] = 0;
00705 }
00706 }
00707 firstLight += thisNum;
00708 num -= thisNum;
00709 remainingLights -= thisNum;
00710 }
00711
00712 totalLayers = neededLayers;
00713 }
00714
00715 delete[] localStacks;
00716
00717 return firstLight;
00718 }
00719 }
00720
00721
00722 struct CachedShaderMetadata
00723 {
00724 iShader* shader;
00725 csShaderMetadata metadata;
00726
00727 CachedShaderMetadata() : shader (0) {}
00728 };
00729 csArray<CachedShaderMetadata> metadataCache;
00730
00731 inline void UpdateMetadata (size_t layer, iShader* shaderToUse)
00732 {
00733 if (shaderToUse != metadataCache[layer].shader)
00734 {
00735 metadataCache[layer].metadata = shaderToUse->GetMetadata();
00736 metadataCache[layer].shader = shaderToUse;
00737 }
00738 }
00739 public:
00740 struct PersistentData;
00741 typedef csArray<iShader*> ShaderArrayType;
00742 typedef ShadowHandler ShadowHandlerType;
00743 typedef typename ShadowHandler::ShadowParameters ShadowParamType;
00744
00748 LightSetup (PersistentData& persist, iLightManager* lightmgr,
00749 SVArrayHolder& svArrays, const LayerConfigType& layerConfig,
00750 ShadowParamType& shadowParam)
00751 : persist (persist), lightmgr (lightmgr),
00752 svArrays (svArrays), allMaxLights (0), newLayers (layerConfig),
00753 shadowParam (shadowParam)
00754 {
00755
00756 for (size_t layer = 0; layer < layerConfig.GetLayerCount (); ++layer)
00757 {
00758 const size_t layerMax = layerConfig.GetMaxLightNum (layer);
00759
00760 allMaxLights += csMin (layerMax, ((size_t)~0) - allMaxLights);
00761 }
00762 }
00763
00769 void operator() (typename RenderTree::MeshNode* node)
00770 {
00771
00772 const LayerConfigType& layerConfig = newLayers.GetOriginalLayers();
00773
00774 metadataCache.SetSize (layerConfig.GetLayerCount());
00775
00776
00777
00778
00779 LayerHelper<RenderTree, LayerConfigType,
00780 PostLightingLayers> layerHelper (
00781 static_cast<RenderTreeLightingTraits::ContextNodeExtraDataType&> (
00782 node->GetOwner()).layerHelperData, layerConfig, newLayers);
00783 ShadowHandler shadows (persist.shadowPersist, layerConfig,
00784 node, shadowParam);
00785 ShadowNone<RenderTree, LayerConfigType> noShadows;
00786
00787 for (size_t i = 0; i < node->meshes.GetSize (); ++i)
00788 {
00789 typename RenderTree::MeshNode::SingleMesh& mesh = node->meshes[i];
00790
00791 size_t numLights = 0;
00792 csLightInfluence* influences = 0;
00793 LightingSorter sortedLights (persist.lightSorterPersist, 0);
00794
00795 if (!mesh.meshFlags.Check(CS_ENTITY_NOLIGHTING))
00796 {
00797 bool meshIsStaticLit = mesh.meshFlags.Check (CS_ENTITY_STATICLIT);
00798 bool skipStatic = meshIsStaticLit
00799 && layerConfig.GetStaticLightsSettings ().nodraw;
00800
00801 uint relevantLightsFlags =
00802 skipStatic ? ((CS_LIGHTQUERY_GET_ALL & ~CS_LIGHTQUERY_GET_TYPE_ALL)
00803 | CS_LIGHTQUERY_GET_TYPE_DYNAMIC)
00804 : CS_LIGHTQUERY_GET_ALL;
00805
00806 lightmgr->GetRelevantLightsSorted (node->GetOwner().sector,
00807 mesh.renderMesh->bbox, influences, numLights, allMaxLights,
00808 &mesh.renderMesh->object2world,
00809 relevantLightsFlags);
00810
00811 sortedLights.SetNumLights (numLights);
00812 for (size_t l = 0; l < numLights; ++l)
00813 {
00814 iLight* light = influences[l].light;
00815 CachedLightData* thisLightSVs =
00816 persist.lightDataCache.GetElementPointer (light);
00817 if (thisLightSVs == 0)
00818 {
00819 CachedLightData newCacheData;
00820 newCacheData.shaderVars =
00821 &(light->GetSVContext()->GetShaderVariables());
00822 thisLightSVs = &persist.lightDataCache.Put (
00823 light, newCacheData);
00824 light->SetLightCallback (persist.GetLightCallback());
00825 }
00826 thisLightSVs->SetupFrame (node->GetOwner().owner, shadows, light);
00827 csFlags lightFlagsMask;
00828 if (mesh.meshFlags.Check (CS_ENTITY_NOSHADOWS))
00829 lightFlagsMask = noShadows.GetLightFlagsMask();
00830 else
00831 lightFlagsMask = shadows.GetLightFlagsMask();
00832 sortedLights.AddLight (influences[l], thisLightSVs->GetSublightNum(),
00833 ~lightFlagsMask);
00834 }
00835 }
00836
00837 size_t lightOffset = 0;
00838 size_t overallPass = 0;
00839 for (size_t layer = 0; layer < layerConfig.GetLayerCount (); ++layer)
00840 {
00841 size_t layerLights = (numLights == 0) ? 0 :
00842 csMin (layerConfig.GetMaxLightNum (layer), numLights - lightOffset);
00843
00844 if (layerLights == 0 && !layerConfig.IsAmbientLayer (layer))
00845 {
00846
00847
00848 node->GetOwner().shaderArray[layerHelper.GetNewLayerIndex (layer, 0)
00849 * node->GetOwner().totalRenderMeshes + mesh.contextLocalId] = 0;
00850 continue;
00851 }
00852
00853 sortedLights.SetLightsLimit (layerLights);
00854 size_t handledLights;
00855 if (mesh.meshFlags.CheckAll (CS_ENTITY_NOSHADOWCAST
00856 | CS_ENTITY_NOSHADOWRECEIVE))
00857 handledLights = HandleLights (noShadows, overallPass, sortedLights,
00858 layer, layerHelper, layerConfig, mesh, node);
00859 else
00860 handledLights = HandleLights (shadows, overallPass, sortedLights,
00861 layer, layerHelper, layerConfig, mesh, node);
00862 overallPass++;
00863 if ((handledLights == 0)
00864 && (!layerConfig.IsAmbientLayer (layer)))
00865 {
00866
00867 node->GetOwner().shaderArray[layerHelper.GetNewLayerIndex (layer, 0)
00868 * node->GetOwner().totalRenderMeshes + mesh.contextLocalId] = 0;
00869 continue;
00870 }
00871 lightOffset += handledLights;
00872 }
00873
00874 lightmgr->FreeInfluenceArray (influences);
00875 }
00876
00877 if (shadows.NeedFinalHandleLight())
00878 {
00879 typename PersistentData::LightDataCache::GlobalIterator lightDataIt (
00880 persist.lightDataCache.GetIterator());
00881 while (lightDataIt.HasNext())
00882 {
00883 csPtrKey<iLight> light;
00884 CachedLightData& data = lightDataIt.Next (light);
00885 shadows.FinalHandleLight (light, data);
00886 data.ClearFrameData();
00887 }
00888 }
00889 }
00890
00891 class PostLightingLayers
00892 {
00893 const LayerConfigType& layerConfig;
00894 csArray<size_t> layerMap;
00895
00896 friend class LightSetup;
00897 const LayerConfigType& GetOriginalLayers() const
00898 {
00899 return layerConfig;
00900 }
00901 public:
00902 PostLightingLayers (const LayerConfigType& layerConfig)
00903 : layerConfig (layerConfig)
00904 {
00905 layerMap.SetCapacity (layerConfig.GetLayerCount());
00906 for (size_t l = 0; l < layerConfig.GetLayerCount(); l++)
00907 layerMap.Push (l);
00908 }
00909
00910 size_t GetLayerCount () const
00911 {
00912 return layerMap.GetSize();
00913 }
00914
00915 const csStringID* GetShaderTypes (size_t layer, size_t& num) const
00916 {
00917 return layerConfig.GetShaderTypes (layerMap[layer], num);
00918 }
00919
00920 iShader* GetDefaultShader (size_t layer) const
00921 {
00922 return layerConfig.GetDefaultShader (layerMap[layer]);
00923 }
00924
00925 size_t GetMaxLightNum (size_t layer) const
00926 {
00927 return layerConfig.GetMaxLightNum (layerMap[layer]);
00928 }
00929
00930 size_t GetMaxLightPasses (size_t layer) const
00931 {
00932 return layerConfig.GetMaxLightPasses (layerMap[layer]);
00933 }
00934 bool IsAmbientLayer (size_t layer) const
00935 {
00936 return layerConfig.IsAmbientLayer (layerMap[layer]);
00937 }
00938
00939 void InsertLayer (size_t after, size_t oldLayer)
00940 {
00941 layerMap.Insert (after+1, oldLayer);
00942 }
00943 };
00944
00949 const PostLightingLayers& GetPostLightingLayers () const
00950 {
00951 return newLayers;
00952 }
00953
00959 struct PersistentData
00960 {
00961 typename ShadowHandler::PersistentData shadowPersist;
00962 LightingSorter::PersistentData lightSorterPersist;
00963 csLightShaderVarCache svNames;
00964 CS::ShaderVarStringID svPassNum;
00965 csRef<csShaderVariable> diffuseBlack;
00966 LightingVariablesHelper::PersistentData varsHelperPersist;
00967 typedef csHash<CachedLightData, csPtrKey<iLight> > LightDataCache;
00968 LightDataCache lightDataCache;
00969
00970 ~PersistentData()
00971 {
00972 if (lcb.IsValid()) lcb->parent = 0;
00973 }
00974
00980 void Initialize (iObjectRegistry* objReg,
00981 RenderTreeBase::DebugPersistent& dbgPersist)
00982 {
00983 csRef<iShaderManager> shaderManager =
00984 csQueryRegistry<iShaderManager> (objReg);
00985
00986 iShaderVarStringSet* strings = shaderManager->GetSVNameStringset();
00987 svNames.SetStrings (strings);
00988 svPassNum = strings->Request ("pass number");
00989 shadowPersist.Initialize (objReg, dbgPersist);
00990
00991 diffuseBlack.AttachNew (new csShaderVariable (svNames.GetLightSVId (
00992 csLightShaderVarCache::lightDiffuse)));
00993 diffuseBlack->SetValue (csVector4 (0, 0, 0, 0));
00994 }
00995
01000 void UpdateNewFrame ()
01001 {
01002 shadowPersist.UpdateNewFrame();
01003 lightSorterPersist.UpdateNewFrame();
01004 varsHelperPersist.UpdateNewFrame();
01005 }
01006
01007 iLightCallback* GetLightCallback()
01008 {
01009 if (!lcb.IsValid()) lcb.AttachNew (new LightCallback (this));
01010 return lcb;
01011 }
01012 protected:
01013 class LightCallback : public scfImplementation1<LightCallback,
01014 iLightCallback>
01015 {
01016 public:
01017 PersistentData* parent;
01018
01019 LightCallback (PersistentData* parent)
01020 : scfImplementation1<LightCallback, iLightCallback> (this),
01021 parent (parent) {}
01022
01023 void OnColorChange (iLight* light, const csColor& newcolor) { }
01024 void OnPositionChange (iLight* light, const csVector3& newpos) { }
01025 void OnSectorChange (iLight* light, iSector* newsector) { }
01026 void OnRadiusChange (iLight* light, float newradius) { }
01027 void OnDestroy (iLight* light)
01028 {
01029 if (parent != 0)
01030 {
01031 parent->lightDataCache.DeleteAll (light);
01032 }
01033 }
01034 void OnAttenuationChange (iLight* light, int newatt) { }
01035 };
01036 csRef<LightCallback> lcb;
01037 };
01038
01039 private:
01040 PersistentData& persist;
01041 iLightManager* lightmgr;
01042 SVArrayHolder& svArrays;
01043 size_t allMaxLights;
01044 PostLightingLayers newLayers;
01045 ShadowParamType& shadowParam;
01046 };
01047
01048 }
01049 }
01050
01051 #endif // __CS_CSPLUGINCOMMON_RENDERMANAGER_LIGHTSETUP_H__