示例#1
0
 public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
 {
     using (context.PushRenderTargetsAndRestore())
     {
         DrawInternal(context, renderView, renderViewStage, startIndex, endIndex);
     }
 }
 public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
 {
     lock (drawLock)
     {
         DrawInternal(context, renderView, renderViewStage, startIndex, endIndex);
     }
 }
示例#3
0
 public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
 {
     lock (drawLock)
     {
         DrawInternal(context, renderView, renderViewStage, startIndex, endIndex);
     }
 }
示例#4
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            if (renderMeshesToGenerateAEN.Count > 0)
            {
                var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey);

                foreach (var renderMesh in renderMeshesToGenerateAEN)
                {
                    var tessellationState = tessellationStates[renderMesh.StaticObjectNode];
                    if (tessellationState.GeneratedIndicesAEN != null)
                    {
                        continue;
                    }

                    var tessellationMeshDraw = tessellationState.MeshDraw;

                    var indicesAEN = IndexExtensions.GenerateIndexBufferAEN(tessellationMeshDraw.IndexBuffer, tessellationMeshDraw.VertexBuffers[0], context.CommandList);
                    tessellationState.GeneratedIndicesAEN = Buffer.Index.New(Context.GraphicsDevice, indicesAEN);
                    tessellationMeshDraw.IndexBuffer      = new IndexBufferBinding(tessellationState.GeneratedIndicesAEN, true, tessellationMeshDraw.IndexBuffer.Count * 12 / 3);
                    tessellationMeshDraw.DrawCount        = 12 / 3 * tessellationMeshDraw.DrawCount;
                }

                renderMeshesToGenerateAEN.Clear(false);
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage)
        {
            // Update per-view resources only when view changes
            if (currentRenderView == renderView)
            {
                return;
            }

            var viewFeature = renderView.Features[RootRenderFeature.Index];

            RenderViewLightData renderViewData;

            if (!renderViewDatas.TryGetValue(renderView.LightingView ?? renderView, out renderViewData) || viewFeature.Layouts.Count == 0)
            {
                return;
            }

            var viewIndex = renderViews.IndexOf(renderView);

            // Update PerView resources
            foreach (var directLightGroup in shaderPermutation.DirectLightGroups)
            {
                directLightGroup.UpdateViewResources(context, viewIndex);
            }

            foreach (var environmentLight in shaderPermutation.EnvironmentLights)
            {
                environmentLight.UpdateViewResources(context, viewIndex);
            }

            currentRenderView = renderView;
        }
 public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
 {
     lock (drawLock)
     {
         context.PushRenderTargets();
         DrawInternal(context, renderView, renderViewStage, startIndex, endIndex);
         context.PopRenderTargets();
     }
 }
示例#7
0
        /// <inheritdoc/>
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey);

            // TODO: stackalloc?
            var descriptorSetsLocal = descriptorSets.Value;

            if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount)
            {
                descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount];
            }

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;

                // Get effect
                var renderEffect = GetRenderNode(renderNodeReference).RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // Get the extra node data
                var nodeData = renderParticleNodeData[renderNodeReference];
                if (nodeData.IndexCount <= 0)
                {
                    continue;
                }

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(commandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSetsLocal.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSetsLocal[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSetsLocal);

                // Bind the buffers and draw
                commandList.SetVertexBuffer(0, nodeData.VertexBuffer, nodeData.VertexBufferOffset, nodeData.VertexBufferStride);
                commandList.SetIndexBuffer(nodeData.IndexBuffer, nodeData.IndexBufferOffset, ParticleBufferContext.IndexStride != sizeof(short));
                commandList.DrawIndexed(nodeData.IndexCount, 0);
            }
        }
示例#8
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            // First do everything that doesn't change per individual render object
            var graphicsDevice  = context.GraphicsDevice;
            var graphicsContext = context.GraphicsContext;
            var commandList     = context.GraphicsContext.CommandList;

            // Refresh shader, might have changed during runtime
            _decalShader.UpdateEffect(graphicsDevice);

            // Set common shader parameters if needed
            _decalShader.Parameters.Set(TransformationKeys.ViewProjection, renderView.ViewProjection);
            _decalShader.Parameters.Set(TransformationKeys.ViewInverse, Matrix.Invert(renderView.View));

            // Important to release it at the end of the draw, otherwise you'll run out of memory!
            //var depthStencil = context.Resolver.ResolveDepthStencil(commandList.DepthStencilBuffer);
            var depthStencil = context.Resolver.ResolveDepthStencil(graphicsDevice.Presenter.DepthStencilBuffer);       // Must use the Presenter's depth buffer, otherwise it won't appear in the Game Studio

            _decalShader.Parameters.Set(DepthBaseKeys.DepthStencil, depthStencil);

            _decalShader.Parameters.Set(CameraKeys.ViewSize, renderView.ViewSize);
            _decalShader.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));
            _decalShader.Parameters.Set(CameraKeys.NearClipPlane, renderView.NearClipPlane);
            _decalShader.Parameters.Set(CameraKeys.FarClipPlane, renderView.FarClipPlane);

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var decalRendObj        = (DecalRenderObject)renderNode.RenderObject;

                if (decalRendObj.RenderCube == null)
                {
                    continue;   // Next render object
                }

                // Assign shader parameters
                _decalShader.Parameters.Set(TransformationKeys.WorldInverse, Matrix.Invert(decalRendObj.WorldMatrix));
                _decalShader.Parameters.Set(TransformationKeys.WorldViewProjection, decalRendObj.WorldMatrix * renderView.ViewProjection);
                _decalShader.Parameters.Set(TransformationKeys.WorldView, decalRendObj.WorldMatrix * renderView.View);
                _decalShader.Parameters.Set(DecalShaderKeys.DecalTexture, decalRendObj.Texture);
                _decalShader.Parameters.Set(DecalShaderKeys.TextureScale, decalRendObj.TextureScale);
                _decalShader.Parameters.Set(DecalShaderKeys.DecalColor, decalRendObj.Color);

                decalRendObj.RenderCube.Draw(graphicsContext, _decalShader);
            }

            context.Resolver.ReleaseDepthStenctilAsShaderResource(depthStencil);
        }
