private void DrawTransparentRenderGroups(GraphicsDevice device, ResourceFactory factory) { var alignment = device.UniformBufferMinOffsetAlignment; var modelBuffStride = 64u; var hostBuffStride = 1u; if (alignment > 64u) { hostBuffStride = alignment / 64u; modelBuffStride = alignment; } // // First sort the transparent render elements by distance to eye point (if not culled). // var drawOrderMap = new SortedList <float, List <Tuple <IRenderGroupState, RenderGroupElement, IPrimitiveSet, uint> > >(); drawOrderMap.Capacity = _cullVisitor.RenderElementCount; var transparentRenderGroupStates = _cullVisitor.TransparentRenderGroup.GetStateList(); var stateToUniformDict = new Dictionary <IRenderGroupState, Matrix4x4[]>(); foreach (var state in transparentRenderGroupStates) { var nDrawables = (uint)state.Elements.Count; var modelMatrixViewBuffer = new Matrix4x4[nDrawables * hostBuffStride]; // Iterate over all elements in this state for (var j = 0; j < nDrawables; ++j) { var renderElement = state.Elements[j]; modelMatrixViewBuffer[j * hostBuffStride] = state.Elements[j].ModelViewMatrix; // Iterate over all primitive sets in this state foreach (var pset in renderElement.PrimitiveSets) { var ctr = pset.GetBoundingBox().Center; // Compute distance eye point var modelView = renderElement.ModelViewMatrix; var ctr_w = Vector3.Transform(ctr, modelView); var dist = Vector3.Distance(ctr_w, Vector3.Zero); if (!drawOrderMap.TryGetValue(dist, out var renderList)) { renderList = new List <Tuple <IRenderGroupState, RenderGroupElement, IPrimitiveSet, uint> >(); drawOrderMap.Add(dist, renderList); } renderList.Add(Tuple.Create(state, renderElement, pset, (uint)j)); } } stateToUniformDict.Add(state, modelMatrixViewBuffer); } DeviceBuffer boundVertexBuffer = null; DeviceBuffer boundIndexBuffer = null; // Now draw transparent elements, back to front IRenderGroupState lastState = null; RenderGraph.RenderInfo ri = null; var currModelViewMatrix = Matrix4x4.Identity; foreach (var renderList in drawOrderMap.Reverse()) { foreach (var element in renderList.Value) { var state = element.Item1; if (null == lastState || state != lastState) { ri = state.GetPipelineAndResources(device, factory, _resourceLayout, Framebuffer); // Set this state's pipeline _commandList.SetPipeline(ri.Pipeline); _commandList.UpdateBuffer(ri.ModelViewBuffer, 0, stateToUniformDict[state]); // Set the resources _commandList.SetGraphicsResourceSet(0, _resourceSet); } uint offset = element.Item4 * modelBuffStride; // Set state-local resources _commandList.SetGraphicsResourceSet(1, ri.ResourceSet, 1, ref offset); var renderGroupElement = element.Item2; if (boundVertexBuffer != renderGroupElement.VertexBuffer) { // Set vertex buffer _commandList.SetVertexBuffer(0, renderGroupElement.VertexBuffer); boundVertexBuffer = renderGroupElement.VertexBuffer; } if (boundIndexBuffer != renderGroupElement.IndexBuffer) { // Set index buffer _commandList.SetIndexBuffer(renderGroupElement.IndexBuffer, IndexFormat.UInt32); boundIndexBuffer = renderGroupElement.IndexBuffer; } element.Item3.Draw(_commandList); lastState = state; } } }
private void DrawTransparentRenderGroups(GraphicsDevice device, ResourceFactory factory) { // // First sort the transparent render elements by distance to eye point (if not culled). // var drawOrderMap = new SortedList <float, List <Tuple <IRenderGroupState, RenderGroupElement, IPrimitiveSet> > >(); drawOrderMap.Capacity = _cullVisitor.RenderElementCount; var transparentRenderGroupStates = _cullVisitor.TransparentRenderGroup.GetStateList(); foreach (var state in transparentRenderGroupStates) { // Iterate over all elements in this state foreach (var renderElement in state.Elements) { // Iterate over all primitive sets in this state foreach (var pset in renderElement.PrimitiveSets) { var ctr = pset.GetBoundingBox().Center; // Compute distance eye point var modelView = renderElement.ModelViewMatrix; var ctr_w = Vector3.Transform(ctr, modelView); var dist = Vector3.Distance(ctr_w, Vector3.Zero); if (!drawOrderMap.TryGetValue(dist, out var renderList)) { renderList = new List <Tuple <IRenderGroupState, RenderGroupElement, IPrimitiveSet> >(); drawOrderMap.Add(dist, renderList); } renderList.Add(Tuple.Create(state, renderElement, pset)); } } } DeviceBuffer boundVertexBuffer = null; DeviceBuffer boundIndexBuffer = null; // Now draw transparent elements, back to front IRenderGroupState lastState = null; RenderGraph.RenderInfo ri = null; var currModelViewMatrix = Matrix4x4.Identity; foreach (var renderList in drawOrderMap.Reverse()) { foreach (var element in renderList.Value) { var state = element.Item1; if (null == lastState || state != lastState) { ri = state.GetPipelineAndResources(device, factory, _resourceLayout); // Set this state's pipeline _commandList.SetPipeline(ri.Pipeline); // Set the resources _commandList.SetGraphicsResourceSet(0, _resourceSet); // Set state-local resources _commandList.SetGraphicsResourceSet(1, ri.ResourceSet); } if (element.Item2.ModelViewMatrix != currModelViewMatrix) { _commandList.UpdateBuffer(ri.ModelViewBuffer, 0, element.Item2.ModelViewMatrix); currModelViewMatrix = element.Item2.ModelViewMatrix; } var renderGroupElement = element.Item2; if (boundVertexBuffer != renderGroupElement.VertexBuffer) { // Set vertex buffer _commandList.SetVertexBuffer(0, renderGroupElement.VertexBuffer); boundVertexBuffer = renderGroupElement.VertexBuffer; } if (boundIndexBuffer != renderGroupElement.IndexBuffer) { // Set index buffer _commandList.SetIndexBuffer(renderGroupElement.IndexBuffer, IndexFormat.UInt16); boundIndexBuffer = renderGroupElement.IndexBuffer; } element.Item3.Draw(_commandList); lastState = state; } } }