C# Winform做动画卡顿怎么办?

Winform用的GDI+,像全屏动画这种卡的稀巴烂,任务管理器看进程如果GPU没动静那就是渣,没加速。

可以使用OpenGL或者DirectX这样有GPU加速就不卡了。

OpenGL用下面这个,控件里会多出一个glControl,拖到form上

using OpenTK.Graphics.ES20;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SkiaDemo
{
    public partial class Form1 : Form
    {
        Random rand = new Random();
        SKColorType colorType = SKColorType.Rgba8888;

        public Form1()
        {
            InitializeComponent();

            glControl1.VSync = false; // why?
            glControl1.Paint += new PaintEventHandler(RenderWithOpenGL);
        }

        private void RenderWithOpenGL(object sender, PaintEventArgs e)
        {
            Control sctl = (Control)sender;
            int width = sctl.Width;
            int height = sctl.Height;

            // setup the Skia surface using OpenGL

            GRContext contextOpenGL = GRContext.Create(GRBackend.OpenGL, GRGlInterface.CreateNativeGlInterface());

            GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer);
            GRGlFramebufferInfo glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());
            GL.GetInteger(GetPName.StencilBits, out var stencil);
            GRBackendRenderTarget renderTarget = new GRBackendRenderTarget(width, height, contextOpenGL.GetMaxSurfaceSampleCount(colorType), stencil, glInfo);

            SKSurface surface = SKSurface.Create(contextOpenGL, renderTarget, GRSurfaceOrigin.BottomLeft, colorType);

            // Draw some stuff on the canvas

            surface.Canvas.Clear(SKColor.Parse("#FFFFFF")); // adds about 3ms fullscreen

            byte alpha = 128;
            var paint = new SKPaint();
            for (int i = 0; i < 1_000; i++)
            {
                float x1 = (float)(rand.NextDouble() * width);
                float x2 = (float)(rand.NextDouble() * width);
                float y1 = (float)(rand.NextDouble() * height);
                float y2 = (float)(rand.NextDouble() * height);

                paint.Color = new SKColor(
                        red: (byte)(rand.NextDouble() * 255),
                        green: (byte)(rand.NextDouble() * 255),
                        blue: (byte)(rand.NextDouble() * 255),
                        alpha: alpha
                    );

                surface.Canvas.DrawLine(x1, y1, x2, y2, paint);
            }

            surface.Canvas.Flush();
            glControl1.SwapBuffers();

            // prevent memory access violations by disposing before exiting
            renderTarget?.Dispose();
            contextOpenGL?.Dispose();
            surface?.Dispose(); 
        }

        private void BtnBenchmark_Click(object sender, EventArgs e)
        {
            int count = 250;

            btnBenchmark.Enabled = false;
            System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();

            progressBar1.Maximum = count;
            for (int i = 0; i < count; i++)
            {
                lblStatus.Text = $"on render {i + 1} of {count}...";
                progressBar1.Value = i + 1;
                progressBar1.Value = i;
                Application.DoEvents(); // adds about 1ms fullscreen
                glControl1.Refresh();
            }
            progressBar1.Value = 0;

            double meanSec = (double)stopwatch.ElapsedTicks / System.Diagnostics.Stopwatch.Frequency / count;
            lblStatus.Text = string.Format("mean render {0:0.00} ms ({1:0.00} Hz)", meanSec * 1000, 1.0 / meanSec);
            btnBenchmark.Enabled = true;
        }
    }
}

DirectX可以用SharpDX,也有提供窗体,改造窗体等方式

需安装SharpDX,SharpDX.Desktop,SharpDX.Direct2D1,SharpDX.DXGI,SharpDX.Mathematics

using System;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.Windows;
using System.Windows.Forms;

using D2DFactory = SharpDX.Direct2D1.Factory;
using DWriteFactory = SharpDX.DirectWrite.Factory;

namespace AdvancedTextRenderingApp
{
    public class CustomColorRenderer : SharpDX.DirectWrite.TextRendererBase
    {
        private RenderTarget renderTarget;
        private SolidColorBrush defaultBrush;

        public void AssignResources(RenderTarget renderTarget,SolidColorBrush defaultBrush)
        {
            this.renderTarget = renderTarget;
            this.defaultBrush = defaultBrush;
        }

        public override Result DrawGlyphRun(object clientDrawingContext, float baselineOriginX, float baselineOriginY, MeasuringMode measuringMode, GlyphRun glyphRun, GlyphRunDescription glyphRunDescription, ComObject clientDrawingEffect)
        {
            SolidColorBrush sb = defaultBrush;
            if (clientDrawingEffect != null && clientDrawingEffect is SolidColorBrush)
            {
                sb = (SolidColorBrush)clientDrawingEffect;
            }

            try
            {
                this.renderTarget.DrawGlyphRun(new Vector2(baselineOriginX, baselineOriginY), glyphRun, sb, measuringMode);
                return Result.Ok;
            }
            catch
            {
                return Result.Fail;
            }
        }
    }