示例#9
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderBackground    = (RenderBackground)renderNode.RenderObject;

                if (renderBackground.Texture.Dimension == TextureDimension.Texture2D)
                {
                    Draw2D(context, renderBackground);
                }
                else if (renderBackground.Texture.Dimension == TextureDimension.TextureCube)
                {
                    DrawCube(context, renderView, renderBackground);
                }
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            // First do everything that doesn't change per individual render object
            var graphicsDevice  = context.GraphicsDevice;
            var graphicsContext = context.GraphicsContext;
            var commandList     = context.GraphicsContext.CommandList;

            // Refresh shader, might have changed during runtime
            myCustomShader.UpdateEffect(graphicsDevice);

            // Set common shader parameters if needed
            //myCustomShader.Parameters.Set(TransformationKeys.ViewProjection, renderView.ViewProjection);

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var myRenderObject      = (MyRenderObject)renderNode.RenderObject;

                if (myRenderObject.VertexBuffer == null)
                {
                    continue; //next render object
                }
                // Assign shader parameters
                myCustomShader.Parameters.Set(TransformationKeys.WorldViewProjection, myRenderObject.WorldMatrix * renderView.ViewProjection);
                myCustomShader.Parameters.Set(TexturingKeys.Texture0, myRenderObject.Texture);
                myCustomShader.Parameters.Set(MyCustomShaderKeys.TextureScale, myRenderObject.TextureScale);
                myCustomShader.Parameters.Set(MyCustomShaderKeys.Color, myRenderObject.Color);

                // Prepare pipeline state
                pipelineState.State.RootSignature  = myCustomShader.RootSignature;
                pipelineState.State.EffectBytecode = myCustomShader.Effect.Bytecode;
                pipelineState.State.Output.CaptureState(commandList);
                pipelineState.Update();
                commandList.SetPipelineState(pipelineState.CurrentState);

                // Apply the effect
                myCustomShader.Apply(graphicsContext);

                // Set vertex buffer and draw
                commandList.SetVertexBuffer(0, myRenderObject.VertexBuffer, 0, MyRenderObject.VertexDeclaration.VertexStride);
                commandList.Draw(MyRenderObject.VertexCount, 0);
            }
        }
示例#11
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage)
        {
            float blendValue = (selectionService?.DisplaySelectionMask ?? false)
                ? 1.0f
                : MathUtil.Clamp((1.0f - (float)clockSelection.Elapsed.TotalSeconds), 0.0f, 1.0f);

            shader.UpdateEffect(context.GraphicsDevice);

            foreach (var renderNode in renderViewStage.SortedRenderNodes)
            {
                var renderMesh = renderNode.RenderObject as RenderMesh;
                if (renderMesh == null)
                {
                    continue;
                }

                MeshDraw drawData = renderMesh.ActiveMeshDraw;

                // bind VB
                for (int slot = 0; slot < drawData.VertexBuffers.Length; slot++)
                {
                    var vertexBuffer = drawData.VertexBuffers[slot];
                    context.CommandList.SetVertexBuffer(slot, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                }

                // set shader parameters
                shader.Parameters.Set(SelectionWireframeShaderKeys.WorldViewProjection, renderMesh.World * renderView.ViewProjection); // matrix
                shader.Parameters.Set(SelectionWireframeShaderKeys.WorldScale, new Vector3(1.0001f));                                  // increase scale to avoid z-fight
                shader.Parameters.Set(SelectionWireframeShaderKeys.Viewport, new Vector4(context.RenderContext.RenderView.ViewSize, 0, 0));
                shader.Parameters.Set(SelectionWireframeShaderKeys.LineWidth, LineWidth);

                // prepare pipeline state
                pipelineState.State.RootSignature  = shader.RootSignature;
                pipelineState.State.EffectBytecode = shader.Effect.Bytecode;
                pipelineState.State.PrimitiveType  = drawData.PrimitiveType;

                Draw(context, drawData, GetColor(ColorOccludedLines, blendValue), DepthStencilStates.None);           // occluded
                Draw(context, drawData, GetColor(ColorNonOccludedLines, blendValue), DepthStencilStates.DepthRead);   // non-occluded
            }
        }
示例#12
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount];

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                // Get effect
                // TODO: Use real effect slot
                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                commandList.SetPipelineState(renderEffect.PipelineState);

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);
                renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSets.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSets[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetDescriptorSets(0, descriptorSets);

                commandList.DrawQuad();
            }
        }
示例#13
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderBackground    = (RenderBackground)renderNode.RenderObject;

                if (renderBackground.Texture == null)
                {
                    continue;
                }

                if (renderBackground.Is2D)
                {
                    Draw2D(context, renderBackground);
                }
                else
                {
                    Draw3D(context, renderView, renderBackground);
                }
            }
        }
