Direct2D 教程 第 4 部分:渐变画笔





5.00/5 (4投票s)
Direct2D 教程:线性与径向渐变画笔
目录
示例代码托管在 Github 上。
引言
在本文中,我们将学习如何在 Direct2D 中使用线性与径向渐变颜色进行绘制。阅读本文的前提是您需要了解如何设置 RenderTarget
。如果您还不清楚 RenderTarget
是什么,请先阅读 RenderTarget 文章,然后再回来阅读本文。
线性渐变
要创建线性渐变画笔,必须定义一个渐变停止数组。一个渐变停止由其位置和颜色组成。第一个渐变停止位置应为 0
,最后一个为 1
。然后调用 CreateGradientStopCollection()
从 stops[]
创建 ID2D1GradientStopCollection
,然后调用 CreateLinearGradientBrush()
创建 ID2D1LinearGradientBrush
。
ComPtr<ID2D1LinearGradientBrush> m_LinearBrush;
void CD2DGradientDlg::CreateLinearGradientBrush()
{
D2D1_GRADIENT_STOP stops[] =
{
{ 0.0f, ColorF(ColorF::Cyan) },
{ 1.0f, ColorF(ColorF::DarkBlue) }
};
ComPtr<ID2D1GradientStopCollection> collection;
HR(m_Target->CreateGradientStopCollection(stops, _countof(stops),
collection.GetAddressOf()));
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props = {};
HR(m_Target->CreateLinearGradientBrush(props, collection.Get(),
m_LinearBrush.ReleaseAndGetAddressOf()));
}
在创建渐变画笔后,我们可以使用它进行绘制。首先,使用 SetStartPoint()
和 SetEndPoint()
设置起始点和结束点。或者,起始点和结束点可以在上面的画笔创建代码中的 D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES
结构中指定。我们的渐变从位置 (0,0
) 开始,到对话框的宽度和高度的位置结束,这意味着渐变是对角线。
void CD2DGradientDlg::DrawLinearGradientRect()
{
auto size = m_Target->GetSize();
m_LinearBrush->SetStartPoint(Point2F(0.0f, 0.0f));
m_LinearBrush->SetEndPoint(Point2F(size.width, size.height));
auto r = RectF(0.0f, 0.0f, size.width, size.height);
m_Target->FillRectangle(r, m_LinearBrush.Get());
}
彩虹线性渐变
接下来,我们将创建一个水平线性渐变,使用彩虹颜色(意味着超过 2 种颜色)。之前的渐变停止被注释掉,并指定了包含 4 种颜色的新的停止。第 2 个和第 3 个停止分别位于 0.33
和 0.66
。这些停止之间的任何颜色都将进行线性插值。
ComPtr<ID2D1LinearGradientBrush> m_LinearBrush;
void CD2DGradientDlg::CreateLinearGradientBrush()
{
/*
D2D1_GRADIENT_STOP stops[] =
{
{ 0.0f, ColorF(ColorF::Cyan) },
{ 1.0f, ColorF(ColorF::DarkBlue) }
};
*/
D2D1_GRADIENT_STOP stops[] =
{
{ 0.0f, ColorF(227.0f / 255.0f, 9.0f / 255.0f, 64.0f / 255.0f, 1.0f) },
{ 0.33f, ColorF(231.0f / 255.0f, 215.0f / 255.0f, 2.0f / 255.0f, 1.0f) },
{ 0.66f, ColorF(15.0f / 255.0f, 168.0f / 255.0f, 149.0f / 255.0f, 1.0f) },
{ 1.0f, ColorF(19.0f / 255.0f, 115.0f / 255.0f, 232.0f / 255.0f, 1.0f) }
};
ComPtr<ID2D1GradientStopCollection> collection;
HR(m_Target->CreateGradientStopCollection(stops, _countof(stops),
collection.GetAddressOf()));
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props = {};
HR(m_Target->CreateLinearGradientBrush(props, collection.Get(),
m_LinearBrush.ReleaseAndGetAddressOf()));
}
在绘制中,代码保持不变,除了将结束点的 y
坐标更改为 0
以创建水平渐变。
m_LinearBrush->SetStartPoint(Point2F(0.0f, 0.0f));
m_LinearBrush->SetEndPoint(Point2F(size.width, 0.0f));
这是我们创建的彩虹渐变。
彩虹线性渐变文本
在本节中,我们将学习如何将渐变画笔应用于文本。在 Direct2D 中,画笔可以应用于接受画笔参数的任何绘图函数。要使用 DrawText
显示文本,必须从 DirectWrite
工厂创建设备无关资源 IDWriteTextFormat
,并使用 CreateTextFormat()
。
ComPtr<IDWriteTextFormat> m_TextFormat;
void CD2DAffineTransformDlg::CreateDeviceIndependentResources()
{
HR(FactorySingleton::GetDWriteFactory()->CreateTextFormat(L"Arial Black",
nullptr, DWRITE_FONT_WEIGHT_ULTRA_BOLD, DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, 40, L"",
m_TextFormat.ReleaseAndGetAddressOf()));
}
要绘制文本,将上述绘图代码中的 FillRectangle()
替换为 DrawText()
。
void CD2DGradientDlg::DrawLinearGradientText()
{
auto size = m_Target->GetSize();
m_LinearBrush->SetStartPoint(Point2F(0.0f, 0.0f));
m_LinearBrush->SetEndPoint(Point2F(size.width, 0.0f));
auto r = RectF(0.0f, 0.0f, size.width, size.height);
m_Target->DrawTextW((LPCTSTR)m_Text, m_Text.GetLength(), m_TextFormat.Get(),
&r, m_LinearBrush.Get());
}
这是渐变文本输出。
径向渐变
在本节中,我们将展示如何创建和使用径向渐变画笔。其创建函数几乎与线性渐变画笔相同,只是函数与径向渐变画笔相关。请注意,在 D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES
中,设置了其中心点。
ComPtr<ID2D1RadialGradientBrush> m_RadialBrush;
void CD2DGradientDlg::CreateRadialGradientBrush()
{
D2D1_GRADIENT_STOP stops[] =
{
{ 0.0f, ColorF(ColorF::Cyan) },
{ 1.0f, ColorF(ColorF::DarkBlue) }
};
ComPtr<ID2D1GradientStopCollection> collection;
HR(m_Target->CreateGradientStopCollection(stops, _countof(stops),
collection.GetAddressOf()));
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES props = {};
props.center = Point2F(50.0f, 50.0f);
HR(m_Target->CreateRadialGradientBrush(props, collection.Get(),
m_RadialBrush.ReleaseAndGetAddressOf()));
}
然后使用径向渐变画笔调用 FillRectangle()
。
void CD2DGradientDlg::DrawRadialGradientRect()
{
auto size = m_Target->GetSize();
auto radius = min(size.width, size.height);
m_RadialBrush->SetRadiusX(radius);
m_RadialBrush->SetRadiusY(radius);
m_Target->FillRectangle(RectF(0.0f, 0.0f, size.width, size.height),
m_RadialBrush.Get());
}
径向渐变文本
要使用径向渐变画笔绘制文本,代码与线性渐变文本相同,只是将径向渐变画笔传递给 DrawText()
。
void CD2DGradientDlg::DrawRadialGradientText()
{
auto size = m_Target->GetSize();
auto radius = min(size.width, size.height);
m_RadialBrush->SetRadiusX(radius);
m_RadialBrush->SetRadiusY(radius);
auto r = RectF(0.0f, 0.0f, size.width, size.height);
m_Target->DrawTextW((LPCTSTR)m_Text, m_Text.GetLength(), m_TextFormat.Get(),
&r, m_RadialBrush.Get());
}
演示代码
文章中显示的所有代码都放在一个单独的演示程序中。要查看特定的渐变演示,只需在 Draw()
中注释和取消注释您想要查看的函数即可。
void CD2DGradientDlg::Draw()
{
m_Target->Clear(ColorF(ColorF::White));
//DrawLinearGradientRect();
//DrawLinearGradientText();
//DrawRadialGradientRect();
DrawRadialGradientText();
}
历史
- 2020 年 9 月 18 日:首次发布