C# 使用 Direct2D 实现斜角效果
Direct2D 是微软新的二维图形 API,可为二维几何图形、位图和文本提供高性能和高质量的呈现。Direct2D 支持硬件加速,无论是绘制速度还是绘制质量,Direct2D 都要比 GDI 和 GDI+ 好很多,不过系统要求 Windows 7 或 Windows Vista SP2 以上。
关于 Direct2D 的一些介绍可以参见微软的帮助《关于 Direct2D》。
Direct2D 内置了很多特效(Effects),包括高斯模糊(Gaussian Blur)、颜色转换(Color Matrix)、阴影(Shadow)等,所有特效的列表可以在这里(英文)看到。利用这些特效可以做出很多效果,组合起来的话,完全可以实现 PhotoShop 中滤镜的功能。
本篇文章就介绍了如何通过组合多种特效,来实现斜角(Bevel)效果。具体的实现使用的是 SharpDX 类库,因为它支持 Direct2D 的内置特效,而微软自己的 WindowsAPICodePackage 至少在 1.1 版还没有支持。SharpDX 使用的是目前最新的开发版 2.5.0,它自带了支持 DirectX 11 和 DirectX 11.1 的两组 DLL,其中前一组 DLL 不支持 Effects,因此要使用支持 DirectX 11.1 的 DLL 才可以。
斜角特效的主要原理来自于 How to Apply Effects to Primitives,这是一篇官方帮助文档,它自带的示例是 C++ 的,而且系统要求是 Windows 8.1 Preview + Microsoft Visual Studio 2013 Preview,因此我将其中核心的部分提取出来,自己编写了一个示例,实现的效果如图 1 所示。
图 1 源位图及其斜角效果对比
斜角效果的实现过程如图 2 所示,利用四个特效进行组合,就可以实现一个比较不错的斜角特效。
图 2 效果实现流程及效果
首先将要应用斜角的图像绘制(或者从外界加载)到一个 SharpDX.Direct2D1.Bitmap1 对象中。示例中的图形是利用 Direct2D 的相关方法绘制的,实际使用中也可以从外界加载。需要注意的是背景必须是透明的,不透明的部分就会产生斜角,否则只会在图片的边缘产生斜角。这个位图被称为“源位图”。
然后为源位图添加一个 SharpDX.Direct2D1.Effects.GaussianBlur 特效,高斯模糊的半径(StandardDeviation 属性)就决定了斜角的尺寸。如图 3 所示,上图的半径是 8,下图的半径是 12,可以明显看到下图的斜角尺寸更大。这里使用高斯模糊特效主要是为了令源图像产生透明度(Alpha)的渐变,以便于下一步进行处理。这里还可以选用 SharpDX.Direct2D1.Effects.Shadow 阴影特效,它同样可以产生透明度的渐变。
图 3 不同高斯模糊半径的对比
接下来,为 GaussianBlur 特效的结果应用 SharpDX.Direct2D1.Effects.PointSpecular 特效,这个特效是斜角效果的关键,这个特效实际上是将源图像当作一个反射面,用源图像的 Alpha 通道表示反射面的高度,然后用一个点光源照射到源图像上,得到的反射结果就是特效的处理结果。这样,上一步高斯模糊得到的 Alpha 渐变,就相当于令源图像产生了一个“凸起”。
PointSpecular 特效有很多参数,包括光源位置、颜色、聚焦、表面缩放比例等等,不同的参数就会产生不同的“斜角”效果。LightPosition 属性是光源的位置,它可以改变斜角的方向,如图 4 所示,上图的光源在上方,下图的光源更加偏右,得到的效果也不同。
图 4 不同光源位置的对比
SurfaceScale 属性是表面的缩放比例,它可以改变斜角的高度,如图 5 所示。
图 5 不同斜角高度的对比
PointSpecular 特效的其它参数也可以对最终的斜角效果产生影响,这就需要自己去测试了。对 PointSpecular 特效的详细解释可进一步参见 Spot-specular lighting effect。
然后,用 SharpDX.Direct2D1.Effects.Composite 特效将源位图和 PointSpecular 特效的结果组合起来。Composite 特效的组合原则很简单,就是根据 Mode 属性的不同,选择输出不同输入的像素。关于该特效具体的组合原则,可以参见 Composite effect。
从图 2 中可以看到,PointSpecular 特效的结果要比源位图更大,而且其中存在一些不需要部分。这里应用一个 Composite 特效,并将 Mode 属性设置为 CompositeMode.SourceIn,这样它的组合原则是 O = DA * S,即输出的像素 = Destination 的 Alpha 值 * Source。其中 Destination 是第一个输入(索引 0,即源位图),Source 是第二个输入(索引 1,即 PointSpecular 特效的结果)。这样就可以将 PointSpecular 特效的结果中不需要的部分剔除掉了。
最后一步,利用 SharpDX.Direct2D1.Effects.ArithmeticComposite 特效将源位图和 Composite 特效的结果组合起来。ArithmeticComposite 特效是“算术组合”特效,它采用公式 $Output_{rgba} = C_1 * Source_{rgba} * Destination_{rgba} + C_2 * Source_{rgba} + C_3 * Destination_{rgba} + C_4$ 来将两个输入位图的像素组合起来,更多信息可以参考 Arithmetic composite effect。
这里组合公式的四个值(由 Coefficients 属性设置) $C_1,C_2,C_3$ 和 $C_4$ 会决定最终的输出效果。这四个值的取值与之前 PointSpecular 特效的属性是非常相关的,在这个例子中,一直采用的一组值是 Vector4(0.0f, 1.0f, 1.0f, 0.0f),如果将这组值改成 Vector4(1.0f, 0.5f, 0.0f, 0.0f),则会如图 6 所示,下边的新值产生的斜角效果明显偏暗。
图 6 不同 Coefficients 属性的对比
如果更换一组 PointSpecular 特效的属性,即除了 SurfaceScale 仍然设置为 5f 以外,其他属性全部取默认值,上面两组 Coefficients 属性得到的结果如图 7 所示,反而是旧值偏亮,新值颜色比较正,但斜角效果不是很明显。
图 7 新的光照条件下不同 Coefficients 属性的对比
总的来说,斜角效果的实现步骤是基本固定的,就是上面的五个步骤。斜角的尺寸、高度和方向也可以很容易确定,尺寸对应于 GaussianBlur 特效的 StandardDeviation 属性,高度对应于 PointSpecular 特效的 SurfaceScale 属性,方向对应于 PointSpecular 特效的 LightPosition 属性。但是斜角特效的颜色则会比较复杂,会由 PointSpecular 特效的 SpecularExponent 属性、SpecularConstant 属性和 ArithmeticComposite 特效的 Coefficients 属性共同决定,而且 LightPosition 属性也会一定程度上影响斜角特效的颜色,这个就需要经验和试验了。
所有源代码和用到的类库都可以在这里下载。
C# 使用 Direct2D 实现斜角效果的更多相关文章
- css实现斜角效果
重点代码: 使用一张图片盖住div,实现斜角效果 .triangle { position: absolute; top:; left:; width: 36px; height: 36px; bac ...
- 使用AS3.0代码实现给图片添加滤镜的模糊与斜角效果
滤镜可应用于任何显示对象(即,从 DisplayObject 类继承的对象), 例如 MovieClip.SimpleButton.TextField 和 Video 对象,以及 BitmapData ...
- AS3.0:给图片添加滤镜模糊与斜角效果
滤镜可应用于任何显示对象(即,从 DisplayObject 类继承的对象), 例如 MovieClip.SimpleButton.TextField 和 Video 对象,以及 BitmapData ...
- 在 WinForm 中使用 Direct2D
在 C# 的 WinForm 应用中,界面的绘制使用的是 GDI+.不过在一些特别的应用中,可能需要用硬件加速来提高绘制的效率.下面就来介绍两种在 WinForm 应用中嵌入 Direct2D 的方法 ...
- 拼图游戏 v1.1
我一直对拼图游戏比较有兴趣,市面上卖的所谓“1000块拼图”也玩过不少,不过玩那个太占地方,后来也不再买了,同时也就萌生了在电脑上玩拼图的想法. 现在虽然有很多拼图游戏,但能大多数只能支持几十或几百块 ...
- 2013年7月份第1周51Aspx源码发布详情
启睿网络信息服务器实例源码 2013-7-5 [ VS2005 ]功能介绍:睿网络信息服务器,QiRui Net Information Services简称QRNIS,该软件前身系KCIS.当前版 ...
- WPF学习之绘图和动画
如今的软件市场,竞争已经进入白热化阶段,功能强.运算快.界面友好.Bug少.价格低都已经成为了必备条件.这还不算完,随着计算机的多媒体功能越来越强,软件的界面是否色彩亮丽.是否能通过动画.3D等效果是 ...
- WPF学习之绘图和动画--DarrenF
Blend作为专门的设计工具让WPF如虎添翼,即能够帮助不了解编程的设计师快速上手,又能够帮助资深开发者快速建立图形或者动画的原型. 1.1 WPF绘图 与传统的.net开发使用GDI+进行绘图不 ...
- 编程实战——电影管理器之界面UI及动画切换
编程实战——电影管理器之界面UI及动画切换 在前文“编程实战——电影管理器之利用MediaInfo获取高清视频文件的相关信息”中提到电影管理器的目的是方便播放影片,在想看影片时不需要在茫茫的文件夹下找 ...
随机推荐
- cf.VK CUP 2015.B.Mean Requests
Mean Requests time limit per test 4 seconds memory limit per test 256 megabytes input standard input ...
- 悦动达人 (多维dp)
悦动达人 Description 一个游戏,在屏幕上有5个格子形成一行,每一秒都会有一个格子闪烁,格子闪烁时你需要保证至少有一只手指在格子上面, 现在我们已经知道第i秒时,第xi个格子会闪烁,我们假设 ...
- hdu 5183. Negative and Positive (哈希表)
Negative and Positive (NP) Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Ja ...
- JSP基本面试的试题
JSP基本面试的试题 1.jsp有哪些内置对象作用分别是什么 答:JSP共有以下9种基本内置组件(可与ASP的6种内部组件相对应): request 用户端请求,此请求会包含来自GET/PO ...
- cas单点登录用户名为中文的解决办法
当用户名为中文时,登录后返回的用户名乱码.解决这个问题只需要在客户端的CAS Validation Filter中添加下配置就行了. <init-param> <param-name ...
- poj 1363 Rails 解题报告
题目链接:http://poj.org/problem?id=1363 题意:有一列火车,车厢编号为1-n,从A方向进站,向B方向出站.现在进站顺序确定,给出一个出站的顺序,判断出站顺序是否合理. 实 ...
- @RequestBody, @ResponseBody 注解详解
简介: @RequestBody 作用: i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对 ...
- XML Parser Error on line 1: 前言中不允许有内容, Mybatis 生成代码
使用用notepad++打开xml文件,然后在菜单“格式”中选择“以UTF-8无BOM格式编码”,保存.
- MapReduce:详解Shuffle过程(转)
/** * author : 冶秀刚 * mail : dennyy99@gmail.com */ Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方.要想理解MapRedu ...
- linux编译中的常见问题
转linux编译中的常见问题 错误提示:Makefile:2: *** 遗漏分隔符 . 停止. 原因makefile中 gcc语句前 缺少一个 tab分割符 错误提示: bash: ./makefil ...