示例#14
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var target         = context.RenderContext.Tags.GetSafe(RenderFrame.Current);
            var graphicsDevice = context.GraphicsDevice;
            var destination    = new RectangleF(0, 0, 1, 1);

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderBackground    = (RenderBackground)renderNode.RenderObject;
                var texture             = renderBackground.Texture;

                var imageBufferMinRatio = Math.Min(texture.ViewWidth / (float)target.Width, texture.ViewHeight / (float)target.Height);
                var sourceSize          = new Vector2(target.Width * imageBufferMinRatio, target.Height * imageBufferMinRatio);
                var source = new RectangleF((texture.ViewWidth - sourceSize.X) / 2, (texture.ViewHeight - sourceSize.Y) / 2, sourceSize.X, sourceSize.Y);

                // TODO GRAPHICS REFACTOR: Disable depth once we sort properly
                spriteBatch.Begin(context.GraphicsContext, SpriteSortMode.FrontToBack, BlendStates.Opaque, graphicsDevice.SamplerStates.LinearClamp, DepthStencilStates.DepthRead, null, backgroundEffect);
                spriteBatch.Parameters.Set(BackgroundEffectKeys.Intensity, renderBackground.Intensity);
                spriteBatch.Draw(texture, destination, source, Color.White, 0, Vector2.Zero, layerDepth: -0.5f);
                spriteBatch.End();
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var target = context.RenderContext.Tags.GetSafe(RenderFrame.Current);
            var graphicsDevice = context.GraphicsDevice;
            var destination = new RectangleF(0, 0, 1, 1);

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);
                var renderBackground = (RenderBackground)renderNode.RenderObject;
                var texture = renderBackground.Texture;
                
                var imageBufferMinRatio = Math.Min(texture.ViewWidth / (float)target.Width, texture.ViewHeight / (float)target.Height);
                var sourceSize = new Vector2(target.Width * imageBufferMinRatio, target.Height * imageBufferMinRatio);
                var source = new RectangleF((texture.ViewWidth - sourceSize.X) / 2, (texture.ViewHeight - sourceSize.Y) / 2, sourceSize.X, sourceSize.Y);

                // TODO GRAPHICS REFACTOR: Disable depth once we sort properly
                spriteBatch.Begin(context.GraphicsContext, SpriteSortMode.FrontToBack, BlendStates.Opaque, graphicsDevice.SamplerStates.LinearClamp, DepthStencilStates.DepthRead, null, backgroundEffect);
                spriteBatch.Parameters.Set(BackgroundEffectKeys.Intensity, renderBackground.Intensity);
                spriteBatch.Draw(texture, destination, source, Color.White, 0, Vector2.Zero, layerDepth: -0.5f);
                spriteBatch.End();
            }
        }
        /// <inheritdoc/>
        public override unsafe void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            // register all texture usage
            foreach (var renderObject in RenderObjects)
            {
                var renderParticleEmitter = (RenderParticleEmitter)renderObject;
                Context.StreamingManager?.StreamResources(renderParticleEmitter.ParticleEmitter.Material.Parameters);
            }

            // Per view - this code was moved here from Prepare(...) so that we can apply the correct Viewport
            {
                var view        = renderView;
                var viewFeature = view.Features[Index];

                Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection);

                // Copy ViewProjection to PerFrame cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB      = resourceGroup.ConstantBuffer.Data;

                    // PerView constant buffer
                    var perViewOffset = viewLayout.GetConstantBufferOffset(this.perViewCBufferOffset);
                    if (perViewOffset != -1)
                    {
                        var perView = (ParticleUtilitiesPerView *)((byte *)mappedCB + perViewOffset);
                        perView->ViewMatrix           = view.View;
                        perView->ProjectionMatrix     = view.Projection;
                        perView->ViewProjectionMatrix = view.ViewProjection;
                        perView->ViewFrustum          = new Vector4(view.ViewSize.X, view.ViewSize.Y, view.NearClipPlane, view.FarClipPlane);

                        perView->Viewport = new Vector4(0,
                                                        0,
                                                        ((float)context.CommandList.Viewport.Width) / ((float)context.CommandList.RenderTarget.Width),
                                                        ((float)context.CommandList.Viewport.Height) / ((float)context.CommandList.RenderTarget.Height));
                    }
                }
            }

            var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey);

            // TODO: stackalloc?
            var descriptorSetsLocal = descriptorSets.Value;

            if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount)
            {
                descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount];
            }

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;

                // Get effect
                var renderEffect = GetRenderNode(renderNodeReference).RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // Get the extra node data
                var nodeData = renderParticleNodeData[renderNodeReference];
                if (nodeData.IndexCount <= 0)
                {
                    continue;
                }

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(commandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSetsLocal.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSetsLocal[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSetsLocal);

                // Bind the buffers and draw
                commandList.SetVertexBuffer(0, nodeData.VertexBuffer, nodeData.VertexBufferOffset, nodeData.VertexBufferStride);
                commandList.SetIndexBuffer(nodeData.IndexBuffer, nodeData.IndexBufferOffset, ParticleBufferContext.IndexStride != sizeof(short));
                commandList.DrawIndexed(nodeData.IndexCount, 0);
            }
        }
            public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage)
            {
                var entity = (renderObject.Source as EntityComponent)?.Entity;

                if (entity != null)
                {
                    var entityId = service.Editor.Controller.GetAbsoluteId(entity);
                    return(service.SelectableIds.Contains(entityId));
                }

                return(false);
            }
示例#18
0
        private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var uiProcessor = SceneInstance.GetCurrent(context.RenderContext).GetProcessor <UIRenderProcessor>();

            if (uiProcessor is null)
            {
                return;
            }

            // Build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderUIElement)renderNode.RenderObject;

                uiElementStates.Add(new UIElementState(renderElement));
            }

            // Evaluate the current draw time (Game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // Update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time            = drawTime;
            renderingContext.RenderTarget    = context.CommandList.RenderTargets[0]; // TODO: Avoid hardcoded index 0

            // Prepare content required for Picking and MouseOver events
            PickingPrepare();

            // Allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;

            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.RenderObject.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description  = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // Update view parameters and perform UI picking
            UIElement elementUnderMouseCursor = null;

            foreach (var uiElementState in uiElementStates)
            {
                var renderObject = uiElementState.RenderObject;
                var rootElement  = renderObject.Page?.RootElement;
                if (rootElement is null)
                {
                    continue;
                }

                UIElement loopedElementUnderMouseCursor = null;

                // Calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = renderObject.Resolution;

                if (renderObject.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);

                    // Update the virtual resolution of the renderer
                    if (renderObject.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                    {
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    }
                    if (renderObject.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                    {
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                    }

                    uiElementState.Update(renderObject, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current);
                    if (cameraComponent != null)
                    {
                        uiElementState.Update(renderObject, cameraComponent);
                    }
                }


                // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element)
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime, ref loopedElementUnderMouseCursor);

                    // Only update resulting element when this one has a value
                    if (loopedElementUnderMouseCursor != null)
                    {
                        elementUnderMouseCursor = loopedElementUnderMouseCursor;
                    }
                }
            }
            UIElementUnderMouseCursor = elementUnderMouseCursor;

            // Render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var renderObject = uiElementState.RenderObject;
                var rootElement  = renderObject.Page?.RootElement;
                if (rootElement is null)
                {
                    continue;
                }

                var updatableRootElement = (IUIElementUpdate)rootElement;
                var virtualResolution    = renderObject.Resolution;

                // Update the rendering context values specific to this element
                renderingContext.Resolution           = virtualResolution;
                renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix;
                renderingContext.DepthStencilBuffer   = renderObject.IsFullScreen ? scopedDepthBuffer : context.CommandList.DepthStencilBuffer;
                renderingContext.ShouldSnapText       = renderObject.SnapText && renderObject.IsBillboard && (renderObject.IsFixedSize || renderObject.IsFullScreen);

                // Calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = uiElementState.WorldViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                }

                var viewportSize           = context.CommandList.Viewport.Size;
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // Set default services
                rootElement.UIElementServices = new UIElementServices {
                    Services = RenderSystem.Services
                };

                // Set default resource dictionary

                // Update layouting context
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // Perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // Update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // Update the UI element hierarchical properties
                //   UI world is translated by a half resolution compared to its quad, which is centered around the origin
                var rootMatrix = Matrix.Translation(-virtualResolution / 2);
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.RenderObject.LastRootMatrix = rootMatrix;

                // Clear and set the Depth buffer as required
                if (renderObject.IsFullScreen)
                {
                    context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // Start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix);

                // End the image draw session
                batch.End();
            }

            PickingClear();

            // Revert the depth stencil buffer to the default value
            context.CommandList.SetRenderTargets(context.CommandList.DepthStencilBuffer, context.CommandList.RenderTargetCount, context.CommandList.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
            public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage)
            {
                var renderMesh = renderObject as RenderMesh;

                return(renderMesh != null &&
                       (HighlightRenderFeature.MaterialHighlightColors.ContainsKey(renderMesh.MaterialPass.Material) ||
                        HighlightRenderFeature.MeshHighlightColors.ContainsKey(renderMesh.Mesh) ||
                        HighlightRenderFeature.MaterialsHighlightedForModel.Contains(renderMesh.MaterialPass.Material) && HighlightRenderFeature.ModelHighlightColors.ContainsKey(renderMesh.RenderModel.ModelComponent)));
            }
