当前位置:网站首页>win10 uwp win2d 离屏渲染
win10 uwp win2d 离屏渲染
2022-08-04 18:37:00 【林德熙】
离屏渲染(Offscreen drawing)是一个不错的科技,在系统有空的时候,提前先画出部分界面。这样在需要直接渲染的时候就可以直接拿出来而不需要等待进行渲染的时候才画出来。
实际上之前我已经写过一篇博客关于 CanvasRenderTarget ,离屏渲染需要使用到 CanvasRenderTarget 。
先来写一个简单的界面,在写之前,请安装 Win2d 。
<Page
x:Class="SairkaDeebowhar.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SairkaDeebowhar"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:win2d="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<win2d:CanvasControl x:Name="CanvasControl" Draw="CanvasControl_OnDraw"></win2d:CanvasControl>
<Button Content="确定" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_OnClick"></Button>
</Grid>
</Page>在点击确定的时候开始进行离屏渲染,因为如果需要让CanvasControl开始渲染需要调用Invalidate,但是调用这个函数不是立刻就渲染,而且在下一个无法控制的时间进行渲染。
所以在 按钮点击的时候可以进行离屏渲染,这时CanvasControl在渲染的时候直接拿按钮点击下去画的就可以。
离屏渲染也叫离线渲染,为了让用户看到炫酷的界面,要求渲染的时间小于 16 毫秒,也就是一秒钟至少60刷新。
渲染的时间是很有限的,如果在渲染中需要耦合计算,那么会让渲染的性能降低。
例如下面的代码,在按钮点击下去的时候,经过很长时间的计算才能知道写入我的名字,如果把代码放在CanvasControl画的时候计算,那么会影响性能。
建议的方法是在按钮点击的时候,在按钮点击那里做计算,这时CanvasControl还可以画其他的东西。
因为我写的是呆磨,很简单,没有让大家看到CanvasControl在空闲的时候做的事情。
private void Button_OnClick(object sender, RoutedEventArgs e)
{
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget offscreen = new CanvasRenderTarget(device, width: 100, height: 100, dpi: 96);
using (CanvasDrawingSession ds = offscreen.CreateDrawingSession())
{
//经过很多时间的计算,才知道需要写我的名字
ds.DrawText("lindexi", new Vector2(10, 10), Colors.Black);
}
_offscreen = offscreen;
// 调用这个函数,会在无法控制的时间调用 CanvasControl_OnDraw ,这时可以发出已经画出来的
CanvasControl.Invalidate();
}
private CanvasRenderTarget _offscreen;在 CanvasControl_OnDraw 就判断 _offscreen 不是空就显示
private void CanvasControl_OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (_offscreen != null)
{
args.DrawingSession.DrawImage(_offscreen,
new Rect(50, 50, _offscreen.Bounds.Width, _offscreen.Bounds.Height));
}
}为什么需要判断_offscreen不是空?因为在xaml加载的时候,就会触发CanvasControl_OnDraw,如果传入DrawImage是一个空,那么会出现参数异常。
通过离屏渲染的图可以使用特效,请看代码
private void Button_OnClick(object sender, RoutedEventArgs e)
{
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget offscreen = new CanvasRenderTarget(device, width: 100, height: 100, dpi: 96);
using (CanvasDrawingSession ds = offscreen.CreateDrawingSession())
{
//经过很多时间的计算,才知道需要写我的名字
ds.DrawText("lindexi", new Vector2(10, 10), Colors.Black);
}
GaussianBlurEffect effect = new GaussianBlurEffect()
{
Source = offscreen,
BlurAmount = 1.0f
};
_offscreen = offscreen;
_effect = effect;
// 调用这个函数,会在无法控制的时间调用 CanvasControl_OnDraw ,这时可以发出已经画出来的
CanvasControl.Invalidate();
}
private CanvasRenderTarget _offscreen;
private GaussianBlurEffect _effect;这时尝试在Win2d显示效果
private void CanvasControl_OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (_offscreen != null)
{
args.DrawingSession.DrawImage(_offscreen,
new Rect(50, 50, _offscreen.Bounds.Width, _offscreen.Bounds.Height));
}
if (_effect != null)
{
args.DrawingSession.DrawImage(_effect);
}
}需要注意,这时的特效的计算是在CanvasControl_OnDraw这时渲染才计算特效。
离线渲染的意思是可以在其他线程渲染,虽然渲染都是在GPU渲染,都是渲染是包括告诉如何渲染和把图片画出来,可以看到如何渲染就可能需要在CPU做很多计算。上面的代码,我经过很多计算才知道需要写 lindexi ,因为本渣叫金鱼,金鱼的意思就是记忆力很差,经常不知道自己叫什么。计算出名字需要的时间是很长的。
如果在按钮按下需要很长时间的计算,那么性能也是很差,这时建议在其他线程做。
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
await Task.Run(() =>
{
// 下面代码可能在 CanvasControl_OnDraw 画出 CanvasRenderTarget 会出现 0x88990012 异常,解决方法请看文章最后
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget offscreen = new CanvasRenderTarget(device, width: 100, height: 100, dpi: 96);
using (CanvasDrawingSession ds = offscreen.CreateDrawingSession())
{
//经过很多时间的计算,才知道需要写我的名字
ds.DrawText("lindexi", new Vector2(10, 10), Colors.Black);
}
GaussianBlurEffect effect = new GaussianBlurEffect()
{
Source = offscreen,
BlurAmount = 1.0f
};
_offscreen = offscreen;
_effect = effect;
});
// 调用这个函数,会在无法控制的时间调用 CanvasControl_OnDraw ,这时可以发出已经画出来的
CanvasControl.Invalidate();
}这就是离屏渲染的使用方法,在其他线程做耗时的渲染,在显示的时候可以快速画出
win2d CanvasRenderTarget vs CanvasBitmap
注意,暗影吉他手告诉我,在 Button_OnClick 的第一句话CanvasDevice device = CanvasDevice.GetSharedDevice();,使用 CanvasDevice.GetSharedDevice() 是错误写法。在CanvasControl_OnDraw里面使用用这个device创建的 CanvasRenderTarget 会弹 0x88990012 异常(Objects used together must be created from the same factory instance)。应该在CreateResources里面得到device。在我的设备上面的代码是可以运行,所以暂时不修改。
多谢暗影吉他手发现问题
边栏推荐
- 如何封装 svg
- Documentary on Security Reinforcement of Network Range Monitoring System (1)—SSL/TLS Encrypted Transmission of Log Data
- July 31, 2022 Summary of the third week of summer vacation
- Literature Review on Involution of College Students
- 谁能解答?从mysql的binlog读取数据到kafka,但是数据类型有Insert,updata,
- #yyds干货盘点# 面试必刷TOP101:链表相加(二)
- Enterprise survey correlation analysis case
- HCIP-R&S By Wakin自用笔记(1)企业网络高级解决方案
- PHP代码审计9—代码执行漏洞
- 【web自动化测试】Playwright快速入门,5分钟上手
猜你喜欢
[Distributed Advanced] Let's fill in those pits in Redis distributed locks.

