效果

什么是 Direct2D 效果?

可以使用 Direct2D 将一个或多个高质量效果应用于图像或一组图像。 效果 API 基于 Direct3D 11 构建,并利用 GPU 功能进行图像处理。 可以在效果图中链接效果,并组合或混合效果的输出。

Direct2D 效果执行图像任务,例如更改亮度、使图像去饱和或创建投影。 效果可以接受零个或多个输入图像,公开控制其操作的多个属性,并生成单个输出图像。

每个效果创建由单个转换组成的内部转换图。 每个转换表示单个图像操作。 转换main目的是容纳为每个输出像素执行的着色器。 这些着色器可以包括像素着色器、顶点着色器、GPU 的混合阶段和计算着色器。

可以使用自定义效果 API 创建的 Direct2D内置效果自定义效果 都以这种方式工作。

有一系列来自类别的 内置效果 ,如此处的类别。 有关完整列表,请参阅 内置效果 部分。

你可以将效果应用于任何位图,包括:Windows 图像处理组件 (WIC) 加载的图像、Direct2D 绘制的基元、来自DirectWrite的文本或 Direct3D 渲染的场景。

使用 Direct2D 效果,可以编写可用于应用程序的效果。 自定义效果框架允许使用 GPU 功能,例如像素着色器、顶点着色器和混合单元。 还可以在自定义效果中包含其他内置或自定义效果。 用于生成自定义效果的框架与用于创建 Direct2D 内置效果的框架相同。 Direct2D 效果创作 API 提供了一组用于创建和注册效果的接口。

更多效果主题

本主题的其余部分介绍了 Direct2D 效果的基础知识,例如将效果应用于图像。 此处的表包含有关效果的其他主题的链接。

主题 说明
效果着色器链接
Direct2D 使用称为效果着色器链接的优化,它将多个效果图呈现传递合并到一个通道中。
自定义效果
演示如何使用标准 HLSL 编写自己的自定义效果。
如何使用 FilePicker 将图像加载到 Direct2D 效果中
演示如何使用 Windows::Storage::P ickers::FileOpenPicker 将图像加载到 Direct2D 效果中。
如何将 Direct2D 内容保存到图像文件
本主题演示如何使用 IWICImageEncoderID2D1Image 的形式将内容保存到 JPEG 等编码图像文件。
如何将效果应用于基元
本主题演示如何对 Direct2DDirectWrite基元应用一系列效果。
控制效果图中的精度和数值剪裁
使用 Direct2D 呈现效果的应用程序必须小心,才能在数值精度方面达到所需的质量和可预测性级别。

将效果应用于图像

可以使用 Direct2D 效果 API 将转换应用于图像。

注意

此示例假定已创建 ID2D1DeviceContextIWICBitmapSource 对象。 有关创建这些对象的详细信息,请参阅如何使用 FilePicker 和设备和设备上下文将图像加载到 Direct2D 效果中。

  1. 声明 ID2D1Effect 变量,然后使用 ID2DDeviceContext::CreateEffect 方法创建位图源效果。

        ComPtr<ID2D1Effect> bitmapSourceEffect;
    
        DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D1BitmapSource, &bitmapSourceEffect));
    
  2. 使用 ID2D1Effect::SetValue 将 BitmapSource 属性设置为 WIC 位图源。

            DX::ThrowIfFailed(m_bitmapSourceEffect->SetValue(D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE, m_wicBitmapSource.Get()));
    
  3. 声明 ID2D1Effect 变量,然后创建 高斯模糊 效果。

        ComPtr<ID2D1Effect> gaussianBlurEffect;
    
        DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D1GaussianBlur, &gaussianBlurEffect));
    
  4. 设置输入以从位图源效果接收图像。 设置 SetValue 方法和标准偏差属性的模糊量。

        gaussianBlurEffect->SetInputEffect(0, bitmapSourceEffect.Get());
    
        DX::ThrowIfFailed(gaussianBlurEffect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, 6.0f));
    
  5. 使用设备上下文绘制生成的图像输出。

        m_d2dContext->BeginDraw();
    
        m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
    
        // Draw the blurred image.
        m_d2dContext->DrawImage(gaussianBlurEffect.Get());
    
        HRESULT hr = m_d2dContext->EndDraw();
    

    与其他 Direct2D 呈现操作一样,必须在 ID2DDeviceContext::BeginDrawEndDraw 调用之间调用 DrawImage 方法。 DrawImage 可以拍摄图像或效果的输出,并将其呈现到目标图面。

