程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 使用 Direct2D 實現斜角效果

C# 使用 Direct2D 實現斜角效果

編輯:C#入門知識

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 屬性也會一定程度上影響斜角特效的顏色,這個就需要經驗和試驗了。

所有源代碼和用到的類庫都可以在這裡下載。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved