internal void IssueQuery(MyCullProxy cullProxy)
        {   
            // Test code, WIP
            var renderContext = MyRender11.RC;
            var renderableProxy = cullProxy.RenderableProxies[0];
            renderContext.Begin(m_query);

            MyRenderingPass.FillBuffers(renderableProxy, renderContext);
            MyRenderingPass.BindProxyGeometry(renderableProxy, renderContext);

            MyRenderUtils.BindShaderBundle(renderContext, renderableProxy.DepthShaders);

            var submesh = renderableProxy.DrawSubmesh;
            renderContext.DrawIndexed(submesh.IndexCount, submesh.StartIndex, submesh.BaseVertex);

            renderContext.End(m_query);
        }
Exemple #2
0
        internal void IssueQuery(MyCullProxy cullProxy)
        {
            // Test code, WIP
            var renderContext   = MyRender11.RC;
            var renderableProxy = cullProxy.RenderableProxies[0];

            renderContext.Begin(m_query);

            MyRenderingPass.FillBuffers(renderableProxy, renderContext);
            MyRenderingPass.BindProxyGeometry(renderableProxy, renderContext);

            MyRenderUtils.BindShaderBundle(renderContext, renderableProxy.DepthShaders);

            var submesh = renderableProxy.DrawSubmesh;

            renderContext.DrawIndexed(submesh.IndexCount, submesh.StartIndex, submesh.BaseVertex);

            renderContext.End(m_query);
        }
        internal override void Destruct()
        {
            if(m_btreeProxy != -1)
            {
                MyScene.RenderablesDBVH.RemoveProxy(m_btreeProxy);
                m_btreeProxy = -1;
            }
            if(m_cullProxy != null)
            {
                MyProxiesFactory.Remove(m_cullProxy);
                m_cullProxy = null;
            }
            DeallocateLodProxies();
            ModelProperties.Clear();

            base.Destruct();
        }
        internal override void Construct()
        {
            base.Construct();

            Type = MyActorComponentEnum.Renderable;
            //m_mesh = null;
            m_lods = null;
            m_cullProxy = MyProxiesFactory.CreateCullProxy();
            m_btreeProxy = -1;

            Mesh = MeshId.NULL;
            Instancing = InstancingId.NULL;
            
            m_instanceCount = 0;
            m_startInstance = 0;

            m_isRenderedStandalone = true;

            m_keyColor = Vector3.One;
            m_objectDithering = 0;

            m_renderableProxiesForLodTransition = null;

            m_lodTransitionState = 0;
            m_lod = 0;

            m_voxelLod = -1;
            m_additionalFlags = 0;

            ModelProperties = new Dictionary<MyEntityMaterialKey, MyModelProperties>();
        }
        // return true if can be removed from queue
        internal unsafe bool RebuildRenderProxies()
        {
            bool notReady = Mesh == MeshId.NULL;
            bool notNeeded = !IsRendered || !m_owner.RenderDirty;
            if(notReady)
            {
                return false;
            }
            if(notNeeded)
            {
                return true;
            }

            if(!m_owner.m_localAabb.HasValue)
            {
                SetLocalAabbToModelLod(0);
            }
            

            if (m_btreeProxy == -1)
            {
                m_btreeProxy = MyScene.RenderablesDBVH.AddProxy(ref m_owner.Aabb, m_cullProxy, 0);
            }

            if (!MyMeshes.IsVoxelMesh(Mesh))
            {
                MyShaderUnifiedFlags vsFlags = MyShaderUnifiedFlags.NONE;
                var skinning = m_owner.GetComponent(MyActorComponentEnum.Skinning) as MySkinningComponent;
                bool skinningEnabled = skinning != null && skinning.SkinMatrices != null;
                var objectConstantsSize = sizeof(MyObjectData);

                if (skinningEnabled)
                {
                    objectConstantsSize += sizeof(Matrix) * 60;
                }

                DeallocateLodProxies();

                m_lods = new MyRenderLod[Mesh.Info.LodsNum];
                for (int i = 0; i < m_lods.Length; i++)
                {
                    m_lods[i] = new MyRenderLod();
                    RebuildLodProxy(i, skinningEnabled, skinning, objectConstantsSize);
                }
            }
            else
            {
                RebuildVoxelRenderProxies();
            }

                //// create proxies for transitions
                //for (int i = 0; i < m_lods.Length - 1; i++)
                //{
                //    m_lods[i].RenderableProxiesForLodTransition = m_lods[i].RenderableProxies.Concat(m_lods[i + 1].RenderableProxies).ToArray();
                //    m_lods[i].TransitionUpSortingKeys = m_lods[i].SortingKeys.Concat(m_lods[i + 1].SortingKeys).ToArray();
                //}

                //m_currentLod = 0;
                //m_prevLod = 0;
                //m_lodState = 0;
                //m_cullProxy.Proxies = m_lods[0].RenderableProxies;
                //m_cullProxy.SortingKeys = m_lods[0].SortingKeys;
            
            //

            m_renderableProxiesForLodTransition = new MyCullProxy[m_lods.Length - 1];
            float currentDistance = CalculateViewerDistance();
            m_lod = 0;
            for (int i = 0; i < m_lods.Length - 1; i++)
            {
                m_renderableProxiesForLodTransition[i] = new MyCullProxy();
                m_renderableProxiesForLodTransition[i].Proxies = m_lods[i].RenderableProxies.Concat(m_lods[i + 1].RenderableProxies).ToArray();
                m_renderableProxiesForLodTransition[i].SortingKeys = m_lods[i].SortingKeys.Concat(m_lods[i + 1].SortingKeys).ToArray();
            }

            for (int i = 0; i < m_lods.Length; i++)
            {
                if ( m_lods[i].Distance <= currentDistance && ((i == m_lods.Length - 1) || currentDistance < m_lods[i+1].Distance))
                { 
                    m_lod = i;
                }
            }

            m_lodTransitionState = 0;
            m_cullProxy.Proxies = m_lods[m_lod].RenderableProxies;
            m_cullProxy.SortingKeys = m_lods[m_lod].SortingKeys;

            //UpdateMaterialProxies();
            UpdateProxiesCustomAlpha();
            UpdateProxiesObjectData();

            //Debug.Assert(m_voxelLod == -1 || m_lods[0].RenderableProxies[0].ObjectData.CustomAlpha == m_voxelLod);

            OnFrameUpdate();

            if(MyScene.EntityDisabledMaterials.ContainsKey(m_owner.ID))
            {
                foreach( var row in MyScene.EntityDisabledMaterials[m_owner.ID])
                {
                    var submeshes = MyMeshes.GetLodMesh(Mesh, row.LOD).Info.PartsNum;
                    for(int i=0; i< submeshes; i++)
                    {
                        var part = MyMeshes.GetMeshPart(Mesh, row.LOD, i);
                        var proxy = m_lods[row.LOD].RenderableProxies[i];

                        if(part.Info.Material.Info.Name == row.Material)
                        {
                            proxy.flags |= MyRenderableProxyFlags.SkipInMainView;
                        }
                    }
                }
            }

            foreach (var property in ModelProperties)
            {
                var L = Mesh.Info.LodsNum;

                for (var l = 0; l < L; ++l)
                {
                    var submeshes = MyMeshes.GetLodMesh(Mesh, l).Info.PartsNum;
                    for (int i = 0; i < submeshes; i++)
                    {
                        var part = MyMeshes.GetMeshPart(Mesh, l, i);
                        var proxy = m_lods[l].RenderableProxies[i];

                        if (part.Info.Material.Info.Name == property.Key.Material)
                        {
                            proxy.ObjectData.Emissive = property.Value.Emissivity;
                            proxy.ObjectData.ColorMul = property.Value.ColorMul;

                            //

                            if (property.Value.TextureSwaps != null)
                            {
                                var meshMat = part.Info.Material;
                                var info = meshMat.Info;

                                foreach (var s in property.Value.TextureSwaps)
                                {
                                    switch (s.MaterialSlot)
                                    {
                                        case "NormalGlossTexture":
                                            info.NormalGloss_Texture = s.TextureName;
                                            break;
                                        case "AddMapsTexture":
                                            info.Extensions_Texture = s.TextureName;
                                            break;
                                        case "AlphamaskTexture":
                                            info.Alphamask_Texture = s.TextureName;
                                            break;
                                        default:
                                            info.ColorMetal_Texture = s.TextureName;
                                            break;
                                    }
                                }

                                proxy.Draw.MaterialId = MyMeshMaterials1.GetProxyId(MyMeshMaterials1.GetMaterialId(ref info));
                            }

                            else if (property.Value.CustomRenderedTexture != RwTexId.NULL)
                            {
                                MyMaterialProxyId matProxy = property.Value.CustomMaterialProxy;
                                if (matProxy == MyMaterialProxyId.NULL)
                                {
                                    matProxy = MyMaterials1.AllocateProxy();
                                    property.Value.CustomMaterialProxy = matProxy;

                                    MyMaterials1.ProxyPool.Data[matProxy.Index] = MyMaterials1.ProxyPool.Data[proxy.Draw.MaterialId.Index];
                                    MyMaterials1.ProxyPool.Data[matProxy.Index].MaterialSRVs.SRVs = (ShaderResourceView[])MyMaterials1.ProxyPool.Data[matProxy.Index].MaterialSRVs.SRVs.Clone();
                                    MyMaterials1.ProxyPool.Data[matProxy.Index].MaterialSRVs.SRVs[0] = property.Value.CustomRenderedTexture.ShaderView;
                                    MyMaterials1.ProxyPool.Data[matProxy.Index].MaterialSRVs.Version = (int)m_owner.ID;
                                }

                                proxy.Draw.MaterialId = matProxy;
                            }
                        }
                    }
                }
            }

            m_owner.MarkRenderClean();
            return true;
        }
 public static void Clear(MyCullProxy cullProxy)
 {
     cullProxy.Clear();
 }
        internal static void ProcessFrustumCullingResults()
        {
            if (m_indicesToRemove == null)
            {
                m_indicesToRemove = new List <int>();
            }

            foreach (MyFrustumCullQuery frustumQuery in m_cullQuery.FrustumQueries)
            {
                var  cullProxies     = frustumQuery.List;
                bool isShadowFrustum = ((frustumQuery.Type == MyFrustumEnum.ShadowCascade) || (frustumQuery.Type == MyFrustumEnum.ShadowProjection));
                for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                {
                    MyCullProxy cullProxy = cullProxies[cullProxyIndex];
                    if (cullProxy == null)
                    {
                        continue;
                    }
                    foreach (MyRenderableProxy proxy in cullProxy.Proxies)
                    {
                        bool shouldCastShadows = (proxy.Flags & MyRenderableProxyFlags.CastShadows) == MyRenderableProxyFlags.CastShadows;
                        if (!proxy.IsInViewDistance() || (isShadowFrustum && !shouldCastShadows))
                        {
                            m_indicesToRemove.Add(cullProxyIndex);
                            break;
                        }
                        var worldMat = proxy.WorldMatrix;
                        worldMat.Translation          -= MyEnvironment.CameraPosition;
                        proxy.ObjectData.LocalMatrix   = worldMat;
                        proxy.ObjectData.MaterialIndex = MySceneMaterials.GetDrawMaterialIndex(proxy.PerMaterialIndex);
                    }
                }

                for (int removeIndex = m_indicesToRemove.Count - 1; removeIndex >= 0; --removeIndex)
                {
                    cullProxies.RemoveAtFast(m_indicesToRemove[removeIndex]);
                    frustumQuery.IsInsideList.RemoveAtFast(m_indicesToRemove[removeIndex]);
                }
                m_indicesToRemove.Clear();

                if (frustumQuery.Type == MyFrustumEnum.MainFrustum)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ViewFrustumObjectsNum = frustumQuery.List.Count;
                }
                else if (frustumQuery.Type == MyFrustumEnum.ShadowCascade)
                {
                    while (m_shadowCascadeProxies.Count < MyRenderProxy.Settings.ShadowCascadeCount)
                    {
                        m_shadowCascadeProxies.Add(new HashSet <MyCullProxy>());
                    }
                    while (m_shadowCascadeProxies_2.Count < MyRenderProxy.Settings.ShadowCascadeCount)
                    {
                        m_shadowCascadeProxies_2.Add(new HashSet <MyCullProxy_2>());
                    }

                    // List 1
                    m_shadowCascadeProxies[frustumQuery.CascadeIndex].Clear();
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                    {
                        var  cullProxy = cullProxies[cullProxyIndex];
                        bool containedInHigherCascade = false;

                        // Cull items if they're fully contained in higher resolution cascades
                        for (int hashSetIndex = 0; hashSetIndex < frustumQuery.CascadeIndex; ++hashSetIndex)
                        {
                            if (m_shadowCascadeProxies[hashSetIndex].Contains(cullProxy))
                            {
                                cullProxies.RemoveAtFast(cullProxyIndex);
                                frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                                --cullProxyIndex;
                                containedInHigherCascade = true;
                                break;
                            }
                        }

                        if (!containedInHigherCascade && frustumQuery.IsInsideList[cullProxyIndex])
                        {
                            m_shadowCascadeProxies[frustumQuery.CascadeIndex].Add(cullProxy);
                        }
                    }

                    // List 2
                    var cullProxies_2 = frustumQuery.List2;
                    m_shadowCascadeProxies_2[frustumQuery.CascadeIndex].Clear();
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies_2.Count; ++cullProxyIndex)
                    {
                        var  cullProxy_2 = cullProxies_2[cullProxyIndex];
                        bool containedInHigherCascade = false;

                        // Cull items if they're fully contained in higher resolution cascades
                        for (int hashSetIndex = 0; hashSetIndex < frustumQuery.CascadeIndex; ++hashSetIndex)
                        {
                            if (m_shadowCascadeProxies_2[hashSetIndex].Contains(cullProxy_2))
                            {
                                cullProxies_2.RemoveAtFast(cullProxyIndex);
                                frustumQuery.IsInsideList2.RemoveAtFast(cullProxyIndex);
                                --cullProxyIndex;
                                containedInHigherCascade = true;
                                break;
                            }
                        }

                        if (!containedInHigherCascade && frustumQuery.IsInsideList2[cullProxyIndex])
                        {
                            m_shadowCascadeProxies_2[frustumQuery.CascadeIndex].Add(cullProxy_2);
                        }
                    }

                    MyPerformanceCounter.PerCameraDraw11Write.ShadowCascadeObjectsNum[frustumQuery.CascadeIndex] = frustumQuery.List.Count;
                }

                if (frustumQuery.Ignored != null)
                {
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; cullProxyIndex++)
                    {
                        if (cullProxies[cullProxyIndex].Proxies.Length > 0 && frustumQuery.Ignored.Contains(cullProxies[cullProxyIndex].Proxies[0].Parent.m_owner.ID))
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                        }
                    }
                }
            }
        }
 internal static void Remove(MyCullProxy proxy)
 {
     m_cullProxyPool.Deallocate(proxy);
 }
 public static void Clear(MyCullProxy cullProxy)
 {
     cullProxy.Clear();
 }
