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); }
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 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(); }