Exemple #1
0
        private void expandBounds(Vector2 pos)
        {
            if (pos.X - PathWidth < minX)
            {
                minX = pos.X - PathWidth;
            }
            if (pos.Y - PathWidth < minY)
            {
                minY = pos.Y - PathWidth;
            }
            if (pos.X + PathWidth > maxX)
            {
                maxX = pos.X + PathWidth;
            }
            if (pos.Y + PathWidth > maxY)
            {
                maxY = pos.Y + PathWidth;
            }

            RectangleF b = bounds;

            if ((RelativeSizeAxes & Axes.X) == 0)
            {
                Width = b.Width;
            }
            if ((RelativeSizeAxes & Axes.Y) == 0)
            {
                Height = b.Height;
            }
        }
Exemple #2
0
            public void SetDragRectangle(RectangleF rectangle)
            {
                var topLeft     = Parent.ToLocalSpace(rectangle.TopLeft);
                var bottomRight = Parent.ToLocalSpace(rectangle.BottomRight);

                Position = topLeft;
                Size     = bottomRight - topLeft;
            }
Exemple #3
0
        public override void DrawQuad(Quad vertexQuad, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null, Vector2?blendRangeOverride = null)
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not draw a quad with a disposed texture.");
            }

            RectangleF texRect         = GetTextureRect(textureRect);
            Vector2    inflationAmount = inflationPercentage.HasValue ? new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height) : Vector2.Zero;
            RectangleF inflatedTexRect = texRect.Inflate(inflationAmount);
            Vector2    blendRange      = blendRangeOverride ?? inflationAmount;

            if (vertexAction == null)
            {
                if (quadBatch == null)
                {
                    quadBatch = new QuadBatch <TexturedVertex2D>(512, 128);
                }
                vertexAction = quadBatch.Add;
            }

            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.BottomLeft,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = blendRange,
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.BottomRight,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = blendRange,
                Colour          = drawColour.BottomRight.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.TopRight,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = blendRange,
                Colour          = drawColour.TopRight.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.TopLeft,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = blendRange,
                Colour          = drawColour.TopLeft.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexQuad.ConservativeArea);
        }
        private void drawFrameBufferToBackBuffer(FrameBuffer frameBuffer, RectangleF drawRectangle, ColourInfo colourInfo)
        {
            // The strange Y coordinate and Height are a result of OpenGL coordinate systems having Y grow upwards and not downwards.
            RectangleF textureRect = new RectangleF(0, frameBuffer.Texture.Height, frameBuffer.Texture.Width, -frameBuffer.Texture.Height);

            if (frameBuffer.Texture.Bind())
            {
                // Color was already applied by base.Draw(); no need to re-apply. Thus we use White here.
                frameBuffer.Texture.DrawQuad(drawRectangle, textureRect, colourInfo);
            }
        }
        /// <summary>
        /// Blits sprite to OpenGL display with specified parameters.
        /// </summary>
        public override void Draw(Quad vertexQuad, RectangleF?textureRect, Color4 drawColour, VertexBatch <TexturedVertex2d> spriteBatch = null)
        {
            Debug.Assert(!isDisposed);

            if (!Bind())
            {
                return;
            }

            RectangleF texRect = textureRect != null
                ? new RectangleF(textureRect.Value.X, textureRect.Value.Y, textureRect.Value.Width, textureRect.Value.Height)
                : new RectangleF(0, 0, Width, Height);

            texRect.X      /= width;
            texRect.Y      /= height;
            texRect.Width  /= width;
            texRect.Height /= height;

            if (spriteBatch == null)
            {
                if (TextureGLSingle.spriteBatch == null)
                {
                    TextureGLSingle.spriteBatch = new QuadBatch <TexturedVertex2d>(1, 100);
                }
                spriteBatch = TextureGLSingle.spriteBatch;
            }

            spriteBatch.Add(new TexturedVertex2d
            {
                Position        = vertexQuad.BottomLeft,
                TexturePosition = new Vector2(texRect.Left, texRect.Bottom),
                Colour          = drawColour
            });
            spriteBatch.Add(new TexturedVertex2d
            {
                Position        = vertexQuad.BottomRight,
                TexturePosition = new Vector2(texRect.Right, texRect.Bottom),
                Colour          = drawColour
            });
            spriteBatch.Add(new TexturedVertex2d
            {
                Position        = vertexQuad.TopRight,
                TexturePosition = new Vector2(texRect.Right, texRect.Top),
                Colour          = drawColour
            });
            spriteBatch.Add(new TexturedVertex2d
            {
                Position        = vertexQuad.TopLeft,
                TexturePosition = new Vector2(texRect.Left, texRect.Top),
                Colour          = drawColour
            });
        }