    public class Program
    {        
        private static D2DFactory d2dFactory;
        private static DWriteFactory dwFactory;
        private static RenderForm mainForm;

        private static WindowRenderTarget renderTarget;

        private static TextFormat textFormat;
        private static TextLayout textLayout;

        //Various brushes for our example
        private static SolidColorBrush backgroundBrush;
        private static SolidColorBrush defaultBrush;
        private static SolidColorBrush greenBrush;
        private static SolidColorBrush redBrush;

        private static CustomColorRenderer textRenderer;

       
        private static RectangleF fullTextBackground;

        //This one is only a measured region
        private static RectangleF textRegionRect;
        

        private static string introText = @"Hello from SharpDX, this is a long text to show some more advanced features like paragraph alignment, custom drawing...";

        [STAThread]
        static void Main(string[] args)
        {
            mainForm = new RenderForm("Advanced Text rendering demo");

            d2dFactory = new D2DFactory();
            dwFactory = new DWriteFactory(SharpDX.DirectWrite.FactoryType.Shared);
            
            textRenderer = new CustomColorRenderer();

            CreateResources();

            var bgcolor = new Color4(0.1f,0.1f,0.1f,1.0f);

            //This is the offset where we start our text layout
            Vector2 offset = new Vector2(202.0f,250.0f);

            textFormat = new TextFormat(dwFactory, "Arial", FontWeight.Regular, FontStyle.Normal, 16.0f);
            textLayout = new TextLayout(dwFactory, introText, textFormat, 300.0f, 200.0f);

            //Apply various modifications to text
            textLayout.SetUnderline(true, new TextRange(0, 5));
            textLayout.SetDrawingEffect(greenBrush, new TextRange(10, 20));
            textLayout.SetFontSize(24.0f, new TextRange(6, 4));
            textLayout.SetFontFamilyName("Comic Sans MS", new TextRange(11,7));

            //Measure full layout
            var textSize = textLayout.Metrics;
            fullTextBackground = new RectangleF(textSize.Left + offset.X, textSize.Top + offset.Y, textSize.Width, textSize.Height);

            //Measure text to apply background to
            var metrics = textLayout.HitTestTextRange(53, 4, 0.0f, 0.0f)[0];
            textRegionRect = new RectangleF(metrics.Left + offset.X, metrics.Top + offset.Y, metrics.Width, metrics.Height);

            //Assign render target and brush to our custom renderer
            textRenderer.AssignResources(renderTarget, defaultBrush);

            RenderLoop.Run(mainForm, () =>
            {
                renderTarget.BeginDraw();
                renderTarget.Clear(bgcolor);

                renderTarget.FillRectangle(fullTextBackground, backgroundBrush);

                renderTarget.FillRectangle(textRegionRect, redBrush);

                textLayout.Draw(textRenderer, offset.X, offset.Y);

                try
                {
                    renderTarget.EndDraw();
                }
                catch
                {
                    CreateResources();
                }
            });

            d2dFactory.Dispose();
            dwFactory.Dispose();
            renderTarget.Dispose();
        }

        private static void CreateResources()
        {
            if (renderTarget != null) { renderTarget.Dispose(); }
            if (defaultBrush != null) { defaultBrush.Dispose(); }
            if (greenBrush != null) { greenBrush.Dispose(); }
            if (redBrush != null) { redBrush.Dispose(); }
            if (backgroundBrush != null) { backgroundBrush.Dispose(); }


            HwndRenderTargetProperties wtp = new HwndRenderTargetProperties();
            wtp.Hwnd = mainForm.Handle;
            wtp.PixelSize = new Size2(mainForm.ClientSize.Width, mainForm.ClientSize.Height);
            wtp.PresentOptions = PresentOptions.Immediately;
            renderTarget = new WindowRenderTarget(d2dFactory, new RenderTargetProperties(), wtp);

            defaultBrush = new SolidColorBrush(renderTarget, Color.White);
            greenBrush = new SolidColorBrush(renderTarget, Color.Green);
            redBrush = new SolidColorBrush(renderTarget, Color.Red);
            backgroundBrush = new SolidColorBrush(renderTarget, new Color4(0.3f, 0.3f, 0.3f, 0.5f));

            textRenderer.AssignResources(renderTarget, defaultBrush);

        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖无疾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值