예제 #1
0
        public override void Draw(Action<TexturedVertex2D> vertexAction)
        {
            updateVertexBatch();

            // Prefer to use own vertex batch instead of the parent-owned one.
            if (Shared.VertexBatch != null)
                vertexAction = Shared.VertexBatch.AddAction;

            base.Draw(vertexAction);

            drawEdgeEffect();
            if (MaskingInfo != null)
            {
                MaskingInfo info = MaskingInfo.Value;
                if (info.BorderThickness > 0)
                    info.BorderColour *= DrawColourInfo.Colour.AverageColour;

                GLWrapper.PushMaskingInfo(info);
            }

            if (Children != null)
                for (int i = 0; i < Children.Count; i++)
                    Children[i].Draw(vertexAction);

            if (MaskingInfo != null)
                GLWrapper.PopMaskingInfo();
        }
예제 #2
0
        public override void Draw(IVertexBatch vertexBatch)
        {
            updateVertexBatch();

            // Prefer to use own vertex batch instead of the parent-owned one.
            if (Shared.VertexBatch != null)
            {
                vertexBatch = Shared.VertexBatch;
            }

            base.Draw(vertexBatch);

            drawEdgeEffect();
            if (MaskingInfo != null)
            {
                GLWrapper.PushMaskingInfo(MaskingInfo.Value);
            }

            if (Children != null)
            {
                foreach (DrawNode child in Children)
                {
                    child.Draw(vertexBatch);
                }
            }

            if (MaskingInfo != null)
            {
                GLWrapper.PopMaskingInfo();
            }
        }
        private InvokeOnDisposal establishFrameBufferViewport(Vector2 roundedSize)
        {
            // Disable masking for generating the frame buffer since masking will be re-applied
            // when actually drawing later on anyways. This allows more information to be captured
            // in the frame buffer and helps with cached buffers being re-used.
            Rectangle screenSpaceMaskingRect = new Rectangle((int)Math.Floor(ScreenSpaceDrawRectangle.X), (int)Math.Floor(ScreenSpaceDrawRectangle.Y), (int)roundedSize.X + 1, (int)roundedSize.Y + 1);

            GLWrapper.PushMaskingInfo(new MaskingInfo
            {
                ScreenSpaceAABB = screenSpaceMaskingRect,
                MaskingRect     = ScreenSpaceDrawRectangle,
                ToMaskingSpace  = Matrix3.Identity,
                BlendRange      = 1,
                AlphaExponent   = 1,
            }, true);

            // Match viewport to FrameBuffer such that we don't draw unnecessary pixels.
            GLWrapper.PushViewport(new Rectangle(0, 0, (int)roundedSize.X, (int)roundedSize.Y));

            return(new InvokeOnDisposal(delegate
            {
                GLWrapper.PopViewport();
                GLWrapper.PopMaskingInfo();
            }));
        }