Exemple #10
0
        protected override void ProcessCullQueryResults(MyCullQuery cullQuery)
        {
            ProfilerShort.Begin("Reset");

            foreach (MyFrustumCullQuery frustumQuery in cullQuery.FrustumCullQueries)
            {
                var cullProxies = frustumQuery.List;
                foreach (MyCullProxy cullProxy in cullProxies)
                {
                    cullProxy.Updated = false;
                    cullProxy.FirstFullyContainingCascadeIndex = uint.MaxValue;
                }
            }
            ProfilerShort.End();
            foreach (var frustumQuery in cullQuery.FrustumCullQueries)
            {
                ProfilerShort.Begin("Distance cull and update");

                var  cullProxies     = frustumQuery.List;
                bool isShadowFrustum = (frustumQuery.Type == MyFrustumEnum.ShadowCascade) || (frustumQuery.Type == MyFrustumEnum.ShadowProjection);
                for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                {
                    MyCullProxy cullProxy = cullProxies[cullProxyIndex];
                    if (cullProxy == null || cullProxy.RenderableProxies == null || cullProxy.RenderableProxies.Length == 0 || cullProxy.RenderableProxies[0].Parent == null || !cullProxy.RenderableProxies[0].Parent.IsVisible)
                    {
                        m_tmpIndicesToRemove.Add(cullProxyIndex);
                        continue;
                    }

                    if (!cullProxy.Updated)
                    {
                        var renderableComponent = cullProxy.Parent;
                        if (renderableComponent != null)
                        {
                            renderableComponent.OnFrameUpdate();
                            if (renderableComponent.IsCulled)
                            {
                                m_tmpIndicesToRemove.Add(cullProxyIndex);
                                continue;
                            }
                            renderableComponent.UpdateInstanceLods();
                        }

                        // Proxies can get removed in UpdateInstanceLods
                        if (cullProxy.RenderableProxies == null)
                        {
                            m_tmpIndicesToRemove.Add(cullProxyIndex);
                            continue;
                        }

                        foreach (MyRenderableProxy proxy in cullProxy.RenderableProxies)
                        {
                            bool shouldCastShadows = proxy.Flags.HasFlags(MyRenderableProxyFlags.CastShadows) &&
                                                     (proxy.Flags.HasFlags(MyRenderableProxyFlags.DrawOutsideViewDistance) || frustumQuery.CascadeIndex < 4);

                            if (isShadowFrustum && !shouldCastShadows)
                            {
                                m_tmpIndicesToRemove.Add(cullProxyIndex);
                                break;
                            }
                            var worldMat = proxy.WorldMatrix;
                            worldMat.Translation -= MyEnvironment.CameraPosition;
                            proxy.CommonObjectData.LocalMatrix   = worldMat;
                            proxy.CommonObjectData.MaterialIndex = MySceneMaterials.GetDrawMaterialIndex(proxy.PerMaterialIndex);
                        }
                        cullProxy.Updated = true;
                    }
                }

                for (int removeIndex = m_tmpIndicesToRemove.Count - 1; removeIndex >= 0; --removeIndex)
                {
                    cullProxies.RemoveAtFast(m_tmpIndicesToRemove[removeIndex]);
                    frustumQuery.IsInsideList.RemoveAtFast(m_tmpIndicesToRemove[removeIndex]);
                }
                m_tmpIndicesToRemove.SetSize(0);

                ProfilerShort.BeginNextBlock("Culling by query type");
                if (frustumQuery.Type == MyFrustumEnum.MainFrustum)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ViewFrustumObjectsNum = frustumQuery.List.Count;
                }
                else if (frustumQuery.Type == MyFrustumEnum.ShadowCascade)
                {
                    while (m_shadowCascadeProxies2.Count < MyRenderProxy.Settings.ShadowCascadeCount)
                    {
                        m_shadowCascadeProxies2.Add(new HashSet <MyCullProxy_2>());
                    }

                    bool isHighCascade = frustumQuery.CascadeIndex < 3;

                    if (cullProxies.Count == 0)
                    {
                        MyShadowCascades.ShadowCascadeObjectsCounter[frustumQuery.CascadeIndex]  = 0;
                        MyShadowCascades.ShadowCascadeTriangleCounter[frustumQuery.CascadeIndex] = 0;
                    }

                    // List 1
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                    {
                        var cullProxy = cullProxies[cullProxyIndex];

                        if ((isHighCascade && (cullProxy.FirstFullyContainingCascadeIndex < frustumQuery.CascadeIndex - 1)) ||
                            (!isHighCascade && cullProxy.FirstFullyContainingCascadeIndex < frustumQuery.CascadeIndex) ||
                            cullProxy.RenderableProxies == null)
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                            continue;
                        }
                        else
                        {
                            foreach (var renderableProxy in cullProxy.RenderableProxies)
                            {
                                MyShadowCascades.ShadowCascadeTriangleCounter[frustumQuery.CascadeIndex] += (renderableProxy.InstanceCount > 0 ? renderableProxy.InstanceCount : 1) * renderableProxy.DrawSubmesh.IndexCount / 3;
                            }

                            if (frustumQuery.IsInsideList[cullProxyIndex])
                            {
                                cullProxy.FirstFullyContainingCascadeIndex = (uint)frustumQuery.CascadeIndex;
                            }
                        }
                    }

                    // List 2
                    var cullProxies2 = frustumQuery.List2;
                    m_shadowCascadeProxies2[frustumQuery.CascadeIndex].Clear();
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies2.Count; ++cullProxyIndex)
                    {
                        var  cullProxy2 = cullProxies2[cullProxyIndex];
                        bool containedInHigherCascade = false;

                        // Cull items if they're fully contained in higher resolution cascades
                        for (int hashSetIndex = 0; hashSetIndex < frustumQuery.CascadeIndex; ++hashSetIndex)
                        {
                            if (m_shadowCascadeProxies2[hashSetIndex].Contains(cullProxy2))
                            {
                                cullProxies2.RemoveAtFast(cullProxyIndex);
                                frustumQuery.IsInsideList2.RemoveAtFast(cullProxyIndex);
                                --cullProxyIndex;
                                containedInHigherCascade = true;
                                break;
                            }
                        }

                        if (!containedInHigherCascade && frustumQuery.IsInsideList2[cullProxyIndex])
                        {
                            m_shadowCascadeProxies2[frustumQuery.CascadeIndex].Add(cullProxy2);
                        }
                    }

                    MyShadowCascades.ShadowCascadeObjectsCounter[frustumQuery.CascadeIndex] = cullProxies.Count;
                }
                else if (frustumQuery.Type == MyFrustumEnum.ShadowProjection)
                {
                    MyShadows.OtherShadowsTriangleCounter = 0;
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; ++cullProxyIndex)
                    {
                        var cullProxy = frustumQuery.List[cullProxyIndex];
                        if (cullProxy.RenderableProxies == null)
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                            continue;
                        }
                        foreach (var proxy in cullProxy.RenderableProxies)
                        {
                            MyShadows.OtherShadowsTriangleCounter += Math.Max(proxy.InstanceCount, 1) * proxy.DrawSubmesh.IndexCount / 3;
                        }
                    }
                }
                ProfilerShort.End();
                if (frustumQuery.Ignored != null)
                {
                    for (int cullProxyIndex = 0; cullProxyIndex < cullProxies.Count; cullProxyIndex++)
                    {
                        if ((cullProxies[cullProxyIndex].RenderableProxies == null || cullProxies[cullProxyIndex].RenderableProxies.Length == 0 || cullProxies[cullProxyIndex].RenderableProxies[0] == null) || (frustumQuery.Ignored.Contains(cullProxies[cullProxyIndex].RenderableProxies[0].Parent.Owner.ID)))
                        {
                            cullProxies.RemoveAtFast(cullProxyIndex);
                            frustumQuery.IsInsideList.RemoveAtFast(cullProxyIndex);
                            --cullProxyIndex;
                            continue;
                        }
                    }
                }
            }
            for (int cascadeIndex = 0; cascadeIndex < MyRenderProxy.Settings.ShadowCascadeCount; ++cascadeIndex)
            {
                if (MyShadowCascades.ShadowCascadeObjectsCounter[cascadeIndex] >= 0)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ShadowCascadeObjectsNum[cascadeIndex] = MyShadowCascades.ShadowCascadeObjectsCounter[cascadeIndex];
                    MyShadowCascades.ShadowCascadeObjectsCounter[cascadeIndex] = -1;
                }
                if (MyShadowCascades.ShadowCascadeTriangleCounter[cascadeIndex] >= 0)
                {
                    MyPerformanceCounter.PerCameraDraw11Write.ShadowCascadeTriangles[cascadeIndex] = MyShadowCascades.ShadowCascadeTriangleCounter[cascadeIndex];
                    MyShadowCascades.ShadowCascadeTriangleCounter[cascadeIndex] = -1;
                }
            }
            if (MyShadows.OtherShadowsTriangleCounter >= 0)
            {
                MyPerformanceCounter.PerCameraDraw11Write.OtherShadowTriangles = MyShadows.OtherShadowsTriangleCounter;
                MyShadows.OtherShadowsTriangleCounter = -1;
            }
        }
 internal static void Remove(MyCullProxy proxy)
 {
     m_cullProxyPool.Deallocate(proxy);
 }
        internal override void Destruct()
        {
            if(m_btreeProxy != -1)
            {
                MyScene.RenderablesDBVH.RemoveProxy(m_btreeProxy);
                m_btreeProxy = -1;
            }
            if(m_cullProxy != null)
            {
                MyProxiesFactory.Remove(m_cullProxy);
                m_cullProxy = null;
            }
            if(m_lods != null)
            {
                for(int i=0; i<m_lods.Length; i++)
                {
                    m_lods[i].DeallocateProxies();
                }
                m_lods = null;
            }
            ModelProperties.Clear();

            base.Destruct();
        }