CAN光纤转换器CAN光端机解决消防火灾报警

PHP代码审计10—命令执行漏洞

什么是网站监控,网站监控软件有什么用?

BigDecimal 使用注意!!“别踩坑”

ECCV 2022 | FPN错位对齐,实现高效半监督目标检测(PseCo)

防火墙基础之防火墙做出口设备安全防护

MySQL安装教程(详细)

The upgrade of capacity helps the flow of computing power, the acceleration moment of China's digital economy

阿里云技术专家秦隆:云上如何进行混沌工程?
随机推荐
DHCP&OSPF组合实验演示(Huawei路由交换设备配置)
股票开户广发证券,网上开户安全吗?
Scala104 - Built-in datetime functions for Spark.sql
EasyCVR调用云端录像API接口返回错误且无录像文件生成,是什么原因?
袋鼠云思枢:数驹DTengine,助力企业构建高效的流批一体数据湖计算平台
CAN光纤转换器CAN光端机解决消防火灾报警
关于使用腾讯云HiFlow场景连接器每天提醒签到打卡
巴比特 | 元宇宙每日必读:微博动漫将招募全球各类虚拟偶像并为其提供扶持...
老电脑怎么重装系统win10
【RTOS训练营】关于上课和答疑
MMDetection 使用示例:从入门到出门
【STM32】入门(五):串口TTL、RS232、RS485
margin 塌陷和重合的理解
curl命令的那些事
ECCV 2022 | FPN错位对齐,实现高效半监督目标检测(PseCo)
mysql cdc 为什么需要RELOAD 这个权限?这个权限在采集数据的过程中的作用是什么?有哪
群友求助,一周没有搞定的需求,3分钟就解决了?
VPC2187/8 电流模式 PWM 控制器 4-100VIN 超宽压启动、高度集成电源控制芯片推荐
基于3D机器视觉的采血试管分拣系统
火灾报警联网FC18中CAN光端机常见问题解答和使用指导