예제 #4
0
            private void drawEdgeEffect()
            {
                if (maskingInfo == null || edgeEffect.Type == EdgeEffectType.None || edgeEffect.Radius <= 0.0f || edgeEffect.Colour.Linear.A <= 0)
                {
                    return;
                }

                RectangleF effectRect = maskingInfo.Value.MaskingRect.Inflate(edgeEffect.Radius).Offset(edgeEffect.Offset);

                if (!screenSpaceMaskingQuad.HasValue)
                {
                    screenSpaceMaskingQuad = Quad.FromRectangle(effectRect) * DrawInfo.Matrix;
                }

                MaskingInfo edgeEffectMaskingInfo = maskingInfo.Value;

                edgeEffectMaskingInfo.MaskingRect     = effectRect;
                edgeEffectMaskingInfo.ScreenSpaceAABB = screenSpaceMaskingQuad.Value.AABB;
                edgeEffectMaskingInfo.CornerRadius    = maskingInfo.Value.CornerRadius + edgeEffect.Radius + edgeEffect.Roundness;
                edgeEffectMaskingInfo.BorderThickness = 0;
                // HACK HACK HACK. We abuse blend range to give us the linear alpha gradient of
                // the edge effect along its radius using the same rounded-corners shader.
                edgeEffectMaskingInfo.BlendRange         = edgeEffect.Radius;
                edgeEffectMaskingInfo.AlphaExponent      = 2;
                edgeEffectMaskingInfo.EdgeOffset         = edgeEffect.Offset;
                edgeEffectMaskingInfo.Hollow             = edgeEffect.Hollow;
                edgeEffectMaskingInfo.HollowCornerRadius = maskingInfo.Value.CornerRadius + edgeEffect.Radius;

                GLWrapper.PushMaskingInfo(edgeEffectMaskingInfo);

                GLWrapper.SetBlend(new BlendingInfo(edgeEffect.Type == EdgeEffectType.Glow ? BlendingMode.Additive : BlendingMode.Mixture));

                Shader.Bind();

                ColourInfo colour = ColourInfo.SingleColour(edgeEffect.Colour);

                colour.TopLeft.MultiplyAlpha(DrawColourInfo.Colour.TopLeft.Linear.A);
                colour.BottomLeft.MultiplyAlpha(DrawColourInfo.Colour.BottomLeft.Linear.A);
                colour.TopRight.MultiplyAlpha(DrawColourInfo.Colour.TopRight.Linear.A);
                colour.BottomRight.MultiplyAlpha(DrawColourInfo.Colour.BottomRight.Linear.A);

                DrawQuad(
                    Texture.WhitePixel,
                    screenSpaceMaskingQuad.Value,
                    colour, null, null, null,
                    // HACK HACK HACK. We re-use the unused vertex blend range to store the original
                    // masking blend range when rendering edge effects. This is needed for smooth inner edges
                    // with a hollow edge effect.
                    new Vector2(maskingInfo.Value.BlendRange));

                Shader.Unbind();

                GLWrapper.PopMaskingInfo();
            }
        public override void Draw(Action <TexturedVertex2D> vertexAction)
        {
            if (CustomVertexAction == null)
            {
                updateVertexBatch();

                // Prefer to use own vertex batch instead of the parent-owned one.
                if (Shared.VertexBatch != null)
                {
                    vertexAction = Shared.VertexBatch.Add;
                }
            }
            else
            {
                vertexAction = CustomVertexAction;
            }

            base.Draw(vertexAction);

            drawEdgeEffect();
            if (MaskingInfo != null)
            {
                MaskingInfo info = MaskingInfo.Value;
                if (info.BorderThickness > 0)
                {
                    info.BorderColour *= DrawInfo.Colour.AverageColour;
                }

                GLWrapper.PushMaskingInfo(info);
            }

            if (Children != null)
            {
                foreach (DrawNode child in Children)
                {
                    child.Draw(vertexAction);
                }
            }

            if (MaskingInfo != null)
            {
                GLWrapper.PopMaskingInfo();
            }
        }
예제 #6
0
        private void drawEdgeEffect()
        {
            if (MaskingInfo == null || EdgeEffect.Type == EdgeEffectType.None || EdgeEffect.Radius <= 0.0f || EdgeEffect.Colour.Linear.A <= 0.0f)
            {
                return;
            }

            RectangleF effectRect = MaskingInfo.Value.MaskingRect.Inflate(EdgeEffect.Radius).Offset(EdgeEffect.Offset);

            if (!ScreenSpaceMaskingQuad.HasValue)
            {
                ScreenSpaceMaskingQuad = Quad.FromRectangle(effectRect) * DrawInfo.Matrix;
            }

            MaskingInfo edgeEffectMaskingInfo = MaskingInfo.Value;

            edgeEffectMaskingInfo.MaskingRect     = effectRect;
            edgeEffectMaskingInfo.ScreenSpaceAABB = ScreenSpaceMaskingQuad.Value.AABB;
            edgeEffectMaskingInfo.CornerRadius   += EdgeEffect.Radius + EdgeEffect.Roundness;
            edgeEffectMaskingInfo.BorderThickness = 0;
            edgeEffectMaskingInfo.BlendRange      = EdgeEffect.Radius;
            edgeEffectMaskingInfo.AlphaExponent   = 2;
            edgeEffectMaskingInfo.Hollow          = EdgeEffect.Hollow;

            GLWrapper.PushMaskingInfo(edgeEffectMaskingInfo);

            GLWrapper.SetBlend(new BlendingInfo(EdgeEffect.Type == EdgeEffectType.Glow ? BlendingMode.Additive : BlendingMode.Mixture));

            Shader.Bind();

            ColourInfo colour = ColourInfo.SingleColour(EdgeEffect.Colour);

            colour.TopLeft.MultiplyAlpha(DrawInfo.Colour.TopLeft.Linear.A);
            colour.BottomLeft.MultiplyAlpha(DrawInfo.Colour.BottomLeft.Linear.A);
            colour.TopRight.MultiplyAlpha(DrawInfo.Colour.TopRight.Linear.A);
            colour.BottomRight.MultiplyAlpha(DrawInfo.Colour.BottomRight.Linear.A);

            Texture.WhitePixel.DrawQuad(ScreenSpaceMaskingQuad.Value, colour);

            Shader.Unbind();

            GLWrapper.PopMaskingInfo();
        }
