C# 使用 Direct2D 实现斜角效果
2013-07-01 21:57
453 查看
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 属性也会一定程度上影响斜角特效的颜色,这个就需要经验和试验了。
所有源代码和用到的类库都可以在这里下载。
关于 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 属性也会一定程度上影响斜角特效的颜色,这个就需要经验和试验了。
所有源代码和用到的类库都可以在这里下载。
相关文章推荐
- Winform使用C#实现Treeview节点"正在展开..."效果
- 使用Unity实现动态2D水效果
- 在Unity5中使用C#脚本实现UI的下滑、变色、渐隐渐现效果
- C#中使用WeiFenLuo.WinFormsUI.Docking.dll实现窗口停靠效果
- Android相册效果(使用C#和Java分别实现)
- C#编写Windows服务程序 (服务端),客户端使用 消息队列 实现淘宝 订单全链路效果
- 使用C#实现Form窗体的淡入淡出效果
- 源码分析使用Cocos2d-x实现2D光线效果
- C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果
- C# 中实现类似于WORD EXCEL 的动态缩放效果(客户后来说程序使用能产生乐趣)
- 使用QT 2D绘图实现窗体的阴影效果
- C#之使用NotifyIcon实现任务栏托盘菜单,图标闪烁效果及气泡提示 很多程序是只需要后台运行的,甚至不需要自己的应用界面。NotifyIcon提供了程序在任务栏的显示功能 程序下载链接如下
- C#迅雷七窗体特效,使用DWM实现Aero Glass效果
- 使用C#实现WinForm窗体的动画效果
- 使用C#实现WinForm窗体的动画效果
- C#使用Shader实现夜幕降临倒计时的效果
- 使用ScrollView实现滚动效果 出现 ScrollView can host only one direct child (ScrollView只能包裹一个直接子元素)
- 使用HTML5中的Canvas实现2D水池效果
- 一种2D水面效果——使用Flash实现
- 使用C#实现在屏幕上画图效果的代码实例