空间转换

Direct2D 提供可在 2D 和 3D 空间中转换图像以及缩放的内置效果。 缩放和变换效果提供各种质量级别,例如:最近邻、线性、立方、多样本线性、各向异性和高质量立方体。

注意

各向异性模式在缩放时生成 mipmap,但是,如果在输入到转换的效果上将 Cached 属性设置为 true,则不会每次为足够小的图像生成 mipmap。

ComPtr<ID2D1Effect> affineTransformEffect;
DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D12DAffineTransform, &affineTransformEffect));

affineTransformEffect->SetInput(0, bitmap.Get());

D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F(0.9f, -0.1f,  0.1f, 0.9f, 8.0f, 45.0f);
DX::ThrowIfFailed(affineTransformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, matrix));

m_d2dContext->BeginDraw();
m_d2dContext->DrawImage(affineTransformEffect.Get());
m_d2dContext->EndDraw();

这种使用 2D 仿射转换效果会稍微逆时针旋转位图。

之前
图像前的 2d 仿射效果。
之后
图像后的 2d 仿射效果。

合成图像

某些效果接受多个输入,并将其合成为一个生成的图像。

内置的复合效果和算术复合效果提供各种模式,有关详细信息,请参阅 复合 主题。 混合效果有多种可用的 GPU 加速模式。

ComPtr<ID2D1Effect> compositeEffect;
DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D1Composite, &compositeEffect));

compositeEffect->SetInput(0, bitmap.Get());
compositeEffect->SetInput(1, bitmapTwo.Get());

m_d2dContext->BeginDraw();
m_d2dContext->DrawImage(compositeEffect.Get());
m_d2dContext->EndDraw();

复合效果根据指定的模式以各种不同方式组合图像。

像素调整

有一些内置的 Direct2D 效果可用于更改像素数据。 例如,颜色矩阵效果可用于更改图像的颜色。

ComPtr<ID2D1Effect> colorMatrixEffect;
DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D1ColorMatrix, &colorMatrixEffect));

colorMatrixEffect->SetInput(0, bitmap.Get());

D2D1_MATRIX_5X4_F matrix = D2D1::Matrix5x4F(0, 0, 1, 0,   0, 1, 0, 0,   1, 0, 0, 0,   0, 0, 0, 1,   0, 0, 0, 0);
DX::ThrowIfFailed(colorMatrixEffect->SetValue(D2D1_COLORMATRIX_PROP_COLOR_MATRIX, matrix));

m_d2dContext->BeginDraw();
m_d2dContext->DrawImage(colorMatrixEffect.Get());
m_d2dContext->EndDraw();

此代码采用图像并更改颜色,如此处的示例图像所示。

之前
图像前的颜色矩阵效果。
之后
图像后的颜色矩阵效果。

有关详细信息,请参阅 颜色内置效果 部分。

生成效果图

可以将效果链接在一起以转换图像。 例如,此处的代码应用阴影和 2D 转换,然后将结果组合在一起。

ComPtr<ID2D1Effect> shadowEffect;
ComPtr<ID2D1Effect> affineTransformEffect;
ComPtr<ID2D1Effect> compositeEffect;

DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D1Shadow, &shadowEffect));
DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D12DAffineTransform, &affineTransformEffect));
DX::ThrowIfFailed(m_d2dContext->CreateEffect(CLSID_D2D1Composite, &compositeEffect));

shadowEffect->SetInput(0, bitmap.Get());
affineTransformEffect->SetInputEffect(0, shadowEffect.Get());

D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Translation(20, 20));

affineTransformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, matrix);

compositeEffect->SetInputEffect(0, affineTransformEffect.Get());
compositeEffect->SetInput(1, bitmap.Get());

m_d2dContext->BeginDraw();
m_d2dContext->DrawImage(compositeEffect.Get());
m_d2dContext->EndDraw();

下面是结果。

阴影效果输出。

效果采用 ID2D1Image 对象作为输入。 可以使用 ID2D1Bitmap ,因为接口派生自 ID2D1Image。 还可以使用 ID2D1Effect::GetOutput 获取 ID2D1Effect 对象的输出作为 ID2D1Image ,或使用 SetInputEffect 方法转换输出。 在大多数情况下,效果图由直接链接在一起的 ID2D1Effect 对象组成,因此可以轻松地将多个效果应用于图像以创建引人注目的视觉对象。

有关详细信息 ,请参阅如何将效果应用于基元

Direct2D 基本图像效果示例

内置效果