示例#20
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current);

            var uiProcessor = renderView.SceneInstance.GetProcessor <UIRenderProcessor>();

            if (uiProcessor == null)
            {
                return;
            }

            //foreach (var uiRoot in uiProcessor.UIRoots)
            //{
            //    // Perform culling on group and accept
            //    if (!renderView.SceneCameraRenderer.CullingMask.Contains(uiRoot.UIComponent.Entity.Group))
            //        continue;

            //    // skips empty UI elements
            //    if (uiRoot.UIComponent.RootElement == null)
            //        continue;

            //    // Project the position
            //    // TODO: This code is duplicated from SpriteComponent -> unify it at higher level?
            //    var worldPosition = new Vector4(uiRoot.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

            //    float projectedZ;
            //    if (uiRoot.UIComponent.IsFullScreen)
            //    {
            //        projectedZ = -uiRoot.TransformComponent.WorldMatrix.M43;
            //    }
            //    else
            //    {
            //        Vector4 projectedPosition;
            //        var cameraComponent = renderView.Camera;
            //        if (cameraComponent == null)
            //            continue;

            //        Vector4.Transform(ref worldPosition, ref cameraComponent.ViewProjectionMatrix, out projectedPosition);
            //        projectedZ = projectedPosition.Z / projectedPosition.W;
            //    }

            //    transparentList.Add(new RenderItem(this, uiRoot, projectedZ));
            //}

            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderUIElement)renderNode.RenderObject;

                uiElementStates.Add(renderElement);
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time            = drawTime;
            renderingContext.RenderTarget    = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0

            var viewport = context.CommandList.Viewport;

            // cache the ratio between viewport and target.
            var viewportSize = viewport.Size;

            viewportTargetRatio = new Vector2(viewportSize.X / renderingContext.RenderTarget.Width, viewportSize.Y / renderingContext.RenderTarget.Height);
            viewportOffset      = new Vector2(viewport.X / viewport.Width, viewport.Y / viewport.Height);

            // compact all the pointer events that happened since last frame to avoid performing useless hit tests.
            CompactPointerEvents();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;

            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.UIComponent.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description  = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.UIComponent;
                var rootElement = uiComponent.RootElement;
                if (rootElement == null)
                {
                    continue;
                }

                var updatableRootElement = (IUIElementUpdate)rootElement;

                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = uiComponent.Resolution;

                if (uiComponent.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);

                    // update the virtual resolution of the renderer
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                    {
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    }
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                    {
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                    }

                    viewParameters.Update(uiComponent.Entity, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current);
                    if (cameraComponent != null)
                    {
                        viewParameters.Update(uiComponent.Entity, cameraComponent);
                    }
                }

                // Analyze the input and trigger the UI element touch and key events
                // Note: this is done before measuring/arranging/drawing the element in order to avoid one frame latency on clicks.
                //       But by doing so the world matrices taken for hit test are the ones calculated during last frame.
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    foreach (var uiState in uiElementStates)
                    {
                        if (uiState.UIComponent.RootElement == null)
                        {
                            continue;
                        }

                        UpdateMouseOver(uiState);
                        UpdateTouchEvents(uiState, drawTime);
                    }
                }

                // update the rendering context values specific to this element
                renderingContext.Resolution           = virtualResolution;
                renderingContext.ViewMatrix           = viewParameters.ViewMatrix;
                renderingContext.ProjectionMatrix     = viewParameters.ProjectionMatrix;
                renderingContext.ViewProjectionMatrix = viewParameters.ViewProjectionMatrix;
                renderingContext.DepthStencilBuffer   = uiComponent.IsFullScreen ? scopedDepthBuffer : currentRenderFrame.DepthStencil;
                renderingContext.ShouldSnapText       = uiComponent.SnapText;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = viewParameters.ViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * viewParameters.ViewProjectionMatrix[0 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * viewParameters.ViewProjectionMatrix[4 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                }
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // set default resource dictionary
                rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary;

                // update layouting context.
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is rotated of 180degrees along Ox
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.LastRootMatrix = rootMatrix;

                // clear and set the Depth buffer as required
                if (uiComponent.IsFullScreen)
                {
                    context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref viewParameters.ViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                ReccursiveDrawWithClipping(context, rootElement);

                // end the image draw session
                batch.End();
            }

            // clear the list of compacted pointer events of time frame
            ClearPointerEvents();

            // revert the depth stencil buffer to the default value
            context.CommandList.SetRenderTargets(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
示例#21
0
            public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage)
            {
                // TODO: More general implementation (esp. if moved from this class to EditorGameComponentGizmoService)
                var renderMesh = renderObject as RenderMesh;

                if (renderMesh != null)
                {
                    // TODO: Avoid having to go through entity
                    return((renderMesh.Source as ModelComponent)?.Entity?.Tags.Get(EditorGameComponentGizmoService.SelectedKey) ?? false);
                }

                return(false);
            }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var batchContext = threadContext.Value;

            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            uint previousBatchState = uint.MaxValue;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            bool hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp  = renderSprite.SpriteComponent;
                var transfoComp = renderSprite.TransformComponent;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // TODO: this should probably be moved to Prepare()
                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Check if the current blend state has changed in any way, if not
                // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method
                var currentBatchState = isPicking ? 0U : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? 1U : 2U) : 3U;
                currentBatchState = (currentBatchState << 1) + (renderSprite.SpriteComponent.IgnoreDepth ? 1U : 0U);
                currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.SpriteComponent.Sampler);

                if (previousBatchState != currentBatchState)
                {
                    var blendState        = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                    var currentEffect     = isPicking ? batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem) : null; // TODO remove this code when material are available
                    var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                    var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                    if (renderSprite.SpriteComponent.Sampler != SpriteComponent.SpriteSampler.LinearClamp)
                    {
                        switch (renderSprite.SpriteComponent.Sampler)
                        {
                        case SpriteComponent.SpriteSampler.PointClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                            break;

                        case SpriteComponent.SpriteSampler.AnisotropicClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                            break;
                        }
                    }

                    if (hasBegin)
                    {
                        batchContext.SpriteBatch.End();
                    }

                    batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousBatchState = currentBatchState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = spriteComp.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId, 0.0f, 0.0f, 0.0f);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, spriteComp.Swizzle, projectedZ);
            }

            if (hasBegin)
            {
                batchContext.SpriteBatch.End();
            }
        }
