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 DispatchCulling() { //MyPerformanceCounter.PerCameraDraw11Write.RenderableObjectsNum = MyRenderablesBoundingTree.m_tree.CountLeaves(MyRenderablesBoundingTree.m_tree.GetRoot()); MyRender11.GetRenderProfiler().StartProfilingBlock("CreateTasksAndWait"); List <Task> tasks = new List <Task>(); for (int i = 1; i < m_cullQuery.Size; i++) { m_cullQuery.FrustumQuery[i].List.Clear(); m_cullQuery.FrustumQuery[i].IsInsideList.Clear(); tasks.Add(Parallel.Start(new MyCullingWork(m_cullQuery.FrustumQuery[i]))); } if (m_cullQuery.Size > 0) { m_cullQuery.FrustumQuery[0].List.Clear(); m_cullQuery.FrustumQuery[0].IsInsideList.Clear(); new MyCullingWork(m_cullQuery.FrustumQuery[0]).DoWork(); } foreach (var task in tasks) { task.Wait(); } MyRender11.GetRenderProfiler().EndProfilingBlock(); //bool ok = false; //for (int i = 0; i < m_cullQuery.Size; i++ ) //{ // if(m_cullQuery.FrustumQuery[i].Type == MyFrustumEnum.MainFrustum) // { // foreach(var e in m_cullQuery.FrustumQuery[i].List) // { // if(e.Proxies[0].Parent.m_owner.ID == 1417) // { // ok = true; break; // } // } // } //} //var x = 7; MyRender11.GetRenderProfiler().StartProfilingBlock("ProcessResults"); for (int i = 0; i < m_cullQuery.Size; i++) { if (m_cullQuery.FrustumQuery[i].Type == MyFrustumEnum.MainFrustum) { MyPerformanceCounter.PerCameraDraw11Write.ViewFrustumObjectsNum = m_cullQuery.FrustumQuery[i].List.Count; int N = m_cullQuery.FrustumQuery[i].List.Count; for (int j = 0; j < N; j++) { foreach (var proxy in m_cullQuery.FrustumQuery[i].List[j].Proxies) { var worldMat = proxy.WorldMatrix; worldMat.Translation -= MyEnvironment.CameraPosition; proxy.ObjectData.LocalMatrix = worldMat; proxy.ObjectData.MaterialIndex = MySceneMaterials.GetDrawMaterialIndex(proxy.PerMaterialIndex); } } } else if (m_cullQuery.FrustumQuery[i].Type == MyFrustumEnum.Cascade0) { MyPerformanceCounter.PerCameraDraw11Write.Cascade0ObjectsNum = m_cullQuery.FrustumQuery[i].List.Count; // m_inCascade0.Clear(); int N = m_cullQuery.FrustumQuery[i].List.Count; for (int j = 0; j < N; j++) { if (m_cullQuery.FrustumQuery[i].IsInsideList[j]) { var item = m_cullQuery.FrustumQuery[i].List[j]; m_inCascade0.Add(item); } } // m_inCascade0_2.Clear(); N = m_cullQuery.FrustumQuery[i].List2.Count; for (int j = 0; j < N; j++) { if (m_cullQuery.FrustumQuery[i].IsInsideList2[j]) { var item = m_cullQuery.FrustumQuery[i].List2[j]; m_inCascade0_2.Add(item); } } } else if (m_cullQuery.FrustumQuery[i].Type == MyFrustumEnum.Cascade1) { // m_inCascade1.Clear(); var list = m_cullQuery.FrustumQuery[i].List; int N = list.Count; for (int j = 0; j < N; j++) { var item = list[j]; if (m_inCascade0.Contains(item)) { // drop list.RemoveAtFast(j); j--; N--; } else if (m_cullQuery.FrustumQuery[i].IsInsideList[j]) { m_inCascade1.Add(item); } } // m_inCascade1_2.Clear(); var list2 = m_cullQuery.FrustumQuery[i].List2; N = list2.Count; for (int j = 0; j < N; j++) { var item = list2[j]; if (m_inCascade0_2.Contains(item)) { // drop list2.RemoveAtFast(j); j--; N--; } else if (m_cullQuery.FrustumQuery[i].IsInsideList2[j]) { m_inCascade1_2.Add(item); } } MyPerformanceCounter.PerCameraDraw11Write.Cascade1ObjectsNum = m_cullQuery.FrustumQuery[i].List.Count; } else if (m_cullQuery.FrustumQuery[i].Type == MyFrustumEnum.Cascade2) { // m_inCascade2.Clear(); var list = m_cullQuery.FrustumQuery[i].List; int N = list.Count; for (int j = 0; j < N; j++) { var item = list[j]; if (m_inCascade0.Contains(item) || m_inCascade1.Contains(item)) { // drop list.RemoveAtFast(j); j--; N--; } else if (m_cullQuery.FrustumQuery[i].IsInsideList[j]) { m_inCascade2.Add(item); } } // m_inCascade2_2.Clear(); var list2 = m_cullQuery.FrustumQuery[i].List2; N = list2.Count; for (int j = 0; j < N; j++) { var item = list2[j]; if (m_inCascade0_2.Contains(item) || m_inCascade1_2.Contains(item)) { // drop list2.RemoveAtFast(j); j--; N--; } else if (m_cullQuery.FrustumQuery[i].IsInsideList2[j]) { m_inCascade2_2.Add(item); } } MyPerformanceCounter.PerCameraDraw11Write.Cascade2ObjectsNum = m_cullQuery.FrustumQuery[i].List.Count; } else if (m_cullQuery.FrustumQuery[i].Type == MyFrustumEnum.Cascade3) { var list = m_cullQuery.FrustumQuery[i].List; int N = list.Count; for (int j = 0; j < N; j++) { var item = list[j]; if (m_inCascade0.Contains(item) || m_inCascade1.Contains(item) || m_inCascade2.Contains(item)) { // drop list.RemoveAtFast(j); j--; N--; } } // var list2 = m_cullQuery.FrustumQuery[i].List2; N = list2.Count; for (int j = 0; j < N; j++) { var item = list2[j]; if (m_inCascade0_2.Contains(item) || m_inCascade1_2.Contains(item) || m_inCascade2_2.Contains(item)) { // drop list2.RemoveAtFast(j); j--; N--; } } MyPerformanceCounter.PerCameraDraw11Write.Cascade3ObjectsNum = m_cullQuery.FrustumQuery[i].List.Count; } if (m_cullQuery.FrustumQuery[i].Ignored != null) { var list = m_cullQuery.FrustumQuery[i].List; int N = list.Count; for (int j = 0; j < N; j++) { if (list[j].Proxies.Length > 0 && m_cullQuery.FrustumQuery[i].Ignored.Contains(list[j].Proxies[0].Parent.m_owner.ID)) { list.RemoveAtFast(j); j--; N--; } } } } MyRender11.GetRenderProfiler().EndProfilingBlock(); }
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; } }