Người dịch: Nguyễn Văn Khiếu
Email: nvkhieu89@gmail.com , nvkhieu@msdnvietnam.net
Sinh viên lớp CNTN, Khóa 2007
Khoa Toán-Tin học, Đại học khoa học Tự nhiên Tp.HCM
Windows Với C + +
Giới thiệu các Direct2D
Kenny Kerr
Link gốc: http://msdn.microsoft.com/en-us/magazine/dd861344.aspx
Cột này được dựa trên một phiên bản trước khi phát hành (bản dung thử) của Windows 7. Thông tin chi tiết có thể thay đổi.
Nội dung
Architecture And Principals Factories And Resources Render Targets Brushes And Drawing Commands
Với sự ra đời của Windows Vista một vài năm trước đây, nó đã rõ ràng rằng thời đại của giao diện Windows thiết bị đồ họa (GDI) đã được sắp chấm dứt. GDI, ngay cả với sự giúp đỡ của GDI +, đã được hiển thị tuổi tác của mình đặc biệt là khi so sánh với các khả năng đồ họa vượt trội của Windows Presentation Foundation (WPF). Như thể đó là chưa đủ, GDI mất tăng tốc phần cứng của nó trong khi WPF đã lợi dụng sự phổ biến của Direct3D tăng tốc phần cứng.
Tuy nhiên, nếu bạn muốn phát triển hiệu năng cao và các ứng dụng có chất lượng cao, thương mại, bạn vẫn sẽ xem xét để C + + và mã nguồn gốc để cung cấp quyền lực đó. Đó là lý do tại sao số điều kích thích tôi biết thêm về Windows 7 so với việc giới thiệu Direct2D và DirectWrite. Direct2D là một thương hiệu mới đồ họa 2D API được thiết kế để hỗ trợ hầu hết nhu cầu và thị giác phong phú các ứng dụng máy tính để bàn với hiệu suất tốt nhất có thể. DirectWrite cũng là một thương hiệu API mới bổ sung Direct2D và cung cấp phần cứng tăng tốc văn bản, khi được sử dụng với Direct2D, và chất lượng cao và văn bản bố trí rendering với hỗ trợ nâng cao để chữ OpenType và rendering văn bản ClearType.
Trong bài viết này, tôi sẽ tìm hiểu những công nghệ mới và cung cấp cho bạn một ý tưởng về các vấn đề tại sao và làm thế nào bạn có thể bắt đầu sử dụng chúng ngày nay.
Architecture And Principals
Trên Windows XP, GDI và Direct3D đã đứng bình đẳng xa cho tận đến khi hệ điều hành được quan tâm.Những người sử dụng phần chế độ GDI và Direct3D interfaced trực tiếp với hạt nhân của họ-đối chế độ. Kết quả là, cả hai có thể trực tiếp tăng tốc phần cứng, được đưa ra trình điều khiển màn hình phù hợp. Với Windows Vista, Microsoft đã giao trách nhiệm kiểm soát độc quyền phần cứng video để Direct3D. GDI đột nhiên trở thành những di sản đồ họa API được hỗ trợ chủ yếu thông qua phần mềm dựa trên rendering trên đầu trang của Direct3D.
Vì vậy, GDI là chết và Direct3D là trong tương lai, nhưng nơi này không để lại cho chúng tôi và cách thực hiện điều này liên quan đến tất cả các Direct2D và WPF? Vâng, điều đầu tiên cần lưu ý là Direct3D là hiệu quả của Windows đơn vị xử lý đồ họa (GPU) API, cho dù bạn muốn biểu diễn đồ họa hoặc Hotwire GPU của bạn cho sức mạnh tính toán thêm. Bỏ qua OpenGL (mà vẫn còn được hỗ trợ), Direct3D là mức đồ họa thấp nhất cho việc kiểm soát trực tiếp một hình ảnh hiển thị adapter từ một người sử dụng chế độ ứng dụng.
Direct3D là những gì được biết đến như là một chế độ ngay lập tức đồ họa API. Điều này có nghĩa là chỉ đơn giản API cung cấp một lớp mỏng hơn bất kỳ phần cứng đồ họa, cung cấp quyền truy cập vào các tính năng của phần cứng trong khi điền vào một số những khoảng trống phần cứng sẽ được hạn chế một cách nào đó. Mỗi khi bạn muốn render hoặc cập nhật màn hình hiển thị, bạn có hiệu quả cần phải cho Direct3D rằng bạn là về để render, cung cấp các đường ống dẫn Direct3D với tất cả mọi thứ cần thiết để render một khung, và sau đó nói với nó rằng bạn đã hoàn tất, và nó sẽ làm cho hiển thị được cập nhật. Mặc dù Direct3D cung cấp nhiều chức năng tiên tiến 3D, đó là vào bạn để trực tiếp kiểm soát tất cả chúng và nó có tương đối ít 3D nguyên thủy. Không cần phải nói, đây không phải là một nhiệm vụ nhỏ.
Trước khi Windows Vista, Direct3D cũng bao gồm một cấp độ cao cần giữ lại, chế độ đồ họa API đã được xây dựng trên API chế độ ngay lập tức. API này cung cấp hỗ trợ trực tiếp cho các thao tác 3D các đối tượng, được gọi là cảnh-một hệ thống phân cấp của các khung hình với các đối tượng và ánh sáng.Nó được gọi là chế độ giữ lại vì các API giữ lại một bản sao của đồ thị cảnh toàn bộ, do đó, để nói chuyện. Ứng dụng chỉ cần cập nhật các cảnh, và API tự động chính của công việc rendering và cập nhật màn hình hiển thị. Những khó khăn, tất nhiên, là tất cả các chi phí này có một lúc, nếu chi phí quá cao hoặc trí tưởng tượng không khá đáp ứng yêu cầu của bạn, bạn cần phải loại bỏ hoàn toàn kỹ thuật này, dựa vào chế độ ngay lập tức API trực tiếp, và cung cấp các thuật toán hình học của riêng bạn.
Nếu bạn đang ở tất cả quen thuộc với WPF, sau đó mô tả trước đây của một giữ lại, chế độ đồ họa API nên âm thanh khá quen thuộc. Mặc dù Direct3D ngưng giữ lại phương thức của nó- API, WPF bao gồm nội bộ của mình được giữ lại phương thức- API, được gọi là Media Integration Layer (MIL). MIL nằm giữa WPF và Direct3D và giữ lại một bản sao của đồ thị cảnh được xác định bởi WPF, cho phép quản lý mã để tương tác với các đối tượng trực quan trong khi còn lại trong nền, phối hợp với MIL để đảm bảo rằng những thay đổi được phản ánh trong biểu đồ cảnh mà nó vẫn còn giữ lại. Điều này cho phép WPF để cung cấp một kinh nghiệm rất phong phú và tương tác cho các nhà phát triển, nhưng nó đi kèm với một mức giá.
Có tất cả nói rằng, cần khá rõ ràng, nơi đến Direct2D in Direct2D cung cấp hỗ trợ rendering cao cho hình học đơn giản và phức tạp, bitmap, và văn bản được xây dựng trực tiếp ngay trên đầu trang của Direct3D của chế độ đồ họa API cho hiệu năng vô song. Kết quả là một hiệu suất cao và phương pháp thấp trên không cho sản xuất chất lượng cao cho các ứng dụng đồ họa nội dung của bạn. Nó cung cấp một API đơn giản đáng kể cho sản xuất 2D nội dung so với sử dụng Direct3D trực tiếp trong khi thêm trên không ít trong hầu hết trường hợp. Trong thực tế, ngoại trừ một vài hoạt động cụ thể như mỗi nguyên thủy chống răng cưa, bạn muốn được cứng ép để tốt hơn Direct2D với Direct3D. Direct2D tốt hơn nên cũng dễ dàng thích của MIL và Quartz2DE.
Như thể đó là không đủ, thậm chí nó đi xa hơn và cung cấp nhiều tính năng bổ sung, như rendering từ xa qua Remote Desktop Protocol (RDP), phần mềm dự phòng cho server-side rendering hoặc bồi thường cho một sự thiếu phần cứng, hỗ trợ cho rendering ClearType văn bản, và khả năng tương tác tuyệt vời với cả hai GDI và Direct3D. Hãy chỉ nói rằng có không ai trong số này không phận "WPF" vô nghĩa.
Bây giờ hãy xuống để viết một số mã! Để giữ cho các ví dụ tập trung, tôi sẽ sử dụng Template hoạt động thư viện (ATL) và Windows Template Library (WTL) để xử lý tất cả các cửa sổ boilerplate mã cho tôi. Hãy nhớ rằng, Direct2D là về rendering. Nếu bạn muốn nó khiến cho một cửa sổ, bạn vẫn cần phải quản lý các cửa sổ đó. Nếu bạn muốn đầu vào con chuột, bạn vẫn cần phải đáp ứng cửa sổ messagenhư bình thường. Bạn nhận được các ý tưởng hình 1. Chứa một bộ khung của một cửa sổ mà tôi sẽ điền vào trong phần còn lại của bài viết này.
Hình 1 Window Skeleton
#define HR(_hr_expr) { hr = _hr_expr; if (FAILED(hr)) return hr; }
class Window : public CWindowImpl >
{
public:
BEGIN_MSG_MAP(Window)
MSG_WM_DESTROY(OnDestroy)
END_MSG_MAP()
HRESULT Create()
VERIFY(__super::Create(0)); // top-level
VERIFY(SetWindowText(L"Direct2D Sample"));
VERIFY(SetWindowPos(0, // z-order
100, // x
100, // y
600, // pixel width,
400, // pixel height,
SWP_NOZORDER | SWP_SHOWWINDOW));
VERIFY(UpdateWindow());
return S_OK;
}
private:
void OnDestroy()
::PostQuitMessage(1);
};
Factories And Resources
Như với các API khác nhau khác như Direct3D và XmlLite, Direct2D sử dụng một phiên bản nhẹ của đặc tả COM để quản lý vòng đời đối tượng thông qua giao diện bắt nguồn từ IUnknown. Không cần phải khởi tạo thời gian chạy COM và lo lắng về các căn hộ hoặc proxy. Nó chỉ là một quy ước để đơn giản hóa quản lý tài nguyên và cho phép các API và các ứng dụng để lộ các đối tượng và tiêu dùng một cách tốt quy định. Hãy nhớ rằng chỉ vì Direct2D COM sử dụng giao diện không có nghĩa là bạn có thể cung cấp các hiện thực của riêng bạn về những giao diện. Thông thường, các Direct2D sẽ làm việc với hiện thực chỉ riêng của mình. Tôi xin đề nghị bạn nên sử dụng lớp CComPtr ATL của con trỏ thông minh để quản lý các giao diện con trỏ, như tôi làm trong các ví dụ trong bài viết này.
Mỗi ứng dụng Direct2D bắt đầu bằng cách tạo ra một đối tượng factory. Chức năng trả về một D2D1CreateFactory thực hiện các giao diện ID2D1Factory:
CComPtr factory;
HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory));
Tất nhiên, trước khi bạn có thể sử dụng bất kỳ các loại, bạn cần bao gồm d2d1.h, tập tin tiêu đề Direct2D, mà tuyên bố Direct2D giao diện khác nhau, cấu trúc, và hằng số cũng như chức năng D2D1CreateFactory. D2d1.lib tập tin được cung cấp để nhập khẩu chức năng D2D1CreateFactory.Các tiêu đề d2d1helper.h cũng cung cấp nhiều chức năng rất hữu ích và các lớp học để chỉ đơn giản là việc sử dụng các Direct2D từ C + +. Tôi thường bao gồm Direct2D trong một dự án bằng cách thêm các chỉ thị sau trong tiêu đề tiền biên dịch của dự án:
#include
#pragma comment(lib, "d2d1.lib")
Như tôi đã đề cập, Direct2D không dựa vào COM, nhưng các thông số đầu tiên D2D1CreateFactory có thể dẫn bạn tin rằng bằng cách khác. Các định nghĩa enum D2D1_FACTORY_TYPE cả D2D1_FACTORY_TYPE_SINGLE_THREADED và D2D1_FACTORY_TYPE_MULTI_THREADED hằng, nhưng không có gì để làm với COM apartments và không giả định bất kỳ lôi cuốn nguy hiểm. Các D2D1_FACTORY_TYPE_SINGLE_THREADED hằng chỉ định rằng đối tượng factory, cũng như bất kỳ và tất cả các đối tượng bắt nguồn từ factory đó, có thể được truy cập bằng một sợi chỉ có duy nhất một lúc. Đối tượng được tạo trong cách này sẽ cung cấp hiệu năng tốt nhất để truy cập đơn-ren, tránh bất kỳ tuần tự hóa không cần thiết vào và ra khỏi các cuộc gọi rendering. Các D2D1_FACTORY_TYPE_MULTI_THREADED hằng, mặt khác, xác định rằng đối tượng factory, cũng như bất kỳ và tất cả các đối tượng bắt nguồn từ factory đó, có thể được truy cập bởi nhiều luồng đồng thời. Direct2D cung cấp đồng bộ hóa cần thiết với sự khớp nhau tính tham khảo. Điều này là hữu ích cho rendering (biểu diễn) đến các mục tiêu khác nhau, đồng thời trong khi chia sẻ tài nguyên nhất định. Hãy nhớ rằng đây là cụ thể xử lý song song với CPU, và hướng dẫn được gửi tới GPU vẫn có thể được theo thứ tự và cuối cùng song song độc lập.
OK, do đó, các factory sử dụng cho các đối tượng là những gì? Vâng, đó là trách nhiệm cho việc tạo ra tất cả các thiết bị-tài nguyên độc lập, chủ yếu hình học, cũng như tạo ra khiến các mục tiêu đại diện cho các thiết bị. Các mục tiêu sau đó làm cho có trách nhiệm tạo thiết bị, nguyên phụ thuộc. Sự khác biệt giữa các thiết bị phụ thuộc và các thiết bị độc lập là nguồn lực quan trọng cho việc sử dụng Direct2D cách chính xác. Một trong những lợi ích của một giữ lại, chế độ đồ họa API như WPF là lớp trung gian giữa phần cứng và mô hình lập trình nói chung sẽ lo kịch bản nơi mà các thiết bị hiển thị có thể bị mất. Điều này có thể xảy ra vì nhiều lý do. Độ phân giải có thể thay đổi trong nền, một bộ điều hợp hiển thị có thể được gỡ bỏ như khi một người dùng undocks một máy tính xách tay, một máy tính để bàn phiên kết nối từ xa có thể bị mất, và như vậy. An ngay lập tức-chế độ đồ họa API như Direct2D cần đưa vào tài khoản các sự kiện này. Tất nhiên, những lợi ích là nguồn lực được sử dụng để render đến một thiết bị đặc biệt có thể được thể chất hiện nay trên thiết bị và do đó cung cấp hiệu năng tốt hơn nhiều.
Đối với những lý do này, nó là tốt thực hành để tách biệt rõ ràng việc tạo ra các thiết bị-tài nguyên độc lập từ thiết bị, tài nguyên phụ thuộc. Để bố trí này, trong hình 2 tôi thêm hai phương pháp để lớp cửa sổ từ hình 1.
Hình 2: Tạo Device-độc lập và thiết bị-phụ thuộc nguyên Separately
HRESULT CreateDeviceIndependentResources()
HRESULT hr;
HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_factory));
// TODO: Create device-independent resources here
HRESULT CreateDeviceResources()
// TODO: Create device resources here
Tôi sẽ kích thích chúng ra trong các phần sắp tới, nhưng lúc này, bạn có thể gọi từ CreateDeviceIndependentResources Tạo phương thức của lớp Window vì phương thức-tài nguyên độc lập cần được tạo ra chỉ một lần. CreateDeviceResources sẽ, tuy nhiên, được gọi là theo yêu cầu để tạo ra nguồn điện khi cần thiết. Bạn cũng sẽ muốn thêm vào biến thành viên m_factory như sau:
CComPtr m_factory;
Render Targets
Một render mục tiêu được sử dụng để đại diện cho một thiết bị và là chính nó phụ thuộc vào các thiết bị nằm bên dưới. Với một render mục tiêu, bạn có thể tạo nguồn lực khác nhau, như chổi quét, và thực hiện các hoạt động vẽ thực tế. Direct2D hỗ trợ một số loại khác nhau của render các mục tiêu. Nếu bạn đang xây dựng một ứng dụng Direct2D từ đầu, bạn có thể tạo ra một mục tiêu để render render nội dung vào một cửa sổ (HWND). Bạn cũng có thể tạo ra một mục tiêu để render render đến một ngữ cảnh thiết bị GDI (DC), hoặc đến một đồ họa DirectX Cơ sở hạ tầng (DXGI) bề mặt để sử dụng trong một ứng dụng Direct3D. Bạn thậm chí có thể tạo ra một mục tiêu khiến cho nhiều loại tài nguyên bitmap cho off-screen.
Factory sản xuất các phương pháp khác nhau được cung cấp cho việc tạo ra các loại khác nhau của render các mục tiêu. Các phương pháp chính họ là khá rõ ràng. Ví dụ, phương pháp CreateHwndRenderTarget tạo ra một cửa sổ render mục tiêu, và phương pháp CreateDxgiSurfaceRenderTarget tạo ra một bề mặt DXGI render mục tiêu. Để khiến cho cửa sổ, bạn sẽ cần phải cập nhật các phương pháp CreateDeviceResources để tạo ra cửa sổ render mục tiêu. Tại rất tối thiểu, nó có thể trông giống như hình 3. Hãy nhớ rằng những mẫu này không phải là DPI-nhận thức, nhưng đó là một chủ đề cho bài khác.
Hình 3: Tạo cửa sổ Render Target
if (0 == m_target)
CRect rect;
VERIFY(GetClientRect(&rect));
D2D1_SIZE_U size = D2D1::SizeU(rect.Width(), rect.Height());
HR(m_factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(m_hWnd, size), &m_target));
Bạn cũng sẽ muốn thêm vào biến thành viên m_target:
CComPtr m_target;
Phương pháp CreateDeviceResources tạo ra nguồn tài nguyên thiết bị chỉ khi render mục tiêu chưa được tạo ra, hoặc, như bạn sẽ thấy ngay, nếu điện thoại bị mất và khiến mục tiêu cần phải được tái tạo.
Tham số đầu tiên Phương pháp CreateHwndRenderTarget là thực sự của các loại D2D1_RENDER_TARGET_PROPERTIES. Tham số này được phổ biến đến tất cả các chức năng render tạo ra mục tiêu. Chức năng RenderTargetProperties thực sự là một chức năng helper được định nghĩa trong file header d2d1helper.h. Nó đại diện cho một mẫu chung cho việc khởi tạo nhiều cấu trúc dữ liệu được sử dụng bởi Direct2D và giúp đơn giản hoá mã của bạn đáng kể. Chức năng helper RenderTargetProperties có tham số với giá trị mặc định để khởi tạo tài khoản cho phổ biến nhất của các cơ cấu kết quả. Bạn có thể ghi đè những giá trị này để điều chỉnh các định dạng điểm ảnh và thông tin độc lập, cũng như các đặc tính bổ sung của render mục tiêu, chẳng hạn như việc để lực lượng phần cứng hoặc phần mềm dựa trên rendering và liệu để hỗ trợ GDI interop.
Tương tự như vậy, tham số thứ hai của CreateHwndRenderTarget thực sự là một cấu trúc D2D1_HWND_RENDER_TARGET_PROPERTIES và cung cấp thông tin cụ thể cho cửa sổ.
Có tạo ra khiến mục tiêu, tôi bây giờ có thể làm một số rendering thực tế. Để làm điều này, thêm một phương thức Render cho lớp cửa sổ với các phác thảo cơ bản được hiển thị trong hình 4.
Hình 4 Rendering
void Render()
if (SUCCEEDED(CreateDeviceResources()))
if (0 == (D2D1_WINDOW_STATE_OCCLUDED & m_target->CheckWindowState()))
m_target->BeginDraw();
m_target->SetTransform(D2D1::Matrix3x2F::Identity());
m_target->Clear(D2D1::ColorF(D2D1::ColorF::Red));
// TODO: add drawing code here
if (D2DERR_RECREATE_TARGET == m_target->EndDraw())
DiscardDeviceResources();
Logic ở đây là khá quan trọng bởi vì nó rất hiệu quả cho phép cập nhật, nhờ sự tái sử dụng các nguồn tài nguyên thiết bị và bởi vì nó phải dự liệu bị mất phương thức. Phương pháp Render bắt đầu bằng cách gọi phương pháp CreateDeviceResources rằng tôi đã được mô tả. Tất nhiên nó sẽ không phải làm bất cứ điều gì nếu các nguồn tài nguyên thiết bị vẫn có sẵn. Như một tối ưu hóa, tôi kiểm tra nhà nước cửa sổ để đảm bảo rằng nó không phải là bít kín, mà chỉ là một thuật ngữ ưa thích mà chỉ ra cửa sổ là tắc nghẽn từ xem và bất kỳ bức tranh sẽ chỉ được một sự lãng phí quý giá tài nguyên CPU và GPU. Mặc dù điều này hiếm khi xảy ra khi các Desktop Window Manager (DWM) là xử lý các thành phần máy tính để bàn, nó không đau và là một tối ưu hóa tốt đẹp khi máy tính để bàn là thành phần vô hiệu hoá.
Bản vẽ phải được thực kẹp giữa các cuộc gọi đến render BeginDraw mục tiêu và phương pháp EndDraw. Hầu hết các mục tiêu của phương pháp render có một kiểu trả về void. Kể từ khi hoạt động vẽ được batched, bất kỳ sự thất bại sẽ được phát hiện chỉ khi các hoạt động vẽ đang đỏ ửng và kết xuất với điện thoại. Phương pháp EndDraw như vậy, có một loại HRESULT trở lại. Nó dùng D2DERR_RECREATE_TARGET hằng để chỉ ra rằng render mục tiêu đã được vô hiệu và phải được tái tạo. Sau đó các cuộc gọi DiscardDeviceResources, mà cần phải phát hành tất cả các nguồn tài nguyên thiết bị.
void DiscardDeviceResources()
m_target.Release();
Tôi nên cũng chỉ đề cập đến các cuộc gọi đến render SetTransform mục tiêu và phương pháp Clear.SetTransform trong trường hợp này chỉ ra rằng bất kỳ hoạt động tiếp theo bản vẽ nên được chuyển bằng cách sử dụng một ma trận sắc. Tất nhiên, một ma trận danh tính thực sự là không có bản dịch nào cả, vì thế này thì chỉ cần đảm bảo rằng các hoạt động vẽ sử dụng không gian chữ phối hợp trong thiết bị điểm ảnh độc lập. Bạn có thể, tuy nhiên, gọi SetTransform liên tục trong suốt rendering để thay đổi các biến đổi trên bay. Phương pháp đơn giản Clear xóa vùng vẽ bản vẽ cho các hoạt động tiếp theo và trong trường hợp này làm cho nó màu đỏ.
Tất nhiên, nếu bạn đã tạo ra cửa sổ vào thời điểm này, bạn sẽ thấy cửa sổ vẫn còn trắng. Vẫn cần một cái gì đó để gọi phương thức Render để cập nhật hiển thị. Đối với điều này, bạn có thể thêm xử lý thông điệp WM_PAINT cho cửa sổ và messageWM_DISPLAYCHANGE. Bạn có thể làm điều đó bằng cách thêm các bản đồ sau đây để thông báo:
MSG_WM_PAINT(OnPaint)
MSG_WM_DISPLAYCHANGE(OnDisplayChange)
Đáp ứng với WM_PAINT là hiển nhiên, nhưng xử lý WM_DISPLAYCHANGE là kém phần quan trọng để đảm bảo rằng cửa sổ là đúng vẽ lại nên độ phân giải màn hình hoặc thay đổi độ sâu màu (xem hình 5).
Hình 5 Repainting
void OnPaint(CDCHandle /*dc*/)
PAINTSTRUCT paint;
VERIFY(BeginPaint(&paint));
Render();
EndPaint(&paint);
void OnDisplayChange(UINT /*bpp*/, CSize /*resolution*/)
Chú ý rằng DC trở lại bởi BeginPaint là không được sử dụng ở tất cả. Tạo cửa sổ bây giờ sẽ kết quả trong một cửa sổ với một nền đỏ, như mong đợi. Thay đổi kích thước cửa sổ sẽ Tuy nhiên, tiết lộ một số nhấp nháy. Điều gì đang xảy ra là nền cửa sổ vẫn còn tự động bị xóa bằng cách sử dụng chổi quét cửa sổ nền lớp vì việc xử lý mặc định của thư WM_ERASEBKGND. Để tránh điều này, chỉ cần xử lý các thông điệp này và trở về TRUE trong phương pháp OnEraseBackground để cho biết rằng bạn sẽ chăm sóc giải phóng nền cửa sổ. Bây giờ bạn có thể thay đổi kích thước cửa sổ trong khi tránh bất kỳ nhấp nháy.
Trong khi bạn đang ở đó, có thể bạn sẽ muốn xử lý các thay đổi kích thước cửa sổ. Để làm như vậy, thêm một handler message thông báo cho cửa sổ WM_SIZE, như sau:
MSG_WM_SIZE (OnSize)
Các OnSize xử lý sau đó đơn giản chỉ cần thông báo cho render mục tiêu rằng kích thước đã thay đổi:
void OnSize(UINT /*type*/, CSize size)
if (0 != m_target)
if (FAILED(m_target->Resize(D2D1::SizeU(size.cx, size.cy))))
VERIFY(Invalidate(FALSE));
Nếu nó không thay đổi kích cỡ, bạn chỉ cần loại bỏ các nguồn tài nguyên thiết bị, và họ sẽ tự động được tái tạo trong thời gian tới cửa sổ là trả lại. Lưu ý về phương pháp Resize chấp nhận kích thước mới trong thiết bị điểm ảnh từ messageWM_SIZE truyền kích thước của khách hàng tại khu vực điểm ảnh. Mặc dù Direct2D sử dụng một thiết bị độc lập, phối hợp hệ thống, cửa sổ render mục tiêu cuối cùng hiểu rằng nó cần bản đồ để pixel thiết bị.
Brushes And Drawing Commands
Để làm bất cứ vẽ có ý nghĩa, bạn sẽ muốn tạo ra một số chổi quét. Bạn sẽ cần cọ vẽ hình dáng khác nhau hình học cũng như các văn bản. chổi quét rơi trong chủng loại thiết bị, nguyên phụ thuộc, vì vậy tạo của họ nên đi vào phương pháp CreateDeviceResources. Như bạn có thể mong đợi, Direct2D cung cấp chổi quét rắn và bitmap cũng như tuyến tính và chổi quét gradient xuyên tâm. Để tạo một chổi quét màu, bạn có thể thêm quyền phương pháp gọi sau đây sau khi tạo các render mục tiêu.Bằng cách đó, nó được tái tạo chỉ khi render mục tiêu là tạo lại.
HR(m_target->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_brush));
Hãy nhớ cũng phát hành các brush trong phương pháp DiscardDeviceResources như sau:
m_brush.Release ();
Bạn cũng sẽ muốn thêm vào biến thành viên m_brush như sau:
CComPtr m_brush;
Hình 7 Vẽ cơ bản
Bây giờ bạn có thể thêm các lệnh vẽ một số phương pháp cơ bản để Render giữa Clear và EndDraw phương pháp. Các mã trong hình 6 tạo ra một vòng tròn với một đường chéo qua nó. Mặc dù tôi sẽ để lại một cuộc thảo luận hoàn toàn của chổi quét cho một bài báo trong tương lai, đó là đáng nói đến là Direct2D cho phép bạn hiệu quả thay đổi màu sắc của một chổi quét trong khi rendering, obviating sự cần thiết để tạo ra chổi quét cho nhiều màu sắc khác nhau.
Hình 6 Circle với đường chéo Line
m_target->DrawLine(D2D1::Point2(10.0f, 10.0f), // start
D2D1::Point2(200.0f, 200.0f), // end
m_brush,
10.0f); // stroke width
const D2D1_POINT_2F center = D2D1::Point2(105.0f, 105.0f);
const D2D1_ELLIPSE ellipse = D2D1::Ellipse(center,
95.0f, // radius X
95.0f); // radius Y
m_target->DrawEllipse(&ellipse,
5.0f); // stroke width
Như tôi đã đề cập, Direct2D sử dụng một thiết bị độc lập, phối hợp các tọa độ hệ thống để bày tỏ sự không nhất thiết là bản đồ để hiển thị điểm ảnh, mà sẽ tôn vinh các thiết lập DPI cho thiết bị mục tiêu hình 7. Cho thấy kết quả của các lệnh vẽ.
Mặc dù tôi đã sử dụng chỉ một chổi quét mờ, bạn cũng có thể chỉ định một giá trị alpha khi tạo chổi quét và pha trộn alpha tâm đến nội dung của bạn.
Thật không may, tôi đã hoàn toàn hết không gian, nhưng bây giờ bạn cần phải có một ý tưởng tốt về tiềm năng mà Direct2D và DirectWrite sẽ có trên các ứng dụng bản địa đi về phía trước. Có nhiều lý do khác để yêu thích những công nghệ mới mà tôi hy vọng, để khai thác vào trong một cột sắp tới, bao gồm cả hình học phong phú và hoạt động cũng như tất cả các khả năng của DirectWrite.Trong khi chờ đợi, bắt đầu thử nghiệm với Direct2D. Tôi chắc rằng bạn sẽ tìm thấy nó ấn tượng.
Nhìn thấy: Direct2D Rendering
Nhiều người sẽ bị cám dỗ để tương hiệu suất của Direct2D và Direct3D ứng dụng. Đây là một cái gì đó của một cam táo để so sánh trong đó Direct2D cung cấp một tập các nguyên thủy hơn nhiều so sánh với 2D khác rendering API như GDI / GDI + hay WPF. Nó cũng là đơn giản hơn nhiều để sử dụng. Tuy nhiên, nó có thể gây ngạc nhiên cho một số khách hàng rằng Direct2D có thể thực sự ra-thực hiện một ứng dụng đơn giản, hoặc ngây thơ, Direct3D trong một số kịch bản khác nhau. Ví dụ, Direct2D có thể tốt hơn một ứng dụng ngây thơ Direct3D khi vẽ số lượng lớn các đường với màu sắc khác nhau hoặc khi trộn liên tục từ một bitmap.
Chìa khóa để làm thế nào Direct2D làm này là để nhận ra rằng Direct2D không duy trì một mối quan hệ giữa 1:01 một yêu cầu cấp bản vẽ để nó và các vấn đề nguyên thủy mà nó để Direct3D. Trong thực tế, Direct2D cố gắng tập hợp các yêu cầu của mình cho Direct3D trong một số cách khác nhau.
Reduced Vertex Buffer Mapping
Xem xét một ứng dụng Direct3D ngây thơ. Nó tạo ra một bộ đệm đỉnh, bản đồ nó, writes hình học của mình trong bộ đệm, bỏ bản đồ nó và rút ra nó. Vấn đề với phương pháp tiếp cận này là nếu đệm đỉnh vẫn còn được sử dụng bởi GPU khi yêu cầu tiếp theo bản đồ đến, CPU sẽ phải đứng cho đến khi GPU được thực hiện với nó, và sau đó nó chỉ có thể được ánh xạ trở lại vào ứng dụng bộ nhớ. Điều này có thể làm giảm đáng kể hiệu suất của ứng dụng.
Direct2D giải quyết vấn đề này bằng cách rời khỏi đệm đỉnh ánh xạ vào bộ nhớ hình học nguyên thủy và tích lũy những cuộc 'vào nó. Chỉ khi bộ đệm đỉnh đầy, hoặc áp dụng các cuộc gọi Flush hoặc EndDraw, không Direct2D sau đó gửi các cuộc gọi rút xuống vào Direct3D. Điều này giảm thiểu số lượng các gian hàng GPU bởi vì số lượng các bản đồ và bỏ cuộc gọi bản đồ sẽ giảm đáng kể.
Coalescing Draw Calls
Ngay cả sau khi hình học được phép tích lũy trong bộ đệm đỉnh, một ứng dụng Direct3D ngây thơ sẽ phải phát hành một lời kêu gọi hòa để Direct3D cho hầu hết các cuộc gọi Direct2D hòa. Hãy xem xét hai hình chữ nhật khác nhau rendered với màu sắc khác nhau, mỗi màu sắc có thể yêu cầu bằng văn bản khác nhau dữ liệu đổ bóng hằng số đại diện cho nó. Mỗi lần các dữ liệu được cập nhật liên tục đổ bóng, một hòa gọi khác nhau cần phải được phát hành.
Vì vậy, miễn là hằng số khác không thay đổi. Ví dụ, cùng loại chổi quét được sử dụng liên tục. Hoặc, nếu chổi quét bitmap, các bitmap đầu vào cùng được sử dụng thống nhất.Direct2D có thể sử dụng shaders đỉnh của nó để tiếp tục tích lũy dữ liệu đổ bóng liên tục và sau đó ra một trong Direct3D hòa gọi cho một số lượng lớn Direct2D hòa các cuộc gọi.
Out-of-Order Text Rendering
Các văn bản Direct2D rendering đường ống được thực thi hoàn toàn bằng phần cứng, thông qua ba giai đoạn. Giai đoạn đầu viết các glyphs vào một kết cấu, giai đoạn kế tiếp xuống các mẫu glyphs và giai đoạn cuối cùng thực hiện một loại hình hoạt động rõ ràng-lọc để chuyển các văn bản để render mục tiêu. Một ứng dụng ngây thơ cũng làm cho mỗi giai đoạn tuần tự, việc thay đổi mục tiêu render ba lần và ban hành một lời kêu gọi hòa để di chuyển dữ liệu giữa mỗi kết cấu. Direct2D sẽ làm cho nguyên thủy văn bản ra khỏi trật tự với nguyên thủy khác. Nó sẽ lần đầu tiên tích lũy một số lượng lớn glyphs. Sau đó xuống lấy mẫu tất cả chúng và pha trộn những tập cuối cùng của glyphs nhằm với nguyên thủy hình học khác đã ban hành để Direct2D. Coalescing các rendering văn bản theo cách này làm giảm số lần các render thay đổi mục tiêu cũng như số lượng của nhà nước nói chung Direct3D thay đổi thiết bị để render các văn bản, ngay cả khi đang Interleaved nguyên thủy khác với các cuộc gọi Direct2D rendering văn bản.
Bằng cách kết hợp đệm đỉnh Trạm trộn, vẽ coalescing gọi, và out-of-rendering thứ tự của văn bản, Direct2D có khả năng đạt được hiệu suất rendering rằng sẽ yêu cầu số tiền rộng rãi của các nỗ lực phát triển cho phù hợp nếu ứng dụng được thay vì trực tiếp nhắm mục tiêu Direct3D.
- Mark Lawrence, Kỹ sư cao cấp phát triển phần mềm, Microsoft.
Biệt danh: Khiếu Nobita, BunhiacopKhiếu
Khiếu Nguyễn
Gifted Student
Faculty of Mathematics and Computer Science
University of Science, HCM City