示例#23
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            if (renderMeshesToGenerateAEN.Count > 0)
            {
                var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey);

                foreach (var renderMesh in renderMeshesToGenerateAEN)
                {
                    var tessellationState = tessellationStates[renderMesh.StaticObjectNode];
                    if (tessellationState.GeneratedIndicesAEN != null)
                        continue;

                    var tessellationMeshDraw = tessellationState.MeshDraw;

                    var indicesAEN = IndexExtensions.GenerateIndexBufferAEN(tessellationMeshDraw.IndexBuffer, tessellationMeshDraw.VertexBuffers[0], context.CommandList);
                    tessellationState.GeneratedIndicesAEN = Buffer.Index.New(Context.GraphicsDevice, indicesAEN);
                    tessellationMeshDraw.IndexBuffer = new IndexBufferBinding(tessellationState.GeneratedIndicesAEN, true, tessellationMeshDraw.IndexBuffer.Count*12/3);
                    tessellationMeshDraw.DrawCount = 12/3*tessellationMeshDraw.DrawCount;
                }

                renderMeshesToGenerateAEN.Clear();
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount];

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);

                // Get effect
                // TODO: Use real effect slot
                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.Effect == null)
                    continue;

                commandList.SetPipelineState(renderEffect.PipelineState);

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);
                renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSets.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                        descriptorSets[i] = resourceGroup.DescriptorSet;
                }

                commandList.SetDescriptorSets(0, descriptorSets);

                commandList.DrawQuad();
            }
        }
            public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage)
            {
                var entity = ((renderObject as RenderMesh)?.Source as ModelComponent)?.Entity;

                return(entity != null && selectedEntities.Contains(entity));
            }
示例#26
0
        private void initUIElementStates(RenderDrawContext context, RenderView renderView,
                                         RenderViewStage renderViewStage, ref UIElementState[] uiElementStates,
                                         int index, int storeIndex, GameTime drawTime, List <PointerEvent> events, ulong posecount)
        {
            var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
            var renderNode          = GetRenderNode(renderNodeReference);
            var renderElement       = (RenderUIElement)renderNode.RenderObject;

            var uiElementState = new UIElementState(renderElement);

            uiElementStates[storeIndex] = uiElementState;

            var renderObject = uiElementState.RenderObject;
            var rootElement  = renderObject.Page?.RootElement;

            if (rootElement != null)
            {
                UIBatch batch = getFreeBatch(context);

                var virtualResolution    = renderObject.Resolution;
                var updatableRootElement = (IUIElementUpdate)rootElement;

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = uiElementState.WorldViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                }

                var viewportSize           = context.CommandList.Viewport.Size;
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // Set default services
                rootElement.UIElementServices = new UIElementServices {
                    Services = RenderSystem.Services
                };

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is translated by a half resolution compared to its quad, which is centered around the origin
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.RenderObject.LastRootMatrix = rootMatrix;
                // set default resource dictionary

                // update layouting context.
                var layoutingContext = batch.layoutingContext as LayoutingContext;
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                if (renderObject.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(context.CommandList.RenderTargets[0].Width, context.CommandList.RenderTargets[0].Height);

                    // update the virtual resolution of the renderer
                    switch (renderObject.ResolutionStretch)
                    {
                    case ResolutionStretch.FixedWidthAdaptableHeight:
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                        break;

                    case ResolutionStretch.FixedHeightAdaptableWidth:
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                        break;

                    case ResolutionStretch.AutoFit:
                        float aspect     = targetSize.X / targetSize.Y;
                        float virtAspect = virtualResolution.X / virtualResolution.Y;
                        if (aspect >= virtAspect)
                        {
                            goto case ResolutionStretch.FixedHeightAdaptableWidth;
                        }
                        goto case ResolutionStretch.FixedWidthAdaptableHeight;

                    case ResolutionStretch.AutoShrink:
                        if (targetSize.X < virtualResolution.X ||
                            targetSize.Y < virtualResolution.Y)
                        {
                            goto case ResolutionStretch.AutoFit;
                        }
                        else
                        {
                            virtualResolution.X = targetSize.X * targetSize.X / virtualResolution.X;
                            virtualResolution.Y = targetSize.Y * targetSize.Y / virtualResolution.Y;
                        }
                        break;
                    }

                    uiElementState.Update(renderObject, virtualResolution);
                }
                else
                {
                    CameraComponent cameraComponent = renderView.Camera as CameraComponent;
                    if (cameraComponent != null)
                    {
                        uiElementState.Update(renderObject, cameraComponent.VerticalFieldOfView,
                                              ref renderView.View, ref renderView.Projection);
                    }
                }

                if (renderObject.Source is UIComponent uic)
                {
                    uic.RenderedResolution = virtualResolution;
                    if (posecount == 0 || posecount != uic.VRPoseUpdate)
                    {
                        PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime, events);
                        uic.VRPoseUpdate = posecount;
                    }
                }

                ReturnBatch(batch);
            }
        }