Exemple #6
0
        /// <summary>
        /// Crop the texture.
        /// </summary>
        /// <param name="cropRectangle">The rectangle the cropped texture should reference.</param>
        /// <param name="relativeSizeAxes">Which axes have a relative size in [0,1] in relation to the texture size.</param>
        /// <param name="wrapModeS">The texture wrap mode in horizontal direction.</param>
        /// <param name="wrapModeT">The texture wrap mode in vertical direction.</param>
        /// <returns>The cropped texture.</returns>
        public Texture Crop(RectangleF cropRectangle, Axes relativeSizeAxes = Axes.None, WrapMode wrapModeS = WrapMode.None, WrapMode wrapModeT = WrapMode.None)
        {
            if (relativeSizeAxes != Axes.None)
            {
                Vector2 scale = new Vector2(
                    relativeSizeAxes.HasFlag(Axes.X) ? Width : 1,
                    relativeSizeAxes.HasFlag(Axes.Y) ? Height : 1
                    );
                cropRectangle *= scale;
            }

            return(new Texture(new TextureGLSub(cropRectangle, TextureGL, wrapModeS, wrapModeT)));
        }
Exemple #7
0
        public override RectangleF GetTextureRect(RectangleF?textureRect)
        {
            RectangleF texRect = textureRect != null
                ? new RectangleF(textureRect.Value.X, textureRect.Value.Y, textureRect.Value.Width, textureRect.Value.Height)
                : new RectangleF(0, 0, Width, Height);

            texRect.X      /= width;
            texRect.Y      /= height;
            texRect.Width  /= width;
            texRect.Height /= height;

            return(texRect);
        }
Exemple #8
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;
            // 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.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, 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();
        }
Exemple #9
0
        protected virtual RectangleF textureBounds(RectangleF?textureRect = null)
        {
            RectangleF texRect = textureRect ?? new RectangleF(0, 0, DisplayWidth, DisplayHeight);

            if (DpiScale != 1)
            {
                texRect.Width  *= DpiScale;
                texRect.Height *= DpiScale;
                texRect.X      *= DpiScale;
                texRect.Y      *= DpiScale;
            }

            return(texRect);
        }
Exemple #10
0
        public void Draw(Quad vertexQuad, Color4 colour, RectangleF?textureRect = null, VertexBatch <TexturedVertex2d> spriteBatch = null)
        {
            RectangleF texRect = textureRect ?? new RectangleF(0, 0, DisplayWidth, DisplayHeight);

            if (DpiScale != 1)
            {
                texRect.Width  *= DpiScale;
                texRect.Height *= DpiScale;
                texRect.X      *= DpiScale;
                texRect.Y      *= DpiScale;
            }

            TextureGL?.Draw(vertexQuad, texRect, colour, spriteBatch);
        }
