diff --git a/osu.Framework/Graphics/Audio/WaveformGraph.cs b/osu.Framework/Graphics/Audio/WaveformGraph.cs index 83b8cc79a3..bbd819f2e8 100644 --- a/osu.Framework/Graphics/Audio/WaveformGraph.cs +++ b/osu.Framework/Graphics/Audio/WaveformGraph.cs @@ -336,7 +336,7 @@ public override void Draw(IRenderer renderer) // 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(renderer.CurrentMaskingInfo.ScreenSpaceScissorArea) * DrawInfo.MatrixInverse).AABBFloat; + RectangleF localMaskingRectangle = (Quad.FromRectangle(renderer.CurrentMaskingInfo.ScreenSpaceAABB) * DrawInfo.MatrixInverse).AABBFloat; float separation = drawSize.X / (points.Count - 1); diff --git a/osu.Framework/Graphics/BufferedDrawNode.cs b/osu.Framework/Graphics/BufferedDrawNode.cs index 692494536c..dada195bcd 100644 --- a/osu.Framework/Graphics/BufferedDrawNode.cs +++ b/osu.Framework/Graphics/BufferedDrawNode.cs @@ -35,7 +35,6 @@ public class BufferedDrawNode : TexturedShaderDrawNode protected RectangleF DrawRectangle { get; private set; } private Color4 backgroundColour; - private RectangleF localDrawRectangle; private RectangleF screenSpaceDrawRectangle; private Vector2 frameBufferScale; private Vector2 frameBufferSize; @@ -53,7 +52,6 @@ public override void ApplyState() base.ApplyState(); backgroundColour = Source.BackgroundColour; - localDrawRectangle = Source.DrawRectangle; screenSpaceDrawRectangle = Source.ScreenSpaceDrawQuad.AABBFloat; DrawColourInfo = Source.FrameBufferDrawColour ?? new DrawColourInfo(Color4.White, base.DrawColourInfo.Blending); frameBufferScale = Source.FrameBufferScale; @@ -157,12 +155,17 @@ protected IDisposable BindFrameBuffer(IFrameBuffer frameBuffer) private IDisposable establishFrameBufferViewport(IRenderer renderer) { + // 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); + renderer.PushMaskingInfo(new MaskingInfo { - ScreenSpaceScissorArea = screenSpaceDrawRectangle, - MaskingArea = localDrawRectangle, - ToMaskingSpace = DrawInfo.MatrixInverse, - ToScissorSpace = Matrix3.Identity, + ScreenSpaceAABB = screenSpaceMaskingRect, + MaskingRect = screenSpaceDrawRectangle, + ToMaskingSpace = Matrix3.Identity, BlendRange = 1, AlphaExponent = 1, }, true); @@ -170,12 +173,14 @@ private IDisposable establishFrameBufferViewport(IRenderer renderer) // Match viewport to FrameBuffer such that we don't draw unnecessary pixels. renderer.PushViewport(new RectangleI(0, 0, (int)frameBufferSize.X, (int)frameBufferSize.Y)); renderer.PushScissor(new RectangleI(0, 0, (int)frameBufferSize.X, (int)frameBufferSize.Y)); + renderer.PushScissorOffset(screenSpaceMaskingRect.Location); return new ValueInvokeOnDisposal<(BufferedDrawNode node, IRenderer renderer)>((this, renderer), tup => tup.node.returnViewport(tup.renderer)); } private void returnViewport(IRenderer renderer) { + renderer.PopScissorOffset(); renderer.PopViewport(); renderer.PopScissor(); renderer.PopMaskingInfo(); diff --git a/osu.Framework/Graphics/Containers/BufferedContainer.cs b/osu.Framework/Graphics/Containers/BufferedContainer.cs index 4f5a11caa2..5a83d0b87a 100644 --- a/osu.Framework/Graphics/Containers/BufferedContainer.cs +++ b/osu.Framework/Graphics/Containers/BufferedContainer.cs @@ -266,7 +266,7 @@ public BufferedContainer(RenderBufferFormat[] formats = null, bool pixelSnapping private void load(ShaderManager shaders) { TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE); - blurShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2_NO_MASKING, FragmentShaderDescriptor.BLUR); + blurShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.BLUR); } protected override DrawNode CreateDrawNode() => new BufferedContainerDrawNode(this, sharedData); diff --git a/osu.Framework/Graphics/Containers/CompositeDrawable_DrawNode.cs b/osu.Framework/Graphics/Containers/CompositeDrawable_DrawNode.cs index eb52db9d96..05d0707856 100644 --- a/osu.Framework/Graphics/Containers/CompositeDrawable_DrawNode.cs +++ b/osu.Framework/Graphics/Containers/CompositeDrawable_DrawNode.cs @@ -43,7 +43,7 @@ protected class CompositeDrawableDrawNode : DrawNode, ICompositeDrawNode private MaskingInfo? maskingInfo; /// - /// The screen-space version of . + /// The screen-space version of . /// Used as cache of screen-space masking quads computed in previous frames. /// Assign null to reset. /// @@ -92,11 +92,10 @@ public override void ApplyState() ? null : new MaskingInfo { - ScreenSpaceScissorArea = Source.ScreenSpaceDrawQuad.AABBFloat, - MaskingArea = Source.DrawRectangle.Normalize(), + ScreenSpaceAABB = Source.ScreenSpaceDrawQuad.AABB, + MaskingRect = Source.DrawRectangle.Normalize(), ConservativeScreenSpaceQuad = Quad.FromRectangle(shrunkDrawRectangle) * DrawInfo.Matrix, ToMaskingSpace = DrawInfo.MatrixInverse, - ToScissorSpace = Matrix3.Identity, CornerRadius = Source.effectiveCornerRadius, CornerExponent = Source.CornerExponent, BorderThickness = Source.BorderThickness, @@ -122,13 +121,13 @@ private void drawEdgeEffect(IRenderer renderer) if (maskingInfo == null || edgeEffect.Type == EdgeEffectType.None || edgeEffect.Radius <= 0.0f || edgeEffect.Colour.Alpha <= 0) return; - RectangleF effectRect = maskingInfo.Value.MaskingArea.Inflate(edgeEffect.Radius).Offset(edgeEffect.Offset); + RectangleF effectRect = maskingInfo.Value.MaskingRect.Inflate(edgeEffect.Radius).Offset(edgeEffect.Offset); screenSpaceMaskingQuad ??= Quad.FromRectangle(effectRect) * DrawInfo.Matrix; MaskingInfo edgeEffectMaskingInfo = maskingInfo.Value; - edgeEffectMaskingInfo.MaskingArea = effectRect; - edgeEffectMaskingInfo.ScreenSpaceScissorArea = screenSpaceMaskingQuad.Value.AABBFloat; + 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 diff --git a/osu.Framework/Graphics/Lines/Path_DrawNode.cs b/osu.Framework/Graphics/Lines/Path_DrawNode.cs index 1432f13ad3..8ab0a46981 100644 --- a/osu.Framework/Graphics/Lines/Path_DrawNode.cs +++ b/osu.Framework/Graphics/Lines/Path_DrawNode.cs @@ -72,7 +72,7 @@ public override void Draw(IRenderer renderer) texture.Bind(); - updateVertexBuffer(renderer); + updateVertexBuffer(); pathShader.Unbind(); @@ -88,7 +88,7 @@ private Color4 colourAt(Vector2 localPos) => DrawColourInfo.Colour.TryExtractSin ? colour.SRGB : DrawColourInfo.Colour.Interpolate(relativePosition(localPos)).SRGB; - private void addSegmentQuads(IRenderer renderer, Line segment, Line segmentLeft, Line segmentRight, RectangleF texRect) + private void addSegmentQuads(Line segment, Line segmentLeft, Line segmentRight, RectangleF texRect) { Debug.Assert(triangleBatch != null); @@ -101,19 +101,19 @@ private void addSegmentQuads(IRenderer renderer, Line segment, Line segmentLeft, // Each of the quads (mentioned above) is rendered as 2 triangles: // Outer quad, triangle 1 - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(segmentRight.EndPoint.X, segmentRight.EndPoint.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), Colour = colourAt(segmentRight.EndPoint) }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(segmentRight.StartPoint.X, segmentRight.StartPoint.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), Colour = colourAt(segmentRight.StartPoint) }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = firstMiddlePoint, TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), @@ -121,19 +121,19 @@ private void addSegmentQuads(IRenderer renderer, Line segment, Line segmentLeft, }); // Outer quad, triangle 2 - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = firstMiddlePoint, TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), Colour = firstMiddleColour }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = secondMiddlePoint, TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), Colour = secondMiddleColour }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(segmentRight.EndPoint.X, segmentRight.EndPoint.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), @@ -141,19 +141,19 @@ private void addSegmentQuads(IRenderer renderer, Line segment, Line segmentLeft, }); // Inner quad, triangle 1 - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = firstMiddlePoint, TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), Colour = firstMiddleColour }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = secondMiddlePoint, TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), Colour = secondMiddleColour }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(segmentLeft.EndPoint.X, segmentLeft.EndPoint.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), @@ -161,19 +161,19 @@ private void addSegmentQuads(IRenderer renderer, Line segment, Line segmentLeft, }); // Inner quad, triangle 2 - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(segmentLeft.EndPoint.X, segmentLeft.EndPoint.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), Colour = colourAt(segmentLeft.EndPoint) }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(segmentLeft.StartPoint.X, segmentLeft.StartPoint.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), Colour = colourAt(segmentLeft.StartPoint) }); - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = firstMiddlePoint, TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), @@ -181,7 +181,7 @@ private void addSegmentQuads(IRenderer renderer, Line segment, Line segmentLeft, }); } - private void addSegmentCaps(IRenderer renderer, float thetaDiff, Line segmentLeft, Line segmentRight, Line prevSegmentLeft, Line prevSegmentRight, RectangleF texRect) + private void addSegmentCaps(float thetaDiff, Line segmentLeft, Line segmentRight, Line prevSegmentLeft, Line prevSegmentRight, RectangleF texRect) { Debug.Assert(triangleBatch != null); @@ -210,7 +210,7 @@ private void addSegmentCaps(IRenderer renderer, float thetaDiff, Line segmentLef for (int i = 1; i <= stepCount; i++) { // Center point - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(origin.X, origin.Y, 1), TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y), @@ -218,7 +218,7 @@ private void addSegmentCaps(IRenderer renderer, float thetaDiff, Line segmentLef }); // First outer point - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(current.X, current.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), @@ -229,7 +229,7 @@ private void addSegmentCaps(IRenderer renderer, float thetaDiff, Line segmentLef currentColour = colourAt(current); // Second outer point - triangleBatch.Add(new TexturedVertex3D(renderer) + triangleBatch.Add(new TexturedVertex3D { Position = new Vector3(current.X, current.Y, 0), TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y), @@ -238,7 +238,7 @@ private void addSegmentCaps(IRenderer renderer, float thetaDiff, Line segmentLef } } - private void updateVertexBuffer(IRenderer renderer) + private void updateVertexBuffer() { // Explanation of the terms "left" and "right": // "Left" and "right" are used here in terms of a typical (Cartesian) coordinate system. @@ -277,7 +277,7 @@ private void updateVertexBuffer(IRenderer renderer) Line currSegmentLeft = new Line(currSegment.StartPoint + ortho * radius, currSegment.EndPoint + ortho * radius); Line currSegmentRight = new Line(currSegment.StartPoint - ortho * radius, currSegment.EndPoint - ortho * radius); - addSegmentQuads(renderer, currSegment, currSegmentLeft, currSegmentRight, texRect); + addSegmentQuads(currSegment, currSegmentLeft, currSegmentRight, texRect); if (prevSegmentLeft is Line psLeft && prevSegmentRight is Line psRight) { @@ -285,7 +285,7 @@ private void updateVertexBuffer(IRenderer renderer) // Connection/filler caps between segment quads float thetaDiff = currSegment.Theta - segments[i - 1].Theta; - addSegmentCaps(renderer, thetaDiff, currSegmentLeft, currSegmentRight, psLeft, psRight, texRect); + addSegmentCaps(thetaDiff, currSegmentLeft, currSegmentRight, psLeft, psRight, texRect); } // Explanation of semi-circle caps: @@ -300,7 +300,7 @@ private void updateVertexBuffer(IRenderer renderer) Line flippedLeft = new Line(currSegmentRight.EndPoint, currSegmentRight.StartPoint); Line flippedRight = new Line(currSegmentLeft.EndPoint, currSegmentLeft.StartPoint); - addSegmentCaps(renderer, MathF.PI, currSegmentLeft, currSegmentRight, flippedLeft, flippedRight, texRect); + addSegmentCaps(MathF.PI, currSegmentLeft, currSegmentRight, flippedLeft, flippedRight, texRect); } if (i == segments.Count - 1) @@ -309,7 +309,7 @@ private void updateVertexBuffer(IRenderer renderer) Line flippedLeft = new Line(currSegmentRight.EndPoint, currSegmentRight.StartPoint); Line flippedRight = new Line(currSegmentLeft.EndPoint, currSegmentLeft.StartPoint); - addSegmentCaps(renderer, MathF.PI, flippedLeft, flippedRight, currSegmentLeft, currSegmentRight, texRect); + addSegmentCaps(MathF.PI, flippedLeft, flippedRight, currSegmentLeft, currSegmentRight, texRect); } prevSegmentLeft = currSegmentLeft; diff --git a/osu.Framework/Graphics/OpenGL/GLRenderer.cs b/osu.Framework/Graphics/OpenGL/GLRenderer.cs index 75b6c7e2d6..f864712d88 100644 --- a/osu.Framework/Graphics/OpenGL/GLRenderer.cs +++ b/osu.Framework/Graphics/OpenGL/GLRenderer.cs @@ -283,7 +283,6 @@ public void DrawVertices(PrimitiveType type, int vertexStart, int verticesCount) var glShader = (GLShader)Shader!; glShader.BindUniformBlock("g_GlobalUniforms", GlobalUniformBuffer!); - glShader.BindUniformBlock("g_MaskingBuffer", ShaderMaskingStack!.CurrentBuffer); int currentUniformBinding = 0; int currentStorageBinding = 0; diff --git a/osu.Framework/Graphics/Rendering/Dummy/DummyRenderer.cs b/osu.Framework/Graphics/Rendering/Dummy/DummyRenderer.cs index a752d0e630..f94221b240 100644 --- a/osu.Framework/Graphics/Rendering/Dummy/DummyRenderer.cs +++ b/osu.Framework/Graphics/Rendering/Dummy/DummyRenderer.cs @@ -29,7 +29,6 @@ public sealed class DummyRenderer : IRenderer public bool IsUvOriginTopLeft => true; public bool IsClipSpaceYInverted => true; public ref readonly MaskingInfo CurrentMaskingInfo => ref maskingInfo; - public int CurrentMaskingIndex => 0; private readonly MaskingInfo maskingInfo; public RectangleI Viewport => RectangleI.Empty; diff --git a/osu.Framework/Graphics/Rendering/FlushBatchSource.cs b/osu.Framework/Graphics/Rendering/FlushBatchSource.cs index de2c95ef0a..13e557e544 100644 --- a/osu.Framework/Graphics/Rendering/FlushBatchSource.cs +++ b/osu.Framework/Graphics/Rendering/FlushBatchSource.cs @@ -12,6 +12,7 @@ public enum FlushBatchSource SetBlendMask, SetDepthInfo, SetFrameBuffer, + SetMasking, SetProjection, SetScissor, SetShader, diff --git a/osu.Framework/Graphics/Rendering/GlobalUniformData.cs b/osu.Framework/Graphics/Rendering/GlobalUniformData.cs index 7f26e04b6a..51ba8b7e13 100644 --- a/osu.Framework/Graphics/Rendering/GlobalUniformData.cs +++ b/osu.Framework/Graphics/Rendering/GlobalUniformData.cs @@ -16,9 +16,23 @@ public record struct GlobalUniformData public UniformBool IsUvOriginTopLeft; public UniformMatrix4 ProjMatrix; + public UniformMatrix3 ToMaskingSpace; + public UniformBool IsMasking; + public UniformFloat CornerRadius; + public UniformFloat CornerExponent; + private readonly UniformPadding4 pad2; + public UniformVector4 MaskingRect; + public UniformFloat BorderThickness; + private readonly UniformPadding12 pad3; + + public UniformMatrix4 BorderColour; + public UniformFloat MaskingBlendRange; + public UniformFloat AlphaExponent; + public UniformVector2 EdgeOffset; + public UniformBool DiscardInner; + public UniformFloat InnerCornerRadius; public UniformInt WrapModeS; public UniformInt WrapModeT; - private readonly UniformPadding8 pad1; } } diff --git a/osu.Framework/Graphics/Rendering/IRenderer.cs b/osu.Framework/Graphics/Rendering/IRenderer.cs index 6e0003c7c1..c97e4914ca 100644 --- a/osu.Framework/Graphics/Rendering/IRenderer.cs +++ b/osu.Framework/Graphics/Rendering/IRenderer.cs @@ -98,8 +98,6 @@ public interface IRenderer /// ref readonly MaskingInfo CurrentMaskingInfo { get; } - int CurrentMaskingIndex { get; } - /// /// The current viewport. /// @@ -278,6 +276,17 @@ public interface IRenderer /// void PopScissor(); + /// + /// Applies a new scissor offset to the scissor rectangle. + /// + /// The scissor offset. + void PushScissorOffset(Vector2I offset); + + /// + /// Restores the last scissor offset. + /// + void PopScissorOffset(); + /// /// Applies a new projection matrix. /// diff --git a/osu.Framework/Graphics/Rendering/MaskingInfo.cs b/osu.Framework/Graphics/Rendering/MaskingInfo.cs index 1220d15bf2..8198d45b6a 100644 --- a/osu.Framework/Graphics/Rendering/MaskingInfo.cs +++ b/osu.Framework/Graphics/Rendering/MaskingInfo.cs @@ -10,34 +10,18 @@ namespace osu.Framework.Graphics.Rendering { public struct MaskingInfo : IEquatable { - /// - /// A rectangle that defines the scissor area in screen-space coordinates. - /// - public RectangleF ScreenSpaceScissorArea; - - /// - /// A rectangle that defines the masking area in the local-space (i.e. ) of the masking container. - /// - public RectangleF MaskingArea; + public RectangleI ScreenSpaceAABB; + public RectangleF MaskingRect; - /// - /// A quad representing the internal "safe" (without borders, corners, and AA smoothening) area of the masking container. - /// - /// - /// This is used to clip drawn polygons during the front-to-back pass such that only areas guaranteed to be visible are drawn. - /// public Quad ConservativeScreenSpaceQuad; /// - /// A matrix that converts from vertex coordinates to the space of . + /// This matrix transforms screen space coordinates to masking space (likely the parent + /// space of the container doing the masking). + /// It is used by a shader to determine which pixels to discard. /// public Matrix3 ToMaskingSpace; - /// - /// A matrix that converts from vertex coordinates to the space of . - /// - public Matrix3 ToScissorSpace; - public float CornerRadius; public float CornerExponent; @@ -55,11 +39,10 @@ public struct MaskingInfo : IEquatable public readonly bool Equals(MaskingInfo other) => this == other; public static bool operator ==(in MaskingInfo left, in MaskingInfo right) => - left.ScreenSpaceScissorArea == right.ScreenSpaceScissorArea && - left.MaskingArea == right.MaskingArea && + left.ScreenSpaceAABB == right.ScreenSpaceAABB && + left.MaskingRect == right.MaskingRect && left.ConservativeScreenSpaceQuad.Equals(right.ConservativeScreenSpaceQuad) && left.ToMaskingSpace == right.ToMaskingSpace && - left.ToScissorSpace == right.ToScissorSpace && left.CornerRadius == right.CornerRadius && left.CornerExponent == right.CornerExponent && left.BorderThickness == right.BorderThickness && diff --git a/osu.Framework/Graphics/Rendering/Renderer.cs b/osu.Framework/Graphics/Rendering/Renderer.cs index 3ad1d47cb7..6fbfaf88fd 100644 --- a/osu.Framework/Graphics/Rendering/Renderer.cs +++ b/osu.Framework/Graphics/Rendering/Renderer.cs @@ -59,7 +59,6 @@ protected internal Storage? CacheStorage public ulong FrameIndex { get; private set; } public ref readonly MaskingInfo CurrentMaskingInfo => ref currentMaskingInfo; - public int CurrentMaskingIndex => ShaderMaskingStack?.CurrentOffset ?? 0; public RectangleI Viewport { get; private set; } public RectangleI Scissor { get; private set; } @@ -131,8 +130,6 @@ protected internal Storage? CacheStorage private readonly LockedWeakList allTextures = new LockedWeakList(); protected IUniformBuffer? GlobalUniformBuffer { get; private set; } - protected ShaderStorageBufferObjectStack? ShaderMaskingStack { get; private set; } - private IVertexBatch? defaultQuadBatch; private IVertexBatch? currentActiveBatch; private MaskingInfo currentMaskingInfo; @@ -199,10 +196,6 @@ protected internal virtual void BeginFrame(Vector2 windowSize) IsUvOriginTopLeft = IsUvOriginTopLeft }; - // 60 elements keeps the total data length under 16KiB (16320). - ShaderMaskingStack ??= new ShaderStorageBufferObjectStack(this, 60, 8192); - ShaderMaskingStack.Clear(); - Debug.Assert(defaultQuadBatch != null); FrameIndex++; @@ -255,12 +248,12 @@ protected internal virtual void BeginFrame(Vector2 windowSize) PushScissorState(true); PushViewport(new RectangleI(0, 0, (int)windowSize.X, (int)windowSize.Y)); PushScissor(new RectangleI(0, 0, (int)windowSize.X, (int)windowSize.Y)); + PushScissorOffset(Vector2I.Zero); PushMaskingInfo(new MaskingInfo { - ScreenSpaceScissorArea = new RectangleI(0, 0, (int)windowSize.X, (int)windowSize.Y), - MaskingArea = new RectangleF(0, 0, windowSize.X, windowSize.Y), + ScreenSpaceAABB = new RectangleI(0, 0, (int)windowSize.X, (int)windowSize.Y), + MaskingRect = new RectangleF(0, 0, windowSize.X, windowSize.Y), ToMaskingSpace = Matrix3.Identity, - ToScissorSpace = Matrix3.Identity, BlendRange = 1, AlphaExponent = 1, CornerExponent = 2.5f, @@ -496,6 +489,12 @@ public void PushScissorState(bool enabled) setScissorState(enabled); } + public void PushScissorOffset(Vector2I offset) + { + scissorOffsetStack.Push(offset); + setScissorOffset(offset); + } + public void PopScissor() { Trace.Assert(scissorRectStack.Count > 1); @@ -512,6 +511,14 @@ public void PopScissorState() setScissorState(scissorStateStack.Peek()); } + public void PopScissorOffset() + { + Trace.Assert(scissorOffsetStack.Count > 1); + + scissorOffsetStack.Pop(); + setScissorOffset(scissorOffsetStack.Peek()); + } + private void setScissor(RectangleI scissor) { if (scissor.Width < 0) @@ -552,6 +559,15 @@ private void setScissorState(bool enabled) ScissorState = enabled; } + private void setScissorOffset(Vector2I offset) + { + if (ScissorOffset == offset) + return; + + FlushCurrentBatch(FlushBatchSource.SetScissor); + ScissorOffset = offset; + } + /// /// Updates the graphics device with a new scissor rectangle. /// @@ -616,74 +632,71 @@ private void setMaskingInfo(MaskingInfo maskingInfo, bool isPushing, bool overwr if (CurrentMaskingInfo == maskingInfo) return; + FlushCurrentBatch(FlushBatchSource.SetMasking); + + GlobalUniformBuffer!.Data = GlobalUniformBuffer.Data with + { + IsMasking = IsMaskingActive, + MaskingRect = new Vector4( + maskingInfo.MaskingRect.Left, + maskingInfo.MaskingRect.Top, + maskingInfo.MaskingRect.Right, + maskingInfo.MaskingRect.Bottom), + ToMaskingSpace = maskingInfo.ToMaskingSpace, + CornerRadius = maskingInfo.CornerRadius, + CornerExponent = maskingInfo.CornerExponent, + BorderThickness = maskingInfo.BorderThickness / maskingInfo.BlendRange, + BorderColour = maskingInfo.BorderThickness > 0 + ? new Matrix4( + // TopLeft + maskingInfo.BorderColour.TopLeft.SRGB.R, + maskingInfo.BorderColour.TopLeft.SRGB.G, + maskingInfo.BorderColour.TopLeft.SRGB.B, + maskingInfo.BorderColour.TopLeft.SRGB.A, + // BottomLeft + maskingInfo.BorderColour.BottomLeft.SRGB.R, + maskingInfo.BorderColour.BottomLeft.SRGB.G, + maskingInfo.BorderColour.BottomLeft.SRGB.B, + maskingInfo.BorderColour.BottomLeft.SRGB.A, + // TopRight + maskingInfo.BorderColour.TopRight.SRGB.R, + maskingInfo.BorderColour.TopRight.SRGB.G, + maskingInfo.BorderColour.TopRight.SRGB.B, + maskingInfo.BorderColour.TopRight.SRGB.A, + // BottomRight + maskingInfo.BorderColour.BottomRight.SRGB.R, + maskingInfo.BorderColour.BottomRight.SRGB.G, + maskingInfo.BorderColour.BottomRight.SRGB.B, + maskingInfo.BorderColour.BottomRight.SRGB.A) + : GlobalUniformBuffer.Data.BorderColour, + MaskingBlendRange = maskingInfo.BlendRange, + AlphaExponent = maskingInfo.AlphaExponent, + EdgeOffset = maskingInfo.EdgeOffset, + DiscardInner = maskingInfo.Hollow, + InnerCornerRadius = maskingInfo.Hollow + ? maskingInfo.HollowCornerRadius + : GlobalUniformBuffer.Data.InnerCornerRadius + }; + if (isPushing) { - RectangleF scissorRect = maskingInfo.ScreenSpaceScissorArea; + // When drawing to a viewport that doesn't match the projection size (e.g. via framebuffers), the resultant image will be scaled + Vector2 projectionScale = new Vector2(ProjectionMatrix.Row0.X / 2, -ProjectionMatrix.Row1.Y / 2); + Vector2 viewportScale = Vector2.Multiply(Viewport.Size, projectionScale); - if (!overwritePreviousScissor) - { - Vector4 currentSmiScissorRectangle = ShaderMaskingStack!.CurrentBuffer[ShaderMaskingStack.CurrentOffset].ScissorRect; - RectangleF currentScissorRectangle = RectangleF.FromLTRB( - currentSmiScissorRectangle.X, - currentSmiScissorRectangle.Y, - currentSmiScissorRectangle.Z, - currentSmiScissorRectangle.W); - - scissorRect = RectangleF.Intersect(currentScissorRectangle, scissorRect); - } + Vector2 location = (maskingInfo.ScreenSpaceAABB.Location - ScissorOffset) * viewportScale; + Vector2 size = maskingInfo.ScreenSpaceAABB.Size * viewportScale; - ShaderMaskingStack!.Push(new ShaderMaskingInfo - { - IsMasking = IsMaskingActive, - MaskingRect = new Vector4( - maskingInfo.MaskingArea.Left, - maskingInfo.MaskingArea.Top, - maskingInfo.MaskingArea.Right, - maskingInfo.MaskingArea.Bottom), - ScissorRect = new Vector4( - scissorRect.Left, - scissorRect.Top, - scissorRect.Right, - scissorRect.Bottom), - ToMaskingSpace = new Matrix4(maskingInfo.ToMaskingSpace), - ToScissorSpace = new Matrix4(maskingInfo.ToScissorSpace), - CornerRadius = maskingInfo.CornerRadius, - CornerExponent = maskingInfo.CornerExponent, - BorderThickness = maskingInfo.BorderThickness / maskingInfo.BlendRange, - BorderColour = maskingInfo.BorderThickness > 0 - ? new Matrix4( - // TopLeft - maskingInfo.BorderColour.TopLeft.SRGB.R, - maskingInfo.BorderColour.TopLeft.SRGB.G, - maskingInfo.BorderColour.TopLeft.SRGB.B, - maskingInfo.BorderColour.TopLeft.SRGB.A, - // BottomLeft - maskingInfo.BorderColour.BottomLeft.SRGB.R, - maskingInfo.BorderColour.BottomLeft.SRGB.G, - maskingInfo.BorderColour.BottomLeft.SRGB.B, - maskingInfo.BorderColour.BottomLeft.SRGB.A, - // TopRight - maskingInfo.BorderColour.TopRight.SRGB.R, - maskingInfo.BorderColour.TopRight.SRGB.G, - maskingInfo.BorderColour.TopRight.SRGB.B, - maskingInfo.BorderColour.TopRight.SRGB.A, - // BottomRight - maskingInfo.BorderColour.BottomRight.SRGB.R, - maskingInfo.BorderColour.BottomRight.SRGB.G, - maskingInfo.BorderColour.BottomRight.SRGB.B, - maskingInfo.BorderColour.BottomRight.SRGB.A) - : ShaderMaskingStack.CurrentBuffer[ShaderMaskingStack.CurrentOffset].BorderColour, - MaskingBlendRange = maskingInfo.BlendRange, - AlphaExponent = maskingInfo.AlphaExponent, - EdgeOffset = maskingInfo.EdgeOffset, - DiscardInner = maskingInfo.Hollow, - InnerCornerRadius = maskingInfo.Hollow - ? maskingInfo.HollowCornerRadius - : ShaderMaskingStack.CurrentBuffer[ShaderMaskingStack.CurrentOffset].InnerCornerRadius, - }); + RectangleI actualRect = new RectangleI( + (int)Math.Floor(location.X), + (int)Math.Floor(location.Y), + (int)Math.Ceiling(size.X), + (int)Math.Ceiling(size.Y)); + + PushScissor(overwritePreviousScissor ? actualRect : RectangleI.Intersect(scissorRectStack.Peek(), actualRect)); } else - ShaderMaskingStack!.Pop(); + PopScissor(); currentMaskingInfo = maskingInfo; } diff --git a/osu.Framework/Graphics/Rendering/RendererExtensions.cs b/osu.Framework/Graphics/Rendering/RendererExtensions.cs index e0dae0b7d8..e56c7d0d14 100644 --- a/osu.Framework/Graphics/Rendering/RendererExtensions.cs +++ b/osu.Framework/Graphics/Rendering/RendererExtensions.cs @@ -263,14 +263,9 @@ public static void PushOrtho(this IRenderer renderer, RectangleF ortho) public static void PushLocalMatrix(this IRenderer renderer, Matrix4 matrix) { var currentMasking = renderer.CurrentMaskingInfo; - - // Normally, ToMaskingSpace is used to convert from screen-space coordinates to local coordinates in the masking-space. - // But if a local matrix is pushed, then vertices will instead be provided in local-space, such that: - // 1. To convert to masking-space we need to first convert to screen-space. - // 2. To convert to scissor-space we need to convert to screen-space. + // normally toMaskingSpace is fed vertices already in screen space coordinates, + // but since we are modifying the matrix the vertices are in local space currentMasking.ToMaskingSpace = new Matrix3(matrix) * currentMasking.ToMaskingSpace; - currentMasking.ToScissorSpace = new Matrix3(matrix); - renderer.PushMaskingInfo(currentMasking, true); renderer.PushProjectionMatrix(matrix * renderer.ProjectionMatrix); } @@ -279,13 +274,10 @@ public static void PushLocalMatrix(this IRenderer renderer, Matrix4 matrix) public static void PushLocalMatrix(this IRenderer renderer, Matrix3 matrix) { var currentMasking = renderer.CurrentMaskingInfo; - - // Normally, ToMaskingSpace is used to convert from screen-space coordinates to local coordinates in the masking-space. - // But if a local matrix is pushed, then vertices will instead be provided in local-space, such that: - // 1. To convert to masking-space we need to first convert to screen-space. - // 2. To convert to scissor-space we need to convert to screen-space. + // normally toMaskingSpace is fed vertices already in screen space coordinates, + // but since we are modifying the matrix the vertices are in local space currentMasking.ToMaskingSpace = matrix * currentMasking.ToMaskingSpace; - currentMasking.ToScissorSpace = matrix; + renderer.PushMaskingInfo(currentMasking, true); // this makes sure it also works for 3D vertices like the ones path uses Matrix4 mat = new Matrix4(matrix); @@ -293,8 +285,6 @@ public static void PushLocalMatrix(this IRenderer renderer, Matrix3 matrix) mat.Row2.X = 0; mat.Row3.Y = mat.Row2.Y; mat.Row2.Y = 0; - - renderer.PushMaskingInfo(currentMasking, true); renderer.PushProjectionMatrix(mat * renderer.ProjectionMatrix); } diff --git a/osu.Framework/Graphics/Rendering/ShaderMaskingInfo.cs b/osu.Framework/Graphics/Rendering/ShaderMaskingInfo.cs deleted file mode 100644 index aa4eb342e5..0000000000 --- a/osu.Framework/Graphics/Rendering/ShaderMaskingInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Runtime.InteropServices; -using osu.Framework.Graphics.Shaders.Types; - -namespace osu.Framework.Graphics.Rendering -{ - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public record struct ShaderMaskingInfo - { - public UniformMatrix4 ToMaskingSpace; - public UniformMatrix4 ToScissorSpace; - - public UniformBool IsMasking; - public UniformFloat CornerRadius; - public UniformFloat CornerExponent; - public UniformFloat BorderThickness; - - public UniformVector4 MaskingRect; - public UniformVector4 ScissorRect; - - public UniformMatrix4 BorderColour; - public UniformFloat MaskingBlendRange; - public UniformFloat AlphaExponent; - public UniformVector2 EdgeOffset; - - public UniformBool DiscardInner; - public UniformFloat InnerCornerRadius; - private readonly UniformPadding8 pad1; - } -} diff --git a/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex2D.cs b/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex2D.cs index 073befa2b3..4a31c2bfd4 100644 --- a/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex2D.cs +++ b/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex2D.cs @@ -30,9 +30,6 @@ public struct TexturedVertex2D : IEquatable, IVertex [VertexMember(1, VertexAttribPointerType.Float)] private readonly float backbufferDrawDepth; - [VertexMember(1, VertexAttribPointerType.Int)] - private readonly int maskingIndex; - [Obsolete("Initialise this type with an IRenderer instead", true)] public TexturedVertex2D() { @@ -43,7 +40,6 @@ public TexturedVertex2D(IRenderer renderer) { this = default; // explicitly initialise all members to default values backbufferDrawDepth = renderer.BackbufferDrawDepth; - maskingIndex = renderer.CurrentMaskingIndex; } public readonly bool Equals(TexturedVertex2D other) => @@ -52,7 +48,6 @@ public readonly bool Equals(TexturedVertex2D other) => && Colour.Equals(other.Colour) && TextureRect.Equals(other.TextureRect) && BlendRange.Equals(other.BlendRange) - && backbufferDrawDepth == other.backbufferDrawDepth - && maskingIndex == other.maskingIndex; + && backbufferDrawDepth == other.backbufferDrawDepth; } } diff --git a/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex3D.cs b/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex3D.cs index 571dddfe34..34bcbac314 100644 --- a/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex3D.cs +++ b/osu.Framework/Graphics/Rendering/Vertices/TexturedVertex3D.cs @@ -21,25 +21,6 @@ public struct TexturedVertex3D : IEquatable, IVertex [VertexMember(2, VertexAttribPointerType.Float)] public Vector2 TexturePosition; - [VertexMember(1, VertexAttribPointerType.Int)] - private readonly int maskingIndex; - - [Obsolete("Initialise this type with an IRenderer instead", true)] - public TexturedVertex3D() - { - this = default; // explicitly initialise all members to default values - } - - public TexturedVertex3D(IRenderer renderer) - { - this = default; // explicitly initialise all members to default values - maskingIndex = renderer.CurrentMaskingIndex; - } - - public readonly bool Equals(TexturedVertex3D other) - => Position.Equals(other.Position) - && TexturePosition.Equals(other.TexturePosition) - && Colour.Equals(other.Colour) - && maskingIndex == other.maskingIndex; + public readonly bool Equals(TexturedVertex3D other) => Position.Equals(other.Position) && TexturePosition.Equals(other.TexturePosition) && Colour.Equals(other.Colour); } } diff --git a/osu.Framework/Graphics/Shaders/ShaderManager.cs b/osu.Framework/Graphics/Shaders/ShaderManager.cs index 0620b004f0..27fa27653e 100644 --- a/osu.Framework/Graphics/Shaders/ShaderManager.cs +++ b/osu.Framework/Graphics/Shaders/ShaderManager.cs @@ -149,7 +149,6 @@ protected virtual void Dispose(bool disposing) public static class VertexShaderDescriptor { public const string TEXTURE_2 = "Texture2D"; - public const string TEXTURE_2_NO_MASKING = "Texture2D_NoMasking"; public const string TEXTURE_3 = "Texture3D"; public const string POSITION = "Position"; } diff --git a/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs b/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs index a69a1c0406..57ce6ad3ec 100644 --- a/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs +++ b/osu.Framework/Graphics/Veldrid/VeldridRenderer.cs @@ -547,7 +547,6 @@ public void DrawVertices(PrimitiveTopology type, int vertexStart, int verticesCo var veldridShader = (VeldridShader)Shader!; veldridShader.BindUniformBlock("g_GlobalUniforms", GlobalUniformBuffer!); - veldridShader.BindUniformBlock("g_MaskingBuffer", ShaderMaskingStack!.CurrentBuffer); pipeline.PrimitiveTopology = type; Array.Resize(ref pipeline.ResourceLayouts, veldridShader.LayoutCount); diff --git a/osu.Framework/Resources/Shaders/Internal/sh_GlobalUniforms.h b/osu.Framework/Resources/Shaders/Internal/sh_GlobalUniforms.h index d7843cf5f9..514c2dcb88 100644 --- a/osu.Framework/Resources/Shaders/Internal/sh_GlobalUniforms.h +++ b/osu.Framework/Resources/Shaders/Internal/sh_GlobalUniforms.h @@ -19,6 +19,19 @@ layout(std140, set = -1, binding = 0) uniform g_GlobalUniforms bool g_IsUvOriginTopLeft; mat4 g_ProjMatrix; + mat3 g_ToMaskingSpace; + + bool g_IsMasking; + highp float g_CornerRadius; + highp float g_CornerExponent; + highp vec4 g_MaskingRect; + highp float g_BorderThickness; + lowp mat4 g_BorderColour; + mediump float g_MaskingBlendRange; + lowp float g_AlphaExponent; + highp vec2 g_EdgeOffset; + bool g_DiscardInner; + highp float g_InnerCornerRadius; // 0 -> None // 1 -> ClampToEdge diff --git a/osu.Framework/Resources/Shaders/Internal/sh_MaskingInfo.h b/osu.Framework/Resources/Shaders/Internal/sh_MaskingInfo.h deleted file mode 100644 index 64b94cb266..0000000000 --- a/osu.Framework/Resources/Shaders/Internal/sh_MaskingInfo.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef INTERNAL_MASKING_INFO_H -#define INTERNAL_MASKING_INFO_H - -#extension GL_ARB_shader_storage_buffer_object : enable - -struct MaskingInfo -{ - mat4 ToMaskingSpace; - mat4 ToScissorSpace; - - bool IsMasking; - highp float CornerRadius; - highp float CornerExponent; - highp float BorderThickness; - - highp vec4 MaskingRect; - highp vec4 ScissorRect; - - lowp mat4 BorderColour; - mediump float MaskingBlendRange; - lowp float AlphaExponent; - highp vec2 EdgeOffset; - - bool DiscardInner; - highp float InnerCornerRadius; - vec2 pad1; -}; - -MaskingInfo g_MaskingInfo; - -#ifndef OSU_GRAPHICS_NO_SSBO - -layout(std140, set = -2, binding = 0) readonly buffer g_MaskingBuffer -{ - MaskingInfo Data[]; -} MaskingBuffer; - -#else // OSU_GRAPHICS_NO_SSBO - -layout(std140, set = -2, binding = 0) uniform g_MaskingBuffer -{ - MaskingInfo Data[60]; -} MaskingBuffer; - -#endif // OSU_GRAPHICS_NO_SSBO - -void InitMasking(int index) -{ - g_MaskingInfo = MaskingBuffer.Data[index]; -} - -#endif // INTERNAL_MASKING_INFO_H \ No newline at end of file diff --git a/osu.Framework/Resources/Shaders/sh_Masking.h b/osu.Framework/Resources/Shaders/sh_Masking.h index cc71a80321..3fdc6c8846 100644 --- a/osu.Framework/Resources/Shaders/sh_Masking.h +++ b/osu.Framework/Resources/Shaders/sh_Masking.h @@ -1,8 +1,6 @@ #ifndef MASKING_H #define MASKING_H -#include "Internal/sh_MaskingInfo.h" - layout(location = 0) in highp vec2 v_MaskingPosition; layout(location = 1) in lowp vec4 v_Colour; @@ -13,27 +11,14 @@ layout(location = 1) in lowp vec4 v_Colour; #endif layout(location = 4) in mediump vec2 v_BlendRange; -layout(location = 5) flat in int v_MaskingIndex; -layout(location = 6) in highp vec2 v_ScissorPosition; - -/// Positive if outside the rect, negative if inside the rect. -highp float distanceFromScissorRect() -{ - highp vec2 topLeftOffset = g_MaskingInfo.ScissorRect.xy - v_ScissorPosition; - highp vec2 bottomRightOffset = v_ScissorPosition - g_MaskingInfo.ScissorRect.zw; - - highp vec2 distanceFromShrunkRect = max(bottomRightOffset, topLeftOffset); - - return max(distanceFromShrunkRect.x, distanceFromShrunkRect.y); -} highp float distanceFromRoundedRect(highp vec2 offset, highp float radius) { highp vec2 maskingPosition = v_MaskingPosition + offset; // Compute offset distance from masking rect in masking space. - highp vec2 topLeftOffset = g_MaskingInfo.MaskingRect.xy - maskingPosition; - highp vec2 bottomRightOffset = maskingPosition - g_MaskingInfo.MaskingRect.zw; + highp vec2 topLeftOffset = g_MaskingRect.xy - maskingPosition; + highp vec2 bottomRightOffset = maskingPosition - g_MaskingRect.zw; highp vec2 distanceFromShrunkRect = max( bottomRightOffset + vec2(radius), @@ -48,7 +33,7 @@ highp float distanceFromRoundedRect(highp vec2 offset, highp float radius) else { distanceFromShrunkRect = max(vec2(0.0), distanceFromShrunkRect); - return pow(pow(distanceFromShrunkRect.x, g_MaskingInfo.CornerExponent) + pow(distanceFromShrunkRect.y, g_MaskingInfo.CornerExponent), 1.0 / g_MaskingInfo.CornerExponent); + return pow(pow(distanceFromShrunkRect.x, g_CornerExponent) + pow(distanceFromShrunkRect.y, g_CornerExponent), 1.0 / g_CornerExponent); } } @@ -70,53 +55,46 @@ highp float distanceFromDrawingRect(mediump vec2 texCoord) lowp vec4 getBorderColour() { - highp vec2 relativeTexCoord = v_MaskingPosition / (g_MaskingInfo.MaskingRect.zw - g_MaskingInfo.MaskingRect.xy); - lowp vec4 top = mix(g_MaskingInfo.BorderColour[0], g_MaskingInfo.BorderColour[2], relativeTexCoord.x); - lowp vec4 bottom = mix(g_MaskingInfo.BorderColour[1], g_MaskingInfo.BorderColour[3], relativeTexCoord.x); + highp vec2 relativeTexCoord = v_MaskingPosition / (g_MaskingRect.zw - g_MaskingRect.xy); + lowp vec4 top = mix(g_BorderColour[0], g_BorderColour[2], relativeTexCoord.x); + lowp vec4 bottom = mix(g_BorderColour[1], g_BorderColour[3], relativeTexCoord.x); return mix(top, bottom, relativeTexCoord.y); } lowp vec4 getRoundedColor(lowp vec4 texel, mediump vec2 texCoord) { - InitMasking(v_MaskingIndex); - - if (!g_MaskingInfo.IsMasking && v_BlendRange == vec2(0.0)) + if (!g_IsMasking && v_BlendRange == vec2(0.0)) { return v_Colour * texel; } - if (distanceFromScissorRect() > 0) - { - discard; - } - - highp float dist = distanceFromRoundedRect(vec2(0.0), g_MaskingInfo.CornerRadius); + highp float dist = distanceFromRoundedRect(vec2(0.0), g_CornerRadius); lowp float alphaFactor = 1.0; // Discard inner pixels - if (g_MaskingInfo.DiscardInner) + if (g_DiscardInner) { - highp float innerDist = (g_MaskingInfo.EdgeOffset == vec2(0.0) && g_MaskingInfo.InnerCornerRadius == g_MaskingInfo.CornerRadius) ? - dist : distanceFromRoundedRect(g_MaskingInfo.EdgeOffset, g_MaskingInfo.InnerCornerRadius); + highp float innerDist = (g_EdgeOffset == vec2(0.0) && g_InnerCornerRadius == g_CornerRadius) ? + dist : distanceFromRoundedRect(g_EdgeOffset, g_InnerCornerRadius); - // v_BlendRange is set from outside in a hacky way to tell us the g_MaskingInfo.MaskingBlendRange used for the rounded + // v_BlendRange is set from outside in a hacky way to tell us the g_MaskingBlendRange used for the rounded // corners of the edge effect container itself. We can then derive the alpha factor for smooth inner edge // effect from that. - highp float innerBlendFactor = (g_MaskingInfo.InnerCornerRadius - g_MaskingInfo.MaskingBlendRange - innerDist) / v_BlendRange.x; + highp float innerBlendFactor = (g_InnerCornerRadius - g_MaskingBlendRange - innerDist) / v_BlendRange.x; if (innerBlendFactor > 1.0) { return vec4(0.0); } - // We exponentiate our factor to exactly counteract the later exponentiation by g_MaskingInfo.AlphaExponent for a smoother inner border. - alphaFactor = pow(min(1.0 - innerBlendFactor, 1.0), 1.0 / g_MaskingInfo.AlphaExponent); + // We exponentiate our factor to exactly counteract the later exponentiation by g_AlphaExponent for a smoother inner border. + alphaFactor = pow(min(1.0 - innerBlendFactor, 1.0), 1.0 / g_AlphaExponent); } - dist /= g_MaskingInfo.MaskingBlendRange; + dist /= g_MaskingBlendRange; // This correction is needed to avoid fading of the alpha value for radii below 1px. - highp float radiusCorrection = g_MaskingInfo.CornerRadius <= 0.0 ? g_MaskingInfo.MaskingBlendRange : max(0.0, g_MaskingInfo.MaskingBlendRange - g_MaskingInfo.CornerRadius); - highp float fadeStart = (g_MaskingInfo.CornerRadius + radiusCorrection) / g_MaskingInfo.MaskingBlendRange; + highp float radiusCorrection = g_CornerRadius <= 0.0 ? g_MaskingBlendRange : max(0.0, g_MaskingBlendRange - g_CornerRadius); + highp float fadeStart = (g_CornerRadius + radiusCorrection) / g_MaskingBlendRange; alphaFactor *= min(fadeStart - dist, 1.0); if (v_BlendRange.x > 0.0 || v_BlendRange.y > 0.0) @@ -130,9 +108,9 @@ lowp vec4 getRoundedColor(lowp vec4 texel, mediump vec2 texCoord) } // This ends up softening glow without negatively affecting edge smoothness much. - alphaFactor = pow(alphaFactor, g_MaskingInfo.AlphaExponent); + alphaFactor = pow(alphaFactor, g_AlphaExponent); - highp float borderStart = 1.0 + fadeStart - g_MaskingInfo.BorderThickness; + highp float borderStart = 1.0 + fadeStart - g_BorderThickness; lowp float colourWeight = min(borderStart - dist, 1.0); lowp vec4 contentColour = v_Colour * texel; diff --git a/osu.Framework/Resources/Shaders/sh_Texture2D.vs b/osu.Framework/Resources/Shaders/sh_Texture2D.vs index b607200ddd..5024d59c47 100644 --- a/osu.Framework/Resources/Shaders/sh_Texture2D.vs +++ b/osu.Framework/Resources/Shaders/sh_Texture2D.vs @@ -2,7 +2,6 @@ #define TEXTURE2D_VS #include "sh_Utils.h" -#include "Internal/sh_MaskingInfo.h" layout(location = 0) in highp vec2 m_Position; layout(location = 1) in lowp vec4 m_Colour; @@ -10,33 +9,23 @@ layout(location = 2) in highp vec2 m_TexCoord; layout(location = 3) in highp vec4 m_TexRect; layout(location = 4) in mediump vec2 m_BlendRange; layout(location = 5) in highp float m_BackbufferDrawDepth; -layout(location = 6) in int m_MaskingIndex; layout(location = 0) out highp vec2 v_MaskingPosition; layout(location = 1) out lowp vec4 v_Colour; layout(location = 2) out highp vec2 v_TexCoord; layout(location = 3) out highp vec4 v_TexRect; layout(location = 4) out mediump vec2 v_BlendRange; -layout(location = 5) flat out int v_MaskingIndex; -layout(location = 6) out highp vec2 v_ScissorPosition; void main(void) { - InitMasking(m_MaskingIndex); - // Transform from screen space to masking space. - highp vec4 maskingPos = g_MaskingInfo.ToMaskingSpace * vec4(m_Position, 1.0, 0.0); + highp vec3 maskingPos = g_ToMaskingSpace * vec3(m_Position, 1.0); v_MaskingPosition = maskingPos.xy / maskingPos.z; - // Transform from screen space to scissor space. - highp vec4 scissorPos = g_MaskingInfo.ToScissorSpace * vec4(m_Position, 1.0, 0.0); - v_ScissorPosition = scissorPos.xy / scissorPos.z; - v_Colour = m_Colour; v_TexCoord = m_TexCoord; v_TexRect = m_TexRect; v_BlendRange = m_BlendRange; - v_MaskingIndex = m_MaskingIndex; gl_Position = g_ProjMatrix * vec4(m_Position, 1.0, 1.0); diff --git a/osu.Framework/Resources/Shaders/sh_Texture2D_NoMasking.vs b/osu.Framework/Resources/Shaders/sh_Texture2D_NoMasking.vs deleted file mode 100644 index 652076e0b9..0000000000 --- a/osu.Framework/Resources/Shaders/sh_Texture2D_NoMasking.vs +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef TEXTURE2D_NO_MASKING_VS -#define TEXTURE2D_NO_MASKING_VS - -#include "sh_Utils.h" - -layout(location = 0) in highp vec2 m_Position; -layout(location = 1) in lowp vec4 m_Colour; -layout(location = 2) in highp vec2 m_TexCoord; -layout(location = 3) in highp vec4 m_TexRect; -layout(location = 4) in mediump vec2 m_BlendRange; -layout(location = 5) in highp float m_BackbufferDrawDepth; - -layout(location = 0) out highp vec2 v_MaskingPosition; -layout(location = 1) out lowp vec4 v_Colour; -layout(location = 2) out highp vec2 v_TexCoord; -layout(location = 3) out highp vec4 v_TexRect; -layout(location = 4) out mediump vec2 v_BlendRange; - -void main(void) -{ - v_Colour = m_Colour; - v_TexCoord = m_TexCoord; - v_TexRect = m_TexRect; - v_BlendRange = m_BlendRange; - - gl_Position = g_ProjMatrix * vec4(m_Position, 1.0, 1.0); - - if (g_BackbufferDraw) - gl_Position.z = m_BackbufferDrawDepth; -} - -#endif \ No newline at end of file diff --git a/osu.Framework/Resources/Shaders/sh_Texture3D.vs b/osu.Framework/Resources/Shaders/sh_Texture3D.vs index 4f64e01657..8b565d8008 100644 --- a/osu.Framework/Resources/Shaders/sh_Texture3D.vs +++ b/osu.Framework/Resources/Shaders/sh_Texture3D.vs @@ -2,39 +2,28 @@ #define TEXTURE3D_VS #include "sh_Utils.h" -#include "Internal/sh_MaskingInfo.h" layout(location = 0) in highp vec3 m_Position; layout(location = 1) in lowp vec4 m_Colour; layout(location = 2) in highp vec2 m_TexCoord; -layout(location = 3) in int m_MaskingIndex; layout(location = 0) out highp vec2 v_MaskingPosition; layout(location = 1) out lowp vec4 v_Colour; layout(location = 2) out highp vec2 v_TexCoord; layout(location = 3) out highp vec4 v_TexRect; layout(location = 4) out mediump vec2 v_BlendRange; -layout(location = 5) flat out int v_MaskingIndex; -layout(location = 6) out highp vec2 v_ScissorPosition; void main(void) { - InitMasking(m_MaskingIndex); - - // Transform from screen space to masking space. - highp vec4 maskingPos = g_MaskingInfo.ToMaskingSpace * vec4(m_Position.xy, 1.0, 0.0); + // Transform to position to masking space. + vec3 maskingPos = g_ToMaskingSpace * vec3(m_Position.xy, 1.0); v_MaskingPosition = maskingPos.xy / maskingPos.z; - // Transform from screen space to scissor space. - highp vec4 scissorPos = g_MaskingInfo.ToScissorSpace * vec4(m_Position.xy, 1.0, 0.0); - v_ScissorPosition = scissorPos.xy / scissorPos.z; - v_TexRect = vec4(0.0); v_BlendRange = vec2(0.0); + v_Colour = m_Colour; v_TexCoord = m_TexCoord; - v_MaskingIndex = m_MaskingIndex; - gl_Position = g_ProjMatrix * vec4(m_Position, 1.0); }