示例#27
0
        private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var uiProcessor = SceneInstance.GetCurrent(context.RenderContext).GetProcessor <UIRenderProcessor>();

            if (uiProcessor == null)
            {
                return;
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // Prepare content required for Picking and MouseOver events
            var events = new List <PointerEvent>();

            PickingPrepare(events);

            ulong poseCount = VirtualReality.VRDeviceSystem.GetSystem?.Device?.PoseCount ?? 0;

            // build the list of the UI elements to render
            UIElementState[] uiElementStates = new UIElementState[endIndex - startIndex];
            if (uiElementStates.Length > 1 && GraphicsDevice.Platform == GraphicsPlatform.Vulkan)
            {
                Xenko.Core.Threading.Dispatcher.For(startIndex, endIndex, (index) =>
                {
                    initUIElementStates(context, renderView, renderViewStage, ref uiElementStates, index, index - startIndex, drawTime, events, poseCount);
                });
            }
            else
            {
                for (int i = startIndex; i < endIndex; i++)
                {
                    initUIElementStates(context, renderView, renderViewStage, ref uiElementStates, i, i - startIndex, drawTime, events, poseCount);
                }
            }

            events?.Clear();

            lock (drawLocker)
            {
                UIBatch batch = getFreeBatch(context);

                var renderingContext = batch.renderingContext as UIRenderingContext;

                // update the rendering context
                renderingContext.GraphicsContext = context.GraphicsContext;
                renderingContext.Time            = drawTime;

                DepthStencilStateDescription stencilState = uiSystem.KeepStencilValueState;

                // actually draw stuff
                for (int j = 0; j < uiElementStates.Length; j++)
                {
                    var uiElementState = uiElementStates[j];

                    renderingContext.RenderObject = uiElementState.RenderObject;
                    var rootElement = renderingContext.RenderObject.Page?.RootElement;
                    if (rootElement == null || rootElement.IsVisible == false)
                    {
                        continue;
                    }

                    // update the rendering context values specific to this element
                    renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix;

                    switch (renderingContext.RenderObject.depthMode)
                    {
                    case Sprites.RenderSprite.SpriteDepthMode.Ignore:
                        stencilState.DepthBufferWriteEnable = false;
                        stencilState.DepthBufferEnable      = false;
                        break;

                    case Sprites.RenderSprite.SpriteDepthMode.ReadOnly:
                        stencilState.DepthBufferWriteEnable = false;
                        stencilState.DepthBufferEnable      = true;
                        break;

                    default:
                        stencilState.DepthBufferWriteEnable = true;
                        stencilState.DepthBufferEnable      = true;
                        break;

                    case Sprites.RenderSprite.SpriteDepthMode.WriteOnly:
                        stencilState.DepthBufferWriteEnable = true;
                        stencilState.DepthBufferEnable      = true;
                        stencilState.DepthBufferFunction    = CompareFunction.Always;
                        break;
                    }

                    SamplerState samplerState;
                    switch (renderingContext.RenderObject.Sampler)
                    {
                    default:
                        samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                        break;

                    case UIElementSampler.PointClamp:
                        samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                        break;

                    case UIElementSampler.AnisotropicClamp:
                        samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                        break;
                    }

                    // start the image draw session
                    renderingContext.StencilTestReferenceValue = 0;
                    batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, samplerState, null, stencilState, renderingContext.StencilTestReferenceValue);

                    // Render the UI elements in the final render target
                    RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix, batch, ref stencilState, samplerState);

                    batch.End();
                }

                ReturnBatch(batch);
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var batchContext = threadContext.Value;

            Matrix viewInverse;
            Matrix.Invert(ref renderView.View, out viewInverse);

            uint previousBatchState = uint.MaxValue;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            bool hasBegin = false;
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp = renderSprite.SpriteComponent;
                var transfoComp = renderSprite.TransformComponent;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                    continue;

                // TODO: this should probably be moved to Prepare()
                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Check if the current blend state has changed in any way, if not
                // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method
                var currentBatchState = isPicking ? 0U : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? 1U : 2U) : 3U;
                currentBatchState = (currentBatchState << 1) + (renderSprite.SpriteComponent.IgnoreDepth ? 1U : 0U);
                currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.SpriteComponent.Sampler);

                if (previousBatchState != currentBatchState)
                {
                    var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                    var currentEffect = isPicking ? batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem) : null; // TODO remove this code when material are available
                    var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                    var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                    if (renderSprite.SpriteComponent.Sampler != SpriteComponent.SpriteSampler.LinearClamp)
                    {
                        switch (renderSprite.SpriteComponent.Sampler)
                        {
                            case SpriteComponent.SpriteSampler.PointClamp:
                                samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                                break;
                            case SpriteComponent.SpriteSampler.AnisotropicClamp:
                                samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                                break;
                        }
                    }

                    if (hasBegin)
                    {
                        batchContext.SpriteBatch.End();
                    }

                    batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousBatchState = currentBatchState;

                var sourceRegion = sprite.Region;
                var texture = sprite.Texture;
                var color = spriteComp.Color;                
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                    continue;

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ);
            }

            if (hasBegin)
            {
                batchContext.SpriteBatch.End();
            }
        }
示例#29
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            BlendStateDescription?       previousBlendState        = null;
            DepthStencilStateDescription?previousDepthStencilState = null;
            EffectInstance previousEffect = null;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            bool hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp        = renderSprite.SpriteComponent;
                var transfoComp       = renderSprite.TransformComponent;
                var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // TODO: this should probably be moved to Prepare()
                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Update the sprite batch
                var blendState    = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available
                if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                {
                    if (hasBegin)
                    {
                        sprite3DBatch.End();
                    }
                    sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousEffect            = currentEffect;
                previousBlendState        = blendState;
                previousDepthStencilState = depthStencilState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = spriteComp.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ);
            }

            if (hasBegin)
            {
                sprite3DBatch.End();
            }
        }
示例#30
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var isMultisample = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount != MultisampleCount.None;

            var batchContext = threadContext.Value;

            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            uint previousBatchState = uint.MaxValue;

            //TODO string comparison ...?
            var isPicking = RenderSystem.RenderStages[renderViewStage.Index].Name == "Picking";

            bool hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var sprite = renderSprite.Sprite;
                if (sprite == null)
                {
                    continue;
                }

                // TODO: this should probably be moved to Prepare()
                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderSprite.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                BlendModes     blendMode;
                EffectInstance currentEffect = null;
                if (isPicking)
                {
                    blendMode     = BlendModes.Default;
                    currentEffect = batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem);
                }
                else
                {
                    var spriteBlend = renderSprite.BlendMode;
                    if (spriteBlend == SpriteBlend.Auto)
                    {
                        spriteBlend = sprite.IsTransparent ? SpriteBlend.AlphaBlend : SpriteBlend.None;
                    }

                    if (spriteBlend == SpriteBlend.AlphaBlend)
                    {
                        blendMode = renderSprite.PremultipliedAlpha ? BlendModes.Alpha : BlendModes.NonPremultiplied;
                    }
                    else
                    {
                        blendMode = spriteBlendToBlendMode[spriteBlend];
                    }
                }

                // Check if the current blend state has changed in any way, if not
                // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method
                var currentBatchState = (uint)blendMode;
                currentBatchState = (currentBatchState << 1) + ((uint)renderSprite.DepthMode);
                currentBatchState = (currentBatchState << 1) + (renderSprite.IsAlphaCutoff ? 1U : 0U);
                currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.Sampler);

                if (previousBatchState != currentBatchState)
                {
                    var blendState = blendModeToDescription[blendMode];

                    if (renderSprite.IsAlphaCutoff)
                    {
                        currentEffect = batchContext.GetOrCreateAlphaCutoffSpriteEffect(RenderSystem.EffectSystem);
                    }

                    DepthStencilStateDescription depthStencilState;
                    switch (renderSprite.DepthMode)
                    {
                    case RenderSprite.SpriteDepthMode.Ignore:
                        depthStencilState = DepthStencilStates.None;
                        break;

                    case RenderSprite.SpriteDepthMode.ReadOnly:
                        depthStencilState = DepthStencilStates.DepthRead;
                        break;

                    default:
                        depthStencilState = DepthStencilStates.Default;
                        break;

                    case RenderSprite.SpriteDepthMode.WriteOnly:
                        depthStencilState = new DepthStencilStateDescription(false, true);
                        break;
                    }

                    var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                    if (renderSprite.Sampler != SpriteSampler.LinearClamp)
                    {
                        switch (renderSprite.Sampler)
                        {
                        case SpriteSampler.PointClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                            break;

                        case SpriteSampler.AnisotropicClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                            break;
                        }
                    }

                    if (hasBegin)
                    {
                        lock (batchEndLocker)
                        {
                            batchContext.SpriteBatch.End();
                        }
                    }

                    var rasterizerState = RasterizerStates.CullNone;
                    if (isMultisample)
                    {
                        rasterizerState.MultisampleCount         = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount;
                        rasterizerState.MultisampleAntiAliasLine = true;
                    }

                    batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, rasterizerState, currentEffect);
                    hasBegin = true;
                }
                previousBatchState = currentBatchState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = renderSprite.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(renderSprite.Source);
                    color = new Color4(compId, 0.0f, 0.0f, 0.0f);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = renderSprite.WorldMatrix;
                if (renderSprite.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    var worldMatrixRow1 = worldMatrix.Row1;
                    var worldMatrixRow2 = worldMatrix.Row2;

                    // remove scale of the camera
                    worldMatrixRow1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrixRow2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrixRow1 *= ((Vector3)renderSprite.WorldMatrix.Row1).Length();
                    worldMatrixRow2 *= ((Vector3)renderSprite.WorldMatrix.Row2).Length();

                    worldMatrix.Row1 = worldMatrixRow1;
                    worldMatrix.Row2 = worldMatrixRow2;

                    // set the position
                    worldMatrix.TranslationVector = renderSprite.WorldMatrix.TranslationVector;

                    // set the rotation
                    var localRotationZ = renderSprite.RotationEulerZ;
                    if (localRotationZ != 0)
                    {
                        worldMatrix = Matrix.RotationZ(localRotationZ) * worldMatrix;
                    }
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // adapt the source region to match what is expected at full resolution
                if (texture.ViewType == ViewType.Full && texture.ViewWidth != texture.FullQualitySize.Width)
                {
                    var fullQualitySize = texture.FullQualitySize;
                    var horizontalRatio = texture.ViewWidth / (float)fullQualitySize.Width;
                    var verticalRatio   = texture.ViewHeight / (float)fullQualitySize.Height;
                    sourceRegion.X      *= horizontalRatio;
                    sourceRegion.Width  *= horizontalRatio;
                    sourceRegion.Y      *= verticalRatio;
                    sourceRegion.Height *= verticalRatio;
                }

                // register resource usage.
                Context.StreamingManager?.StreamResources(texture);

                // draw the sprite
                batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, renderSprite.Swizzle, projectedZ);
            }

            if (hasBegin)
            {
                lock (batchEndLocker)
                {
                    batchContext.SpriteBatch.End();
                }
            }
        }