Exemple #11
0
        /// <summary>
        /// Blits sprite to OpenGL display with specified parameters.
        /// </summary>
        public override void Draw(Quad vertexQuad, RectangleF?textureRect, Color4 drawColour, VertexBatch <TexturedVertex2D> spriteBatch = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!isDisposed);

            RectangleF texRect = GetTextureRect(textureRect);

            if (inflationPercentage.HasValue)
            {
                texRect = texRect.Inflate(new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height));
            }

            if (spriteBatch == null)
            {
                if (TextureGLSingle.spriteBatch == null)
                {
                    TextureGLSingle.spriteBatch = new QuadBatch <TexturedVertex2D>(512, 128);
                }
                spriteBatch = TextureGLSingle.spriteBatch;
            }

            Color4 linearColour = drawColour.toLinear();

            spriteBatch.Add(new TexturedVertex2D
            {
                Position        = vertexQuad.BottomLeft,
                TexturePosition = new Vector2(texRect.Left, texRect.Bottom),
                Colour          = linearColour
            });
            spriteBatch.Add(new TexturedVertex2D
            {
                Position        = vertexQuad.BottomRight,
                TexturePosition = new Vector2(texRect.Right, texRect.Bottom),
                Colour          = linearColour
            });
            spriteBatch.Add(new TexturedVertex2D
            {
                Position        = vertexQuad.TopRight,
                TexturePosition = new Vector2(texRect.Right, texRect.Top),
                Colour          = linearColour
            });
            spriteBatch.Add(new TexturedVertex2D
            {
                Position        = vertexQuad.TopLeft,
                TexturePosition = new Vector2(texRect.Left, texRect.Top),
                Colour          = linearColour
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexQuad.ConservativeArea);
        }
Exemple #12
0
        private RectangleF boundsInParent(RectangleF?textureRect)
        {
            RectangleF actualBounds = bounds;

            if (textureRect.HasValue)
            {
                RectangleF localBounds = textureRect.Value;
                actualBounds.X     += localBounds.X;
                actualBounds.Y     += localBounds.Y;
                actualBounds.Width  = Math.Min(localBounds.Width, bounds.Width);
                actualBounds.Height = Math.Min(localBounds.Height, bounds.Height);
            }

            return(actualBounds);
        }
Exemple #13
0
        /// <summary>
        /// Blits sprite to OpenGL display with specified parameters.
        /// </summary>
        public override void Draw(Quad vertexQuad, RectangleF?textureRect, Color4 drawColour, VertexBatch <TexturedVertex2d> spriteBatch = null)
        {
            RectangleF actualBounds = bounds;

            if (textureRect.HasValue)
            {
                RectangleF localBounds = textureRect.Value;
                actualBounds.X     += localBounds.X;
                actualBounds.Y     += localBounds.Y;
                actualBounds.Width  = Math.Min(localBounds.Width, bounds.Width);
                actualBounds.Height = Math.Min(localBounds.Height, bounds.Height);
            }

            parent.Draw(vertexQuad, actualBounds, drawColour, spriteBatch);
        }
Exemple #14
0
        /// <summary>
        /// Applies a new orthographic projection rectangle.
        /// </summary>
        /// <param name="ortho">The orthographic projection rectangle.</param>
        public static void PushOrtho(RectangleF ortho)
        {
            FlushCurrentBatch();

            ortho_stack.Push(ortho);
            if (Ortho == ortho)
            {
                return;
            }
            Ortho = ortho;

            ProjectionMatrix = Matrix4.CreateOrthographicOffCenter(Ortho.Left, Ortho.Right, Ortho.Bottom, Ortho.Top, -1, 1);
            Shader.SetGlobalProperty(@"g_ProjMatrix", ProjectionMatrix);

            UpdateScissorToCurrentViewportAndOrtho();
        }
