Exemple #1
0
        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;
                }
            }
        }
        /// <summary>
        /// Cull Visitor for billboard
        /// </summary>
        /// <param name="billboard"></param>
        public override void Apply(IBillboard billboard)
        {
            var bb = billboard.GetBoundingBox();

            if (IsCulled(bb, ModelMatrixStack.Peek()))
            {
                return;
            }

            IPipelineState pso = null;

            // Node specific state
            if (billboard.HasPipelineState)
            {
                pso = billboard.PipelineState;
            }

            // Shared State
            else if (PipelineStateStack.Count != 0)
            {
                pso = PipelineStateStack.Peek();
            }

            // Fallback
            else
            {
                pso = PipelineState.Create();
            }

            var eyeLocal  = GetEyeLocal();
            var modelView = GetModelViewMatrix();

            foreach (var drawable in billboard.Drawables)
            {
                // TODO - need to modify is culled to handle billboard matrix offset
                //if (IsCulled(drawable.GetBoundingBox(), ModelMatrixStack.Peek())) continue;

                var billboardMatrix = billboard.ComputeMatrix(modelView, eyeLocal);

                var drawablePso = pso;
                if (drawable.HasPipelineState)
                {
                    drawablePso = drawable.PipelineState;
                }

                //
                // This allocates / updates vbo/ibos
                //
                drawable.ConfigureDeviceBuffers(GraphicsDevice, ResourceFactory);

                var renderElementCache = new Dictionary <IRenderGroupState, RenderGroupElement>();

                foreach (var pset in drawable.PrimitiveSets)
                {
                    // TODO - need to modify is culled to handle billboard matrix offset
                    //if (IsCulled(pset.GetBoundingBox(), ModelMatrixStack.Peek())) continue;

                    //
                    // Sort into appropriate render group
                    //
                    IRenderGroupState renderGroupState = null;
                    if (drawablePso.BlendStateDescription.AttachmentStates.Contains(BlendAttachmentDescription.AlphaBlend))
                    {
                        renderGroupState = TransparentRenderGroup.GetOrCreateState(drawablePso, pset.PrimitiveTopology, drawable.VertexLayout);
                    }
                    else
                    {
                        renderGroupState = OpaqueRenderGroup.GetOrCreateState(drawablePso, pset.PrimitiveTopology, drawable.VertexLayout);
                    }

                    if (false == renderElementCache.TryGetValue(renderGroupState, out var renderElement))
                    {
                        renderElement = new RenderGroupElement()
                        {
                            ModelViewMatrix = billboardMatrix.PostMultiply(modelView),
                            VertexBuffer    = drawable.GetVertexBufferForDevice(GraphicsDevice),
                            IndexBuffer     = drawable.GetIndexBufferForDevice(GraphicsDevice),
                            PrimitiveSets   = new List <IPrimitiveSet>()
                        };
                        renderGroupState.Elements.Add(renderElement);

                        renderElementCache.Add(renderGroupState, renderElement);
                    }
                    renderElement.PrimitiveSets.Add(pset);
                }
            }
        }
Exemple #3
0
        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;
                }
            }
        }