예제 #7
0
            protected virtual void DrawChildrenOpaqueInteriors(DepthValue depthValue, Action <TexturedVertex2D> vertexAction)
            {
                bool canIncrement = depthValue.CanIncrement;

                // Assume that if we can't increment the depth value, no child can, thus nothing will be drawn.
                if (canIncrement)
                {
                    updateTriangleBatch();

                    // Prefer to use own vertex batch instead of the parent-owned one.
                    if (triangleBatch != null)
                    {
                        vertexAction = triangleBatch.AddAction;
                    }

                    if (maskingInfo != null)
                    {
                        GLWrapper.PushMaskingInfo(maskingInfo.Value);
                    }
                }

                // We still need to invoke this method recursively for all children so their depth value is updated
                if (Children != null)
                {
                    for (int i = Children.Count - 1; i >= 0; i--)
                    {
                        Children[i].DrawOpaqueInteriorSubTree(depthValue, vertexAction);
                    }
                }

                // Assume that if we can't increment the depth value, no child can, thus nothing will be drawn.
                if (canIncrement)
                {
                    if (maskingInfo != null)
                    {
                        GLWrapper.PopMaskingInfo();
                    }
                }
            }
            public override void Draw(Action <TexturedVertex2D> vertexAction)
            {
                updateQuadBatch();

                // Prefer to use own vertex batch instead of the parent-owned one.
                if (quadBatch != null)
                {
                    vertexAction = quadBatch.AddAction;
                }

                base.Draw(vertexAction);

                drawEdgeEffect();

                if (maskingInfo != null)
                {
                    MaskingInfo info = maskingInfo.Value;
                    if (info.BorderThickness > 0)
                    {
                        info.BorderColour = ColourInfo.Multiply(info.BorderColour, DrawColourInfo.Colour);
                    }

                    GLWrapper.PushMaskingInfo(info);
                }

                if (Children != null)
                {
                    for (int i = 0; i < Children.Count; i++)
                    {
                        Children[i].Draw(vertexAction);
                    }
                }

                if (maskingInfo != null)
                {
                    GLWrapper.PopMaskingInfo();
                }
            }
예제 #9
0
        private void drawEdgeEffect()
        {
            if (MaskingInfo == null || EdgeEffect.Type == EdgeEffectType.None || EdgeEffect.Radius <= 0.0f || EdgeEffect.Colour.A <= 0.0f)
            {
                return;
            }

            RectangleF effectRect = MaskingInfo.Value.MaskingRect.Inflate(EdgeEffect.Radius).Offset(EdgeEffect.Offset);

            if (!ScreenSpaceMaskingQuad.HasValue)
            {
                ScreenSpaceMaskingQuad = Quad.FromRectangle(effectRect) * DrawInfo.Matrix;
            }

            MaskingInfo edgeEffectMaskingInfo = MaskingInfo.Value;

            edgeEffectMaskingInfo.MaskingRect     = effectRect;
            edgeEffectMaskingInfo.ScreenSpaceAABB = ScreenSpaceMaskingQuad.Value.AABB;
            edgeEffectMaskingInfo.CornerRadius   += EdgeEffect.Radius + EdgeEffect.Roundness;
            edgeEffectMaskingInfo.BorderThickness = 0;
            edgeEffectMaskingInfo.BlendRange      = EdgeEffect.Radius;

            GLWrapper.PushMaskingInfo(edgeEffectMaskingInfo);

            GLWrapper.SetBlend(new BlendingInfo(EdgeEffect.Type == EdgeEffectType.Glow ? BlendingMode.Additive : BlendingMode.Mixture));

            Shader.Bind();

            Color4 colour = EdgeEffect.Colour;

            colour.A *= DrawInfo.Colour.A;

            Texture.WhitePixel.Draw(ScreenSpaceMaskingQuad.Value, colour);

            Shader.Unbind();

            GLWrapper.PopMaskingInfo();
        }
        private IDisposable establishFrameBufferViewport()
        {
            // Disable masking for generating the frame buffer since masking will be re-applied
            // when actually drawing later on anyways. This allows more information to be captured
            // in the frame buffer and helps with cached buffers being re-used.
            RectangleI screenSpaceMaskingRect = new RectangleI((int)Math.Floor(screenSpaceDrawRectangle.X), (int)Math.Floor(screenSpaceDrawRectangle.Y), (int)frameBufferSize.X + 1, (int)frameBufferSize.Y + 1);

            GLWrapper.PushMaskingInfo(new MaskingInfo
            {
                ScreenSpaceAABB = screenSpaceMaskingRect,
                MaskingRect     = screenSpaceDrawRectangle,
                ToMaskingSpace  = Matrix3.Identity,
                BlendRange      = 1,
                AlphaExponent   = 1,
            }, true);

            // Match viewport to FrameBuffer such that we don't draw unnecessary pixels.
            GLWrapper.PushViewport(new RectangleI(0, 0, (int)frameBufferSize.X, (int)frameBufferSize.Y));
            GLWrapper.PushScissor(new RectangleI(0, 0, (int)frameBufferSize.X, (int)frameBufferSize.Y));
            GLWrapper.PushScissorOffset(screenSpaceMaskingRect.Location);

            return(new ValueInvokeOnDisposal <BufferedDrawNode>(this, d => d.returnViewport()));
        }