A game framework written with osu! in mind.
at master 137 lines 5.1 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System.Collections.Generic; 5using osu.Framework.Graphics.OpenGL; 6using osu.Framework.Graphics.OpenGL.Buffers; 7using osuTK; 8using osuTK.Graphics; 9using osu.Framework.Graphics.Primitives; 10using osu.Framework.Graphics.Shaders; 11using System; 12using osu.Framework.Graphics.Colour; 13using osu.Framework.Utils; 14using osuTK.Graphics.ES30; 15 16namespace osu.Framework.Graphics.Containers 17{ 18 public partial class BufferedContainer<T> 19 { 20 private class BufferedContainerDrawNode : BufferedDrawNode, ICompositeDrawNode 21 { 22 protected new BufferedContainer<T> Source => (BufferedContainer<T>)base.Source; 23 24 protected new CompositeDrawableDrawNode Child => (CompositeDrawableDrawNode)base.Child; 25 26 private bool drawOriginal; 27 private ColourInfo effectColour; 28 private BlendingParameters effectBlending; 29 private EffectPlacement effectPlacement; 30 31 private Vector2 blurSigma; 32 private Vector2I blurRadius; 33 private float blurRotation; 34 35 private long updateVersion; 36 37 private IShader blurShader; 38 39 public BufferedContainerDrawNode(BufferedContainer<T> source, BufferedContainerDrawNodeSharedData sharedData) 40 : base(source, new CompositeDrawableDrawNode(source), sharedData) 41 { 42 } 43 44 public override void ApplyState() 45 { 46 base.ApplyState(); 47 48 updateVersion = Source.updateVersion; 49 50 effectColour = Source.EffectColour; 51 effectBlending = Source.DrawEffectBlending; 52 effectPlacement = Source.EffectPlacement; 53 54 drawOriginal = Source.DrawOriginal; 55 blurSigma = Source.BlurSigma; 56 blurRadius = new Vector2I(Blur.KernelSize(blurSigma.X), Blur.KernelSize(blurSigma.Y)); 57 blurRotation = Source.BlurRotation; 58 59 blurShader = Source.blurShader; 60 } 61 62 protected override long GetDrawVersion() => updateVersion; 63 64 protected override void PopulateContents() 65 { 66 base.PopulateContents(); 67 68 if (blurRadius.X > 0 || blurRadius.Y > 0) 69 { 70 GLWrapper.PushScissorState(false); 71 72 if (blurRadius.X > 0) drawBlurredFrameBuffer(blurRadius.X, blurSigma.X, blurRotation); 73 if (blurRadius.Y > 0) drawBlurredFrameBuffer(blurRadius.Y, blurSigma.Y, blurRotation + 90); 74 75 GLWrapper.PopScissorState(); 76 } 77 } 78 79 protected override void DrawContents() 80 { 81 if (drawOriginal && effectPlacement == EffectPlacement.InFront) 82 base.DrawContents(); 83 84 GLWrapper.SetBlend(effectBlending); 85 86 ColourInfo finalEffectColour = DrawColourInfo.Colour; 87 finalEffectColour.ApplyChild(effectColour); 88 89 DrawFrameBuffer(SharedData.CurrentEffectBuffer, DrawRectangle, finalEffectColour); 90 91 if (drawOriginal && effectPlacement == EffectPlacement.Behind) 92 base.DrawContents(); 93 } 94 95 private void drawBlurredFrameBuffer(int kernelRadius, float sigma, float blurRotation) 96 { 97 FrameBuffer current = SharedData.CurrentEffectBuffer; 98 FrameBuffer target = SharedData.GetNextEffectBuffer(); 99 100 GLWrapper.SetBlend(BlendingParameters.None); 101 102 using (BindFrameBuffer(target)) 103 { 104 blurShader.GetUniform<int>(@"g_Radius").UpdateValue(ref kernelRadius); 105 blurShader.GetUniform<float>(@"g_Sigma").UpdateValue(ref sigma); 106 107 Vector2 size = current.Size; 108 blurShader.GetUniform<Vector2>(@"g_TexSize").UpdateValue(ref size); 109 110 float radians = -MathUtils.DegreesToRadians(blurRotation); 111 Vector2 blur = new Vector2(MathF.Cos(radians), MathF.Sin(radians)); 112 blurShader.GetUniform<Vector2>(@"g_BlurDirection").UpdateValue(ref blur); 113 114 blurShader.Bind(); 115 DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White)); 116 blurShader.Unbind(); 117 } 118 } 119 120 public List<DrawNode> Children 121 { 122 get => Child.Children; 123 set => Child.Children = value; 124 } 125 126 public bool AddChildDrawNodes => RequiresRedraw; 127 } 128 129 private class BufferedContainerDrawNodeSharedData : BufferedDrawNodeSharedData 130 { 131 public BufferedContainerDrawNodeSharedData(RenderbufferInternalFormat[] formats, bool pixelSnapping) 132 : base(2, formats, pixelSnapping) 133 { 134 } 135 } 136 } 137}