Exemple #15
0
        public override void DrawQuad(Quad vertexQuad, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!isDisposed);

            RectangleF texRect = GetTextureRect(textureRect);

            if (inflationPercentage.HasValue)
            {
                texRect = texRect.Inflate(new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height));
            }

            if (vertexAction == null)
            {
                if (quadBatch == null)
                {
                    quadBatch = new QuadBatch <TexturedVertex2D>(512, 128);
                }
                vertexAction = quadBatch.Add;
            }

            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.BottomLeft,
                TexturePosition = new Vector2(texRect.Left, texRect.Bottom),
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.BottomRight,
                TexturePosition = new Vector2(texRect.Right, texRect.Bottom),
                Colour          = drawColour.BottomRight.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.TopRight,
                TexturePosition = new Vector2(texRect.Right, texRect.Top),
                Colour          = drawColour.TopRight.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexQuad.TopLeft,
                TexturePosition = new Vector2(texRect.Left, texRect.Top),
                Colour          = drawColour.TopLeft.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexQuad.ConservativeArea);
        }
        public override void DrawTriangle(Triangle vertexTriangle, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!isDisposed);

            RectangleF texRect = GetTextureRect(textureRect);

            if (inflationPercentage.HasValue)
            {
                texRect = texRect.Inflate(new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height));
            }

            if (vertexAction == null)
            {
                if (triangleBatch == null)
                {
                    // We multiply the size param by 3 such that the amount of vertices is a multiple of the amount of vertices
                    // per primitive (triangles in this case). Otherwise overflowing the batch will result in wrong
                    // grouping of vertices into primitives.
                    triangleBatch = new LinearBatch <TexturedVertex2D>(512 * 3, 128, PrimitiveType.Triangles);
                }
                vertexAction = triangleBatch.Add;
            }

            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2((texRect.Left + texRect.Right) / 2, texRect.Top),
                Colour          = drawColour.TopLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P1,
                TexturePosition = new Vector2(texRect.Left, texRect.Bottom),
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P2,
                TexturePosition = new Vector2(texRect.Right, texRect.Bottom),
                Colour          = drawColour.BottomRight.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexTriangle.ConservativeArea);
        }
Exemple #17
0
        public InfoOverlay()
        {
            RelativeSizeAxes = Axes.Both;

            Children = new[]
            {
                layout = new FlashyBox(d => d.ToScreenSpace(d.LayoutRectangle))
                {
                    Colour = Color4.Green,
                    Alpha  = 0.5f,
                },
                shape = new FlashyBox(d => d.ScreenSpaceDrawQuad)
                {
                    Colour = Color4.Blue,
                    Alpha  = 0.5f,
                },
                childShape = new FlashyBox(delegate(Drawable d)
                {
                    var c = d as CompositeDrawable;
                    if (c == null)
                    {
                        return(d.ScreenSpaceDrawQuad);
                    }

                    RectangleF rect = new RectangleF(c.ChildOffset, c.ChildSize);
                    return(d.ToScreenSpace(rect));
                })
                {
                    Colour = Color4.Red,
                    Alpha  = 0.5f,
                },
                // We're adding this guy twice to get a border in a somewhat hacky way.
                new FlashyBox(d => quadAroundPosition(d.ToScreenSpace(d.OriginPosition), 5))
                {
                    Colour = Color4.Blue,
                },
                new FlashyBox(d => quadAroundPosition(d.ToScreenSpace(d.OriginPosition), 3))
                {
                    Colour = Color4.Yellow,
                },
            };
        }
Exemple #18
0
        /// <summary>
        /// Applies the last orthographic projection rectangle.
        /// </summary>
        public static void PopOrtho()
        {
            Trace.Assert(ortho_stack.Count > 1);

            FlushCurrentBatch();

            ortho_stack.Pop();
            RectangleF actualRect = ortho_stack.Peek();

            if (Ortho == actualRect)
            {
                return;
            }
            Ortho = actualRect;

            ProjectionMatrix = Matrix4.CreateOrthographicOffCenter(Ortho.Left, Ortho.Right, Ortho.Bottom, Ortho.Top, -1, 1);
            Shader.SetGlobalProperty(@"g_ProjMatrix", ProjectionMatrix);

            UpdateScissorToCurrentViewportAndOrtho();
        }
