2019-10-23-C#-从零开始写-SharpDx-应用-绘制基础图形
title | author | date | CreateTime | categories |
---|---|---|---|---|
C# 从零开始写 SharpDx 应用 绘制基础图形
|
lindexi
|
2019-10-23 21:16:35 +0800
|
2019-06-03 14:44:22 +0800
|
C#
|
本文告诉大家通过 SharpDx 画出简单的 2D 界面
本文属于 SharpDx 系列 博客,建议从头开始读
本文分为两步,第一步是初始化,第二步才是画界面
初始化
先创建 RenderForm 用来显示界面,在创建的过程需要指定宽度和高度
- _renderForm = new RenderForm();
- _renderForm.ClientSize = new Size(Width, Height);
- private const int Width = 1280;
- private const int Height = 720;
上面创建的代码大部分参阅了C# 从零开始写 SharpDx 应用 初始化dx修改颜色的代码
在 InitializeDeviceResources 函数里面更改一些参数,用于创建资源和初始化
- var backBufferDesc =
- new ModeDescription(Width, Height, new Rational(60, 1), Format.R8G8B8A8_UNorm);
- var swapChainDesc = new SwapChainDescription
- {
- BufferCount = 1,
- ModeDescription = backBufferDesc,
- IsWindowed = true,
- OutputHandle = _renderForm.Handle,
- SampleDescription = new SampleDescription(1, 0),
- SwapEffect = SwapEffect.Discard,
- Usage = Usage.RenderTargetOutput
- };
- Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport, swapChainDesc,
- out _d3DDevice, out _swapChain);
- _d3DDeviceContext = _d3DDevice.ImmediateContext;
- using (var backBuffer = _swapChain.GetBackBuffer<Texture2D>(0))
- {
- _renderTargetView = new RenderTargetView(_d3DDevice, backBuffer);
- _viewport = new Viewport(0, 0, Width, Height);
- _d3DDeviceContext.Rasterizer.SetViewport(_viewport);
- }
- CreateD2DRender();
上面参数和C# 从零开始写 SharpDx 应用 初始化dx修改颜色的有一些不相同,在 SwapChainDescription 里面添加了 SwapEffect 参数
在创建交换链的时候,在 Device.CreateWithSwapChain 里面修改了 DeviceCreationFlags 参数
上面内容还是在创建 3D 内容,在 DX 里面是通过一个 3D 的平面画 2D 界面
在 CreateD2DRender 方法里面才是创建 2D 的代码
想要绘制界面需要 SharpDX.Direct2D1.RenderTarget
对象,需要先创建工厂然后通过工厂和交换链拿到平面,然后将输出定向到拿到的平面
创建工厂只需要直接创建
- var d2dFactory = new SharpDX.Direct2D1.Factory();
从交换链拿到平面
- Texture2D backBuffer = D3D11.Resource.FromSwapChain<Texture2D>(_swapChain, 0);
- Surface surface = backBuffer.QueryInterface<Surface>();
创建 RenderTarget 用于绘图
- var d2dRenderTarget = new RenderTarget(d2dFactory, surface,
- new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)));
这里 CreateD2DRender 方法代码请看下面
- using DeviceContext = SharpDX.Direct2D1.DeviceContext;
- using Factory = SharpDX.Direct2D1.Factory;
- private void CreateD2DRender()
- {
- var d2dFactory = new SharpDX.Direct2D1.Factory();
- Texture2D backBuffer = D3D11.Resource.FromSwapChain<Texture2D>(_swapChain, 0);
- Surface surface = backBuffer.QueryInterface<Surface>();
- var d2dRenderTarget = new RenderTarget(d2dFactory, surface,
- new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)));
- _d2dFactory = d2dFactory;
- _d2dRenderTarget = d2dRenderTarget;
- }
- private Factory _d2dFactory;
- private RenderTarget _d2dRenderTarget;
现在拿到了 _d2dRenderTarget
就可以用来画 2D 的界面了,开启绘制循环之后进行画界面
- public void Run()
- {
- RenderLoop.Run(_renderForm, RenderCallback);
- }
- private void RenderCallback()
- {
- Draw();
- }
- private void Draw()
- {
- // 在这里绘制
- }
下面将会告诉大家如何在 Draw 方法里面绘制界面
画界面
在 Draw 方法里面,使用下面方式画界面
- private void Draw()
- {
- _d2dRenderTarget.BeginDraw();
- // 实际画的代码
- _d2dRenderTarget.EndDraw();
- _swapChain.Present(1, PresentFlags.None);
- }
先调用 BeginDraw 方法开启绘制,在调用 EndDraw 方法将所有绘制指令压缩处理,大部分都是直接传送到显卡渲染
然后调用交换链 _swapChain
将后台缓存和前台显示交换,这样就可以做到刷新界面
具体画的内容可以分为基础图形和 3D 绘制
在所有开始绘制之前都需要调用 BeginDraw 方法,在绘制完成之后调用 EndDraw 方法将绘制的命令处理,然后发送到显卡
画线
画线条需要传入两个点,用两个点画出一条线条,还有线条的笔刷。可选的是线条的宽度,和样式
下面代码是作为添加所有参数的例子
- _d2dRenderTarget.BeginDraw();
- var brush = new SolidColorBrush(_d2dRenderTarget, ColorToRaw4(Color.Bisque));
- var styleProperties = new StrokeStyleProperties()
- {
- StartCap = CapStyle.Square,
- EndCap = CapStyle.Round
- };
- var strokeStyle = new StrokeStyle(_d2dFactory, styleProperties);
- using (strokeStyle)
- using (brush)
- {
- _d2dRenderTarget.DrawLine(new RawVector2(10, 100), new RawVector2(100, 100),
- brush, strokeWidth: 5, strokeStyle);
- }
- _d2dRenderTarget.EndDraw();
运行代码可以看到下面图片
这段代码写在 Draw 函数里面,在 SharpDx 里面创建的资源,例如笔画和样式等,都需要做手动的释放,这部分的写法和 WPF 不相同,需要自己关注资源的创建和释放,但是这样做才能做到更改的性能
在 StrokeStyleProperties 里面有很多有趣的参数,请大家自己玩一下
在代码里面用到 ColorToRaw4 方法,因为在 SharpDx 里面的颜色使用的范围是 0-1 而不是 System.Drawing.Color 使用 255 范围
- RawColor4 ColorToRaw4(Color color)
- {
- const float n = 255f;
- return new RawColor4(color.R / n, color.G / n, color.B / n, color.A / n);
- }
通过 ColorToRaw4 方法可以转换颜色
矩形
通过 DrawRectangle 方法可以画出矩形,在矩形里面需要传入 RawRectangleF 和颜色,可选线条宽度和样式和线条相同
- var brush = new SolidColorBrush(_d2dRenderTarget, ColorToRaw4(Color.Bisque));
- var rect = new RawRectangleF(10, 10, 100, 100);
- using (brush)
- {
- _d2dRenderTarget.DrawRectangle(rect, brush);
- }
注意 RawRectangleF 的构造函数传入的是左上右下而不是左上角的点和宽度高度
- var rect = new RawRectangleF(left: 10, top: 10, right: 100, bottom: 100);
在没有指定线条宽度是会使用 _d2dRenderTarget
的默认线条宽度,通过下面代码可以设置默认线条宽度
- _d2dRenderTarget.StrokeWidth = 10;
圆角矩形可以使用 DrawRoundedRectangle 方法
- var roundedRectangle = new RoundedRectangle();
- roundedRectangle.Rect = rect;
- roundedRectangle.RadiusX = 10;
- roundedRectangle.RadiusY = 10;
- _d2dRenderTarget.DrawRoundedRectangle(roundedRectangle, brush);
这里的 rect 和 brush 都是上面的代码
填充矩形使用 FillRectangle 方法,这个方法只需要传入矩形和笔刷,稍微更改上面的代码
- _d2dRenderTarget.FillRectangle(rect, brush);
运行代码你可以看到一个填充的矩形
填充的圆角矩形使用 FillRoundedRectangle 方法,这个方法也不需要传入线条宽度等
- _d2dRenderTarget.FillRoundedRectangle(roundedRectangle, brush);
运行上面代码,可以看到填充的圆角矩形
椭圆
画椭圆使用 DrawEllipse 方法,传入椭圆和线条颜色,可选线条宽度和样式
- var brush = new SolidColorBrush(_d2dRenderTarget, ColorToRaw4(Color.Bisque));
- var ellipse = new Ellipse(new RawVector2(100, 100), 10, 10);
- using (brush)
- {
- _d2dRenderTarget.DrawEllipse(ellipse, brush);
- }
运行上面代码可以看到下图
创建椭圆时传入的是圆心和两个方向的大小
填充椭圆使用 FillEllipse 方法,传入的是笔刷,不需要传入线条宽度等
- var brush = new SolidColorBrush(_d2dRenderTarget, ColorToRaw4(Color.Bisque));
- var ellipse = new Ellipse(new RawVector2(100, 100), 10, 10);
- using (brush)
- {
- _d2dRenderTarget.FillEllipse(ellipse, brush);
- }
使用上面代码可以填充椭圆
几何
复杂的几何可以使用 Geometry 绘制
使用 DrawGeometry 方法传入 Geometry 和颜色,可选线条相关设置
- var brush = new SolidColorBrush(_d2dRenderTarget, ColorToRaw4(Color.Bisque));
- var rect = new RawRectangleF(left: 10, top: 10, right: 100, bottom: 100);
- Geometry geometry = new RectangleGeometry(_d2dFactory, rect);
- using(geometry)
- using (brush)
- {
- _d2dRenderTarget.DrawGeometry(geometry, brush);
- }
这里的 Geometry 可选的很多,最支持定制的是 PathGeometry 方法
如使用很多代码画出线条
- var geometry = new PathGeometry(_d2dFactory);
- var geometrySink = geometry.Open();
- geometrySink.BeginFigure(new RawVector2(10,100),FigureBegin.Filled );
- geometrySink.AddLine(new RawVector2(100,100));
- geometrySink.EndFigure(FigureEnd.Closed);
- geometrySink.Close();
在 PathGeometry 使用 Open 方法返回 GeometrySink 可以支持很多绘制,包括组合多个几何
文字
绘制文字需要 SharpDX.DirectWrite.Factory
需要先创建才能使用,注意工厂需要只创建一次
- var factory = new SharpDX.DirectWrite.Factory();
创建工厂可以用来实例文本格式
- var textFormat = new TextFormat(factory, "宋体", 20);
在 TextFormat 构造函数可以传入很多参数,用于绘制
绘制文本需要使用 DrawText 方法,在这个方法传入需要绘制的字符串和文本格式,和绘制的范围和颜色
- var brush = new SolidColorBrush(_d2dRenderTarget, ColorToRaw4(Color.Bisque));
- var factory = new SharpDX.DirectWrite.Factory();
- var textFormat = new TextFormat(factory, "宋体", 20);
- var rect = new RawRectangleF(left: 10, top: 10, right: 100, bottom: 100);
- using(textFormat)
- using (brush)
- {
- _d2dRenderTarget.DrawText("林德熙是逗比", textFormat, rect, brush);
- }
对于 factory 在实际项目请写在初始化的方法,而不是每次进入绘制方法的时候都创建,这个代码将会内存泄露
在画文本需要用到很多参数,用于自己定制,请小伙伴自己玩一下
有了基础的画界面就可以做出好看的界面,如何根据这些简单的方法画出好看的界面请看 WPF 源代码 从零开始写一个 UI 框架
更多请看 SharpDx 系列
使用 SharpDx 绘制很底层,但是绘制性能超级高
2019-10-23-C#-从零开始写-SharpDx-应用-绘制基础图形的更多相关文章
- C# 从零开始写 SharpDx 应用 绘制基础图形
本文告诉大家通过 SharpDx 画出简单的 2D 界面 本文属于 SharpDx 系列 博客,建议从头开始读 本文分为两步,第一步是初始化,第二步才是画界面 初始化 先创建 RenderForm 用 ...
- C# 从零开始写 SharpDx 应用 笔刷
本文告诉大家如何在 SharpDx 里面使用笔刷,包括纯色笔刷.渐变笔刷和图片笔刷 本文属于 SharpDx 系列 博客,建议从头开始读 初始化 本文将会在 C# 从零开始写 SharpDx 应用 初 ...
- C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口
原文:C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http ...
- C# 从零开始写 SharpDx 应用 画三角
原文:C# 从零开始写 SharpDx 应用 画三角 版权声明:博客已迁移到 https://blog.lindexi.com 欢迎访问.如果当前博客图片看不到,请到 https://blog.lin ...
- C# 从零开始写 SharpDx 应用 初始化dx修改颜色
原文:C# 从零开始写 SharpDx 应用 初始化dx修改颜色 版权声明:博客已迁移到 https://blog.lindexi.com 欢迎访问.如果当前博客图片看不到,请到 https://bl ...
- 2019-8-30-C#-从零开始写-SharpDx-应用-笔刷
title author date CreateTime categories C# 从零开始写 SharpDx 应用 笔刷 lindexi 2019-8-30 8:50:0 +0800 2019-6 ...
- 2018-10-20-C#-从零开始写-SharpDx-应用-初始化dx修改颜色
title author date CreateTime categories C# 从零开始写 SharpDx 应用 初始化dx修改颜色 lindexi 2018-10-20 17:34:37 +0 ...
- 2018-8-17-C#-从零开始写-SharpDx-应用-控制台创建-Sharpdx-窗口
title author date CreateTime categories C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口 lindexi 2018-8-17 9:3:3 ...
- 2018-9-30-C#-从零开始写-SharpDx-应用-画三角
title author date CreateTime categories C# 从零开始写 SharpDx 应用 画三角 lindexi 2018-09-30 18:30:14 +0800 20 ...
随机推荐
- 19.SimLogin_case01
什么是模拟登录? 要抓取的信息,只有在登录之后才能查看.这种情况下,就需要爬虫做模拟登录,绕过登录页. cookies和session的区别: cookie数据存放在客户的浏览器上,session数据 ...
- USACO training course Mother's Milk /// DFS(有点意思) oj10120
题目大意: 输入 A B C 为三个容器的容量 一开始A B是空的 C是满的 每一次倾倒只能在 盛的容器满 或 倒的容器空 时才停止 输出当A容器空时 C容器内剩余量的所有可能值 Sample Inp ...
- 关于spring java.lang.IllegalArgumentException: Name for argument type [java.lang.String] 的错误
况描述: web工程在windows环境eclipse下编译部署没有问题,系统升级时需要运维从Git取相应的源码并编译部署到线上机器,部署启动正常没有错误,当访问业务的action时报错,如下. 错误 ...
- 跟我一起使用create-react-app脚手架搭建vw-layout解决方案
之前也是看过大漠的vw适配Vue-cli,我自己写H5,还有使用vue做项目的时候,会搭建大漠博客中的那一套. 现在在github上面,看见了一位博主使用create-react-app也是用vw适配 ...
- [转]Git 常用命令详解
史上最浅显易懂的Git教程 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/ ht ...
- 筛法求欧拉函数(poj2478
求1-n的欧拉函数的值 #include <iostream> #include <cstdio> #include <queue> #include <al ...
- CF1163E Magical Permutation
题意:给定集合,求一个最大的x,使得存在一个0 ~ 2x - 1的排列,满足每相邻的两个数的异或值都在S中出现过.Si <= 2e5 解:若有a,b,c,令S1 = a ^ b, S2 = b ...
- html 引入公共的头部和底部
- Laravel移除Cache-Control
碰到一个问题,网站上线后,需要移除Cache-Control,就是下面这个东西 方案1 失败 参考网址:https://stackoverflow.com/questions/51821563/lar ...
- SPSS分析过程可自动化,你知道吗
SPSS分析过程可自动化,你知道吗 在使用SPSS的过程中,有时候会遇到重复进行相同分析操作的情况,或者分析过程很复杂的情况. 这时候我们多么希望SPSS能够记住上一次的分析步骤,不要让我们重复的去点 ...