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获取高清视频文件的相关信息”中提到电影管理器的目的是方便播放影片,在想看影片时不需要在茫茫的文件夹下找 ...
 
随机推荐
- Power of Cryptography(用double的泰勒公式可行分析)
			
Power of Cryptography Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onli ...
 - HDU 1025 Constructing Roads In JGShining's Kingdom(求最长上升子序列nlogn算法)
			
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1025 解题报告:先把输入按照r从小到大的顺序排个序,然后就转化成了求p的最长上升子序列问题了,当然按p ...
 - [BZOJ2303][Apio2011]方格染色
			
[BZOJ2303][Apio2011]方格染色 试题描述 Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好,他们想要表格中每个2 × ...
 - django-cms 代码研究(二)bugs?
			
djangocms集成到现有项目中后,发现了几个问题: 1. 现有项目的url匹配失效,下面requests请求被交给djangocms处理了 url(r'^admin/', include(admi ...
 - BeautifulSoup获取指定class样式的div
			
如何获取指定的标签的内容是解析网页爬取数据的必要手段,比如想获取<div class='xxx'> ...<div>这样的div标签,通常有三种办法, 1)用字符串查找方法,然 ...
 - Django  authentication 使用方法
			
转自 : https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
 - makefile中的自动化变量$@,$%,$
			
转自:http://www.2cto.com/os/201302/191344.html makefile中的自动化变量$@,$%,$ 自动化变量 模式规则中,规则的目标和依赖文件名代表了一 ...
 - HTML5 manifest离线缓存
			
一.基本概念 离线缓存是HTML5新引入的技术,能够让你的Web应用程序指定哪些文件可以缓存在本地,使得你的网络断开时依然可以通过本地的缓存来进行访问浏览. 二.使用方法 1. MIME type 声 ...
 - iOS 查看系统字体效果的网页
			
常常需要查看字体的样式,这里推荐一个网页http://iosfonts.com,方便查阅.
 - Java for LeetCode 023 Merge k Sorted Lists
			
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 解 ...