Exemple #19
0
        public static void UpdateScissorToCurrentViewportAndOrtho()
        {
            RectangleF viewportRect = Viewport;
            Vector2    offset       = viewportRect.TopLeft - Ortho.TopLeft;

            RectangleI currentScissorRect = scissor_rect_stack.Peek();

            RectangleI scissorRect = new RectangleI(
                currentScissorRect.X + (int)Math.Floor(offset.X),
                Viewport.Height - currentScissorRect.Bottom - (int)Math.Ceiling(offset.Y),
                currentScissorRect.Width,
                currentScissorRect.Height);

            if (!Precision.AlmostEquals(offset, Vector2.Zero))
            {
                ++scissorRect.Width;
                ++scissorRect.Height;
            }

            GL.Scissor(scissorRect.X, scissorRect.Y, scissorRect.Width, scissorRect.Height);
        }
Exemple #20
0
        protected override void UpdateVertices()
        {
            Vertices.Clear();
            Normals.Clear();

            float cornerRadius = (drawable as CompositeDrawable)?.CornerRadius ?? 0;

            // Sides
            RectangleF rect = drawable.DrawRectangle;

            Vector2[] corners           = { rect.TopLeft, rect.TopRight, rect.BottomRight, rect.BottomLeft };
            const int amount_side_steps = 2;

            for (int i = 0; i < 4; ++i)
            {
                Vector2 a      = corners[i];
                Vector2 b      = corners[(i + 1) % 4];
                Vector2 diff   = b - a;
                float   length = diff.Length;
                Vector2 dir    = diff / length;

                float usableLength = Math.Max(length - 2 * cornerRadius, 0);

                Vector2 normal = (b - a).PerpendicularRight.Normalized();
                for (int j = 0; j < amount_side_steps; ++j)
                {
                    Vertices.Add(a + dir * (cornerRadius + j * usableLength / (amount_side_steps - 1)));
                    Normals.Add(normal);
                }
            }

            const int amount_corner_steps = 10;

            if (cornerRadius > 0)
            {
                // Rounded corners
                Vector2[] offsets =
                {
                    new Vector2(cornerRadius,  cornerRadius),
                    new Vector2(-cornerRadius, cornerRadius),
                    new Vector2(-cornerRadius, -cornerRadius),
                    new Vector2(cornerRadius,  -cornerRadius),
                };

                for (int i = 0; i < 4; ++i)
                {
                    Vector2 a = corners[i];

                    float startTheta = (i - 1) * (float)Math.PI / 2;

                    for (int j = 0; j < amount_corner_steps; ++j)
                    {
                        float theta = startTheta + j * (float)Math.PI / (2 * (amount_corner_steps - 1));

                        Vector2 normal = new Vector2((float)Math.Sin(theta), (float)Math.Cos(theta));
                        Vertices.Add(a + offsets[i] + normal * cornerRadius);
                        Normals.Add(normal);
                    }
                }
            }

            // To simulation space
            Matrix3 mat     = drawable.DrawInfo.Matrix * ScreenToSimulationSpace;
            Matrix3 normMat = mat.Inverted();

            normMat.Transpose();

            // Remove translation
            normMat.M31 = normMat.M32 = normMat.M13 = normMat.M23 = 0;
            Vector2 translation = Vector2.Zero * normMat;

            for (int i = 0; i < Vertices.Count; ++i)
            {
                Vertices[i] *= mat;
                Normals[i]   = (Normals[i] * normMat - translation).Normalized();
            }
        }
        public override void Draw(Action <TexturedVertex2D> vertexAction)
        {
            currentFrameBufferIndex = originalIndex;

            Vector2 frameBufferSize = new Vector2((float)Math.Ceiling(ScreenSpaceDrawRectangle.Width), (float)Math.Ceiling(ScreenSpaceDrawRectangle.Height));

            if (UpdateVersion > DrawVersion.Value || frameBufferSize != FrameBuffers[0].Size)
            {
                DrawVersion.Value = UpdateVersion;

                using (establishFrameBufferViewport(frameBufferSize))
                {
                    drawChildren(vertexAction, frameBufferSize);

                    // Blur post-processing in case a blur radius is defined.
                    if (BlurRadius.X > 0 || BlurRadius.Y > 0)
                    {
                        GL.Disable(EnableCap.ScissorTest);

                        if (BlurRadius.X > 0)
                        {
                            drawBlurredFrameBuffer(BlurRadius.X, BlurSigma.X, BlurRotation);
                        }
                        if (BlurRadius.Y > 0)
                        {
                            drawBlurredFrameBuffer(BlurRadius.Y, BlurSigma.Y, BlurRotation + 90);
                        }

                        GL.Enable(EnableCap.ScissorTest);
                    }
                }

                finalizeFrameBuffer();
            }

            RectangleF drawRectangle = FilteringMode == All.Nearest
                ? new RectangleF(ScreenSpaceDrawRectangle.X, ScreenSpaceDrawRectangle.Y, frameBufferSize.X, frameBufferSize.Y)
                : ScreenSpaceDrawRectangle;

            Shader.Bind();

            if (DrawOriginal && EffectPlacement == EffectPlacement.InFront)
            {
                GLWrapper.SetBlend(DrawInfo.Blending);
                drawFrameBufferToBackBuffer(FrameBuffers[originalIndex], drawRectangle, DrawInfo.Colour);
            }

            // Blit the final framebuffer to screen.
            GLWrapper.SetBlend(new BlendingInfo(EffectBlending));

            ColourInfo effectColour = DrawInfo.Colour;

            effectColour.ApplyChild(EffectColour);
            drawFrameBufferToBackBuffer(FrameBuffers[0], drawRectangle, effectColour);

            if (DrawOriginal && EffectPlacement == EffectPlacement.Behind)
            {
                GLWrapper.SetBlend(DrawInfo.Blending);
                drawFrameBufferToBackBuffer(FrameBuffers[originalIndex], drawRectangle, DrawInfo.Colour);
            }

            Shader.Unbind();
        }
            public override void Draw(Action <TexturedVertex2D> vertexAction)
            {
                base.Draw(vertexAction);

                if (texture?.Available != true || points == null || points.Count == 0)
                {
                    return;
                }

                shader.Bind();
                texture.TextureGL.Bind();

                Vector2 localInflationAmount = new Vector2(0, 1) * DrawInfo.MatrixInverse.ExtractScale().Xy;

                // We're dealing with a _large_ number of points, so we need to optimise the quadToDraw * drawInfo.Matrix multiplications below
                // for points that are going to be masked out anyway. This allows for higher resolution graphs at larger scales with virtually no performance loss.
                // Since the points are generated in the local coordinate space, we need to convert the screen space masking quad coordinates into the local coordinate space
                RectangleF localMaskingRectangle = (Quad.FromRectangle(GLWrapper.CurrentMaskingInfo.ScreenSpaceAABB) * DrawInfo.MatrixInverse).AABBFloat;

                float separation = drawSize.X / (points.Count - 1);

                for (int i = 0; i < points.Count - 1; i++)
                {
                    float leftX  = i * separation;
                    float rightX = (i + 1) * separation;

                    if (rightX < localMaskingRectangle.Left)
                    {
                        continue;
                    }

                    if (leftX > localMaskingRectangle.Right)
                    {
                        break; // X is always increasing
                    }
                    Color4 frequencyColour = baseColour;

                    // colouring is applied in the order of interest to a viewer.
                    frequencyColour = Interpolation.ValueAt(points[i].MidIntensity / midMax, frequencyColour, midColour, 0, 1);
                    // high end (cymbal) can help find beat, so give it priority over mids.
                    frequencyColour = Interpolation.ValueAt(points[i].HighIntensity / highMax, frequencyColour, highColour, 0, 1);
                    // low end (bass drum) is generally the best visual aid for beat matching, so give it priority over high/mid.
                    frequencyColour = Interpolation.ValueAt(points[i].LowIntensity / lowMax, frequencyColour, lowColour, 0, 1);

                    ColourInfo finalColour = DrawColourInfo.Colour;
                    finalColour.ApplyChild(frequencyColour);

                    Quad quadToDraw;

                    switch (channels)
                    {
                    default:
                    case 2:
                    {
                        float height = drawSize.Y / 2;
                        quadToDraw = new Quad(
                            new Vector2(leftX, height - points[i].Amplitude[0] * height),
                            new Vector2(rightX, height - points[i + 1].Amplitude[0] * height),
                            new Vector2(leftX, height + points[i].Amplitude[1] * height),
                            new Vector2(rightX, height + points[i + 1].Amplitude[1] * height)
                            );
                        break;
                    }

                    case 1:
                    {
                        quadToDraw = new Quad(
                            new Vector2(leftX, drawSize.Y - points[i].Amplitude[0] * drawSize.Y),
                            new Vector2(rightX, drawSize.Y - points[i + 1].Amplitude[0] * drawSize.Y),
                            new Vector2(leftX, drawSize.Y),
                            new Vector2(rightX, drawSize.Y)
                            );
                        break;
                    }
                    }

                    quadToDraw *= DrawInfo.Matrix;
                    DrawQuad(texture, quadToDraw, finalColour, null, vertexBatch.AddAction, Vector2.Divide(localInflationAmount, quadToDraw.Size));
                }

                shader.Unbind();
            }
Exemple #23
0
            public override void Draw(Action <TexturedVertex2D> vertexAction)
            {
                base.Draw(vertexAction);

                if (Points == null || Points.Count == 0)
                {
                    return;
                }

                Shader.Bind();
                Texture.TextureGL.Bind();

                Vector2 localInflationAmount = new Vector2(0, 1) * DrawInfo.MatrixInverse.ExtractScale().Xy;

                // We're dealing with a _large_ number of points, so we need to optimise the quadToDraw * drawInfo.Matrix multiplications below
                // for points that are going to be masked out anyway. This allows for higher resolution graphs at larger scales with virtually no performance loss.
                // Since the points are generated in the local coordinate space, we need to convert the screen space masking quad coordinates into the local coordinate space
                RectangleF localMaskingRectangle = (Quad.FromRectangle(GLWrapper.CurrentMaskingInfo.ScreenSpaceAABB) * DrawInfo.MatrixInverse).AABBFloat;

                float separation = DrawSize.X / (Points.Count - 1);

                for (int i = 0; i < Points.Count - 1; i++)
                {
                    float leftX  = i * separation;
                    float rightX = (i + 1) * separation;

                    if (rightX < localMaskingRectangle.Left)
                    {
                        continue;
                    }
                    if (leftX > localMaskingRectangle.Right)
                    {
                        break; // X is always increasing
                    }
                    ColourInfo colour = DrawInfo.Colour;
                    Quad       quadToDraw;

                    switch (Channels)
                    {
                    default:
                    case 2:
                    {
                        float height = DrawSize.Y / 2;
                        quadToDraw = new Quad(
                            new Vector2(leftX, height - Points[i].Amplitude[0] * height),
                            new Vector2(rightX, height - Points[i + 1].Amplitude[0] * height),
                            new Vector2(leftX, height + Points[i].Amplitude[1] * height),
                            new Vector2(rightX, height + Points[i + 1].Amplitude[1] * height)
                            );
                    }
                    break;

                    case 1:
                    {
                        quadToDraw = new Quad(
                            new Vector2(leftX, DrawSize.Y - Points[i].Amplitude[0] * DrawSize.Y),
                            new Vector2(rightX, DrawSize.Y - Points[i + 1].Amplitude[0] * DrawSize.Y),
                            new Vector2(leftX, DrawSize.Y),
                            new Vector2(rightX, DrawSize.Y)
                            );
                        break;
                    }
                    }

                    quadToDraw *= DrawInfo.Matrix;
                    Texture.DrawQuad(quadToDraw, colour, null, Shared.VertexBatch.Add, Vector2.Divide(localInflationAmount, quadToDraw.Size));
                }

                Shader.Unbind();
            }