示例#31
0
文件: Groups.cs 项目: vvvv/VL.Stride
 void ILowLevelAPIRender.Draw(RenderContext renderContext, RenderDrawContext drawContext, RenderView renderView, RenderViewStage renderViewStage, CommandList commandList)
 {
     foreach (var upstreamLayer in FUpstreamLayers)
     {
         upstreamLayer?.Draw(renderContext, drawContext, renderView, renderViewStage, commandList);
     }
 }
        private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current);

            var uiProcessor = renderView.SceneInstance.GetProcessor<UIRenderProcessor>();
            if (uiProcessor == null)
                return;


            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);
                var renderElement = (RenderUIElement)renderNode.RenderObject;
 
                uiElementStates.Add(new UIElementState(renderElement));
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time = drawTime;
            renderingContext.RenderTarget = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0

            // Prepare content required for Picking and MouseOver events
            PickingPrepare();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;
            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.RenderObject.UIComponent.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // update view parameters and perform UI picking
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.RenderObject.UIComponent;
                var rootElement = uiComponent.Page?.RootElement;
                if (rootElement == null)
                    continue;
                
                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = uiComponent.Resolution;

                if (uiComponent.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);

                    // update the virtual resolution of the renderer
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;

                    uiElementState.Update(uiComponent.Entity, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current);
                    if (cameraComponent != null)
                        uiElementState.Update(uiComponent.Entity, cameraComponent);
                }

                // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element)
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime);
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.RenderObject.UIComponent;
                var rootElement = uiComponent.Page?.RootElement;
                if (rootElement == null)
                    continue;

                var updatableRootElement = (IUIElementUpdate)rootElement;
                var virtualResolution = uiComponent.Resolution;

                // update the rendering context values specific to this element
                renderingContext.Resolution = virtualResolution;
                renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix;
                renderingContext.DepthStencilBuffer = uiComponent.IsFullScreen ? scopedDepthBuffer : currentRenderFrame.DepthStencil;
                renderingContext.ShouldSnapText = uiComponent.SnapText;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin = uiElementState.WorldViewProjectionMatrix.Row4;
                var virtualWidth = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i] = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                }

                var viewportSize = context.CommandList.Viewport.Size;
                var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // Set default services
                rootElement.UIElementServices = new UIElementServices { Services = RenderSystem.Services };

                // set default resource dictionary
                rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary;

                // update layouting context.
                layoutingContext.VirtualResolution = virtualResolution;
                layoutingContext.RealResolution = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is translated by a half resolution compared to its quad, which is centered around the origin
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.RenderObject.LastRootMatrix = rootMatrix;

                // clear and set the Depth buffer as required
                if (uiComponent.IsFullScreen)
                {
                    context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix);

                // end the image draw session
                batch.End();
            }

            PickingClear();

            // revert the depth stencil buffer to the default value 
            context.CommandList.SetRenderTargets(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
示例#33
0
文件: Groups.cs 项目: vvvv/VL.Stride
 void ILowLevelAPIRender.Draw(RenderContext renderContext, RenderDrawContext drawContext, RenderView renderView, RenderViewStage renderViewStage, CommandList commandList)
 {
     FUpstreamLayer1?.Draw(renderContext, drawContext, renderView, renderViewStage, commandList);
     FUpstreamLayer2?.Draw(renderContext, drawContext, renderView, renderViewStage, commandList);
 }
示例#34
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            // Do not call into VL if not running
            var renderContext = context.RenderContext;
            var runtime       = this.runtime ?? (this.runtime = renderContext.Services.GetService <IVLRuntime>());

            if (runtime != null && !runtime.IsRunning)
            {
                return;
            }

            // Build the list of layers to render
            singleCallLayers.Clear();
            layers.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderLayer)renderNode.RenderObject;

                if (renderElement.Enabled)
                {
                    if (renderElement.SingleCallPerFrame)
                    {
                        singleCallLayers.Add(renderElement.Layer);
                    }
                    else
                    {
                        layers.Add(renderElement.Layer);
                    }
                }
            }

            // Call layers which want to get invoked only once per frame first
            var currentFrameNr = renderContext.Time.FrameCount;

            if (lastFrameNr != currentFrameNr)
            {
                lastFrameNr = currentFrameNr;
                foreach (var layer in singleCallLayers)
                {
                    try
                    {
                        layer?.Draw(Context, context, renderView, renderViewStage, context.CommandList);
                    }
                    catch (Exception e)
                    {
                        RuntimeGraph.ReportException(e);
                    }
                }
            }

            // Call layers which can get invoked twice per frame (for each eye)
            foreach (var layer in layers)
            {
                try
                {
                    layer?.Draw(Context, context, renderView, renderViewStage, context.CommandList);
                }
                catch (Exception e)
                {
                    RuntimeGraph.ReportException(e);
                }
            }
        }
