幾何實現概觀
本主題描述如何使用 Direct2D 幾何實現,在特定案例中改善應用程式的幾何轉譯效能。
它包含下列區段:
什麼是幾何實現?
Windows 8.1中引進的幾何實現是一種新的繪圖基本類型,可讓Direct2D應用程式輕鬆改善在某些情況下的幾何轉譯效能。 幾何實現是由 ID2D1GeometryRealization 介面表示。
為何要使用幾何實現?
當 Direct2D 轉譯 ID2D1Geometry 物件時,它必須將該幾何轉換成圖形硬體透過稱為鑲嵌的程式瞭解的表單。 一般而言,即使幾何未變更,Direct2D 也必須在繪製的每個框架上鑲嵌幾何。 如果您的 app 會呈現相同的幾何,則重複的鑲嵌代表浪費的計算工作。 快取鑲嵌或甚至幾何的完整點陣化,以及繪製該快取標記法,而不是重複重新鑲嵌,會更有計算效率。
開發人員解決此問題的常見方式是快取幾何的完整點陣化。 特別是,通常會建立新的點陣圖、將幾何點陣化到該點陣圖,然後視需要將該點陣圖繪製到場景。 (此方法會在改善 Direct2D 應用程式的效能的 Geometry 轉譯 一節中說明。) 雖然這種方法非常有計算效率,但有一些缺點:
- 快取的點陣圖會敏感于套用至場景的轉換變更。 例如,縮放點陣化可能會導致明顯的縮放成品。 使用高品質調整演算法減輕這些成品的計算成本可能很高。
- 快取的點陣圖會耗用大量的記憶體,特別是在以高解析度點陣化時。
幾何實現提供替代方式來快取幾何,以避免上述缺點。 幾何實現不是以圖元表示 (,如同完整點陣化) 的情況,而是以數學平面上的點表示。 基於這個理由,它們比縮放和其他操作的完整點陣化更不敏感,而且會耗用較少的記憶體。
使用幾何實現的時機
當您的應用程式轉譯複雜幾何時,請考慮使用幾何實現,其圖形不常變更,但可能會變更轉換。
例如,請考慮顯示靜態地圖但允許使用者放大和縮小的對應應用程式。此應用程式可以受益于使用幾何實現。 由於要轉譯的幾何維持靜態狀態,因此快取它們有助於儲存鑲嵌工作。 但是,由於使用者縮放時會縮放地圖,因此快取完整點陣化並不理想,因為縮放成品。 快取幾何實現可讓應用程式避免重新鑲嵌工作,同時在調整期間維持高視覺品質。
另一方面,請考慮具有持續變更之動畫幾何的 kaleidoscope 應用程式。 此應用程式可能無法受益于使用幾何實現。 由於圖形本身會從框架變更為框架,因此快取其鑲嵌並不實用。 此應用程式的最佳方法是直接繪製 ID2D1Geometry 物件。
建立幾何實現
必須從現有的ID2D1Geometry 物件建立 ID2D1GeometryRealization物件。 若要建立幾何實現,請呼叫 CreateFilledGeometryRealization 方法或 CreateStrokedGeometryRealization 方法,並傳入要實現的 ID2D1Geometry 。
- CreateFilledGeometryRealization 會建立圖形內部的實現:呼叫 FillGeometry所繪製的區域。
- CreateStrokedGeometryRealization 會建立圖形筆劃的實現:呼叫 DrawGeometry所繪製的區域。
這兩種幾何實現都是以 ID2D1GeometryRealization 介面表示。
建立幾何實現時, Direct2D 必須將所提供幾何中的任何曲線壓平到多邊形近似值。 您必須提供扁平化容錯參數給建立方法—這會指定與裝置無關的圖元 (DIP) 的最大距離,介於幾何的 true 曲線與其多邊形近似值之間。 您提供的扁平化容錯越低,產生的幾何實現物件精確度就越高。 同樣地,提供較高的扁平化容錯會產生較低的精確度幾何實現。 請注意,繪製比低精確度幾何實現更昂貴,但可以在引進可見成品之前進一步調整。 如需使用扁平化容錯的指引,請參閱下面的 調整幾何實現 。
注意
幾何實現物件與特定圖形裝置相關聯:它們是裝置相依的資源。
繪圖幾何實現
繪圖幾何實現類似于繪製其他 Direct2D 基本類型,例如點陣圖。 若要這樣做,請呼叫 DrawGeometryRealization 方法,並傳遞要繪製的幾何實現物件,以及要使用的筆刷。 如同其他 Direct2D 繪圖方法,您必須在呼叫 BeginDraw和EndDraw之間呼叫DrawGeometryRealization。
調整幾何實現
幾何實現就像其他 Direct2D 基本類型一樣,遵守裝置內容上的轉換集。 雖然轉譯和旋轉轉換對幾何實現的視覺品質沒有任何影響,但縮放轉換可能會產生視覺成品。
特別是,將足夠的縮放比例套用至任何幾何實現,可能會顯示真實曲線的多邊形近似值。 此處的影像顯示一對橢圓幾何實現, (填滿和筆劃) 太遠。 曲線壓平成品是可見的。
對視覺品質敏感的應用程式應該採取措施,以確保不會發生這種情況。 處理調整的方式取決於應用程式的需求。 以下是數種不同應用程式類型的建議方法。
在未調整的應用程式中使用幾何實現
如果您的應用程式未在幾何實現上執行任何調整,則使用單一壓平容錯只建立一次實現是安全的。 (非縮放轉換不會影響轉譯幾何實現的視覺品質。) 使用 ComputeFlatteningTolerance 函式來計算 DPI 的適當扁平化容錯:
float dpiX, dpiY;
deviceContext->GetDpi(&dpiX, &dpiY);
float flatteningTolerance = D2D1::ComputeFlatteningTolerance(
D2D1::Matrix3x2F::Identity(), // apply no additional scaling transform
dpiX, // horizontal DPI
dpiY // vertical DPI
);
在以少量縮放的應用程式中使用幾何實現
如果您的 app 只能透過少量 (來相應增加幾何,例如,最多 2x 或 3x) ,則可能只是為了建立幾何實現一次而適當,且比例較低的扁平化容錯低於預設值。 這會建立較高的精確度實現,可在產生調整成品之前大幅相應增加;取捨是繪製較高精確度的實現需要更多工作。
例如,假設您知道您的應用程式永遠不會調整幾何實現超過 2 倍。 您的應用程式可以使用一半預設值的扁平化容錯來建立幾何實現,並只要視需要調整實現,最多 2 倍。 使用 ComputeFlatteningTolerance 函式,將 2.0 傳遞為 maxZoomFactor 參數,以計算適當的扁平化容錯:
float dpiX, dpiY;
deviceContext->GetDpi(&dpiX, &dpiY);
float flatteningTolerance = D2D1::ComputeFlatteningTolerance(
D2D1::Matrix3x2F::Identity(), // apply no additional scaling transform
dpiX, // horizontal DPI
dpiY, // vertical DPI
2.0f // realization can be scaled by an additional 2x
);
在大規模調整的應用程式中使用幾何實現
如果您的 app 可以透過 (大量來相應增加或減少幾何,例如,10 倍以上的) ,則適當地處理縮放更為複雜。
對於大部分的應用程式而言,建議的方法是在相應增加場景時,以漸進方式降低壓平容錯來重新建立幾何實現,以維持視覺逼真度並避免調整成品。 同樣地,隨著場景相應減少,應用程式應該以漸進方式較高的扁平化容錯重新建立幾何實現,以避免不可見的浪費轉譯詳細資料。 應用程式不應該在每次調整變更時重新建立幾何實現,因為這麼做會破壞快取鑲嵌工作的目的。 相反地,應用程式應該較不常重新建立幾何實現:例如,每 2 倍增加或縮小規模之後。
每次應用程式中的縮放比例變更以回應使用者互動時,應用程式都可以比較新的縮放比例與幾何實現上次建立 (儲存在 m_lastScale 成員) 中的縮放比例。 如果這兩個值在此案例中關閉 (,則在 2 個) 因數內,則不會採取進一步的動作。 但是,如果兩個值未關閉,則會重新建立幾何實現。 ComputeFlatteningTolerance函式是用來計算適合新尺規的壓平縮小容錯,而m_lastScale會更新為新的小數位數。
此外,應用程式一律會使用比平常用於新小數位數的容錯來建立實現,方法是將值 2 當做 maxZoomFactor 參數傳遞至 ComputeFlatteningTolerance。 這可讓新的幾何實現增加額外因素 2,而不會產生縮放成品。
注意
此處所述的方法可能不適用於所有應用程式。 例如,如果您的 app 允許非常大型的因素快速縮放場景, (例如,如果它包含可從 100% 移至 1,000,000% 的縮放滑杆,則此方法可能會因為重新建立幾何實現每個) 畫面而產生過多的工作。 另一種方法是在使用者完成捏合手勢) 之後,只有在場景縮放的每個操作 (都完成之後,才重新建立幾何實現。