Exemple #24
0
        public override void DrawTriangle(Triangle vertexTriangle, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!IsDisposed);

            RectangleF texRect         = GetTextureRect(textureRect);
            Vector2    inflationAmount = inflationPercentage.HasValue ? new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height) : Vector2.Zero;
            RectangleF inflatedTexRect = texRect.Inflate(inflationAmount);

            if (vertexAction == null)
            {
                if (triangleBatch == null)
                {
                    // We multiply the size param by 3 such that the amount of vertices is a multiple of the amount of vertices
                    // per primitive (triangles in this case). Otherwise overflowing the batch will result in wrong
                    // grouping of vertices into primitives.
                    triangleBatch = new LinearBatch <TexturedVertex2D>(512 * 3, 128, PrimitiveType.Triangles);
                }
                vertexAction = triangleBatch.Add;
            }

            // We split the triangle into two, such that we can obtain smooth edges with our
            // texture coordinate trick. We might want to revert this to drawing a single
            // triangle in case we ever need proper texturing, or if the additional vertices
            // end up becoming an overhead (unlikely).
            SRGBColour topColour    = (drawColour.TopLeft + drawColour.TopRight) / 2;
            SRGBColour bottomColour = (drawColour.BottomLeft + drawColour.BottomRight) / 2;

            // Left triangle half
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = topColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P1,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = (vertexTriangle.P1 + vertexTriangle.P2) / 2,
                TexturePosition = new Vector2((inflatedTexRect.Left + inflatedTexRect.Right) / 2, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = bottomColour.Linear,
            });

            // Right triangle half
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = topColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = (vertexTriangle.P1 + vertexTriangle.P2) / 2,
                TexturePosition = new Vector2((inflatedTexRect.Left + inflatedTexRect.Right) / 2, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = bottomColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P2,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = drawColour.BottomRight.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexTriangle.ConservativeArea);
        }
        public override void DrawTriangle(Triangle vertexTriangle, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not draw a triangle with a disposed texture.");
            }

            RectangleF texRect         = GetTextureRect(textureRect);
            Vector2    inflationAmount = inflationPercentage.HasValue ? new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height) : Vector2.Zero;
            RectangleF inflatedTexRect = texRect.Inflate(inflationAmount);

            if (vertexAction == null)
            {
                vertexAction = default_triangle_action;
            }

            // We split the triangle into two, such that we can obtain smooth edges with our
            // texture coordinate trick. We might want to revert this to drawing a single
            // triangle in case we ever need proper texturing, or if the additional vertices
            // end up becoming an overhead (unlikely).
            SRGBColour topColour    = (drawColour.TopLeft + drawColour.TopRight) / 2;
            SRGBColour bottomColour = (drawColour.BottomLeft + drawColour.BottomRight) / 2;

            // Left triangle half
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = topColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P1,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = (vertexTriangle.P1 + vertexTriangle.P2) / 2,
                TexturePosition = new Vector2((inflatedTexRect.Left + inflatedTexRect.Right) / 2, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = bottomColour.Linear,
            });

            // Right triangle half
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = topColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = (vertexTriangle.P1 + vertexTriangle.P2) / 2,
                TexturePosition = new Vector2((inflatedTexRect.Left + inflatedTexRect.Right) / 2, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = bottomColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P2,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = drawColour.BottomRight.Linear,
            });

            FrameStatistics.Add(StatisticsCounterType.Pixels, (long)vertexTriangle.ConservativeArea);
        }