示例#35
0
        /// <inheritdoc/>
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            // TODO: PerView data
            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount];

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;
                if (renderParticleEmitter.ParticleEmitter.VertexBuilder.ResourceContext == null)
                {
                    continue;
                }

                // Generate vertices
                // TODO: Just just unmap/barrier here
                renderParticleEmitter.ParticleEmitter.BuildVertexBuffer(context.CommandList, ref viewInverse);

                // Get effect
                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // TODO GRAPHICS REFACTOR: Extract data
                var particleSystemComponent = renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent;
                var particleSystem          = particleSystemComponent.ParticleSystem;
                var vertexBuilder           = renderParticleEmitter.ParticleEmitter.VertexBuilder;

                // Bind VB
                var vertexBuffer = vertexBuilder.ResourceContext.VertexBuffer;
                var indexBuffer  = vertexBuilder.ResourceContext.IndexBuffer;
                commandList.SetVertexBuffer(0, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                commandList.SetIndexBuffer(indexBuffer.Buffer, indexBuffer.Offset, indexBuffer.Is32Bit);

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSets.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSets[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSets);

                commandList.DrawIndexed(vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, vertexBuilder.ResourceContext.IndexBufferPosition);
            }
        }
示例#36
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            BlendStateDescription?       previousBlendState        = null;
            DepthStencilStateDescription?previousDepthStencilState = null;
            EffectInstance previousEffect = null;

            //TODO string comparison ...?
            var isPicking = RenderSystem.RenderStages[renderViewStage.Index].Name == "Picking";

            var hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var spriteState = (RenderSpriteStudio)renderNode.RenderObject;

                var depthStencilState = DepthStencilStates.DepthRead;

                foreach (var node in spriteState.SortedNodes)
                {
                    if (node.Sprite?.Texture == null || node.Sprite.Region.Width <= 0 || node.Sprite.Region.Height <= 0f || node.Hide != 0)
                    {
                        continue;
                    }

                    // Update the sprite batch

                    BlendStateDescription spriteBlending;
                    switch (node.BaseNode.AlphaBlending)
                    {
                    case SpriteStudioBlending.Mix:
                        spriteBlending = BlendStates.AlphaBlend;
                        break;

                    case SpriteStudioBlending.Multiplication:
                        spriteBlending = MultBlendState;
                        break;

                    case SpriteStudioBlending.Addition:
                        spriteBlending = BlendStates.Additive;
                        break;

                    case SpriteStudioBlending.Subtraction:
                        spriteBlending = SubBlendState;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    // TODO: this should probably be moved to Prepare()
                    // Project the position
                    // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                    var worldPosition = new Vector4(spriteState.WorldMatrix.TranslationVector, 1.0f);

                    Vector4 projectedPosition;
                    Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                    var projectedZ = projectedPosition.Z / projectedPosition.W;

                    var blendState = isPicking ? BlendStates.Default : spriteBlending;
                    // TODO: the current impementation to determine if the sprite is selected does not work. This should be fixed later at some point
                    //var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : ShadowObject.IsObjectSelected(spriteState.SpriteStudioComponent) ? GetOrCreateSelectedSpriteEffect() : null;
                    var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null;
                    // TODO remove this code when material are available
                    if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                    {
                        if (hasBegin)
                        {
                            sprite3DBatch.End();
                        }
                        sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect);
                        hasBegin = true;
                    }

                    previousEffect            = currentEffect;
                    previousBlendState        = blendState;
                    previousDepthStencilState = depthStencilState;

                    var sourceRegion = node.Sprite.Region;
                    var texture      = node.Sprite.Texture;

                    // skip the sprite if no texture is set.
                    if (texture == null)
                    {
                        continue;
                    }

                    var color4 = Color4.White;
                    if (isPicking)
                    {
                        // TODO move this code corresponding to picking out of the runtime code.
                        color4 = new Color4(RuntimeIdHelper.ToRuntimeId(spriteState.Source));
                    }
                    else
                    {
                        if (node.BlendFactor > 0.0f)
                        {
                            switch (node.BlendType) //todo this should be done in a shader
                            {
                            case SpriteStudioBlending.Mix:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            case SpriteStudioBlending.Multiplication:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            case SpriteStudioBlending.Addition:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            case SpriteStudioBlending.Subtraction:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        }
                        else
                        {
                            color4 *= node.FinalTransparency;
                        }
                    }

                    Matrix.Multiply(ref node.ModelTransform, ref spriteState.WorldMatrix, out var worldMatrix);

                    // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                    var normalizedCenter = new Vector2(node.Sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - node.Sprite.Center.Y / sourceRegion.Height);
                    if (node.Sprite.Orientation == ImageOrientation.Rotated90)
                    {
                        var oldCenterX = normalizedCenter.X;
                        normalizedCenter.X = -normalizedCenter.Y;
                        normalizedCenter.Y = oldCenterX;
                    }
                    // apply the offset due to the center of the sprite
                    var size         = node.Sprite.Size;
                    var centerOffset = Vector2.Modulate(normalizedCenter, size);
                    worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                    worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;

                    // draw the sprite
                    sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref size, ref color4, node.Sprite.Orientation, SwizzleMode.None, projectedZ);
                }
            }

            if (hasBegin)
            {
                sprite3DBatch.End();
            }
        }
示例#37
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            Matrix viewInverse;
            Matrix.Invert(ref renderView.View, out viewInverse);

            BlendStateDescription? previousBlendState = null;
            DepthStencilStateDescription? previousDepthStencilState = null;
            EffectInstance previousEffect = null;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            bool hasBegin = false;
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp = renderSprite.SpriteComponent;
                var transfoComp = renderSprite.TransformComponent;
                var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                    continue;

                // TODO: this should probably be moved to Prepare()
                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Update the sprite batch
                var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available
                if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                {
                    if (hasBegin)
                    {
                        sprite3DBatch.End();
                    }
                    sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousEffect = currentEffect;
                previousBlendState = blendState;
                previousDepthStencilState = depthStencilState;

                var sourceRegion = sprite.Region;
                var texture = sprite.Texture;
                var color = spriteComp.Color;                
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                    continue;

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ);
            }

            if(hasBegin) sprite3DBatch.End();
        }