Поделиться через


Применение эффектов к примитивам

В этом разделе показано, как применить ряд эффектов к Direct2D и DirectWrite примитивам.

Вы можете использовать API эффектов Direct2D для применения графиков эффектов к примитивам, отрисованным с помощью Direct2D , на изображение. В примере есть два округленные прямоугольники и текст Direct2D. Используйте Direct2D для рисования прямоугольников и DirectWrite для рисования текста.

прямоугольники с текстом direct2d внутри.

Используя эффекты Direct2D, вы можете сделать это изображение похожим на следующее изображение. Примените эффекты Гауссова размытия, точечного зеркального освещения, арифметического составленияи составного к 2D-примитивам для создания изображения.

прямоугольники с текстом

После отрисовки прямоугольников и текста на промежуточной поверхности его можно использовать в качестве входных данных для объектов ID2D1Effect в графе изображения.

В этом примере установите исходное изображение в качестве входного для эффекта гауссовского размытия , а затем используйте выходное изображение размытия в качестве входного для эффекта точечного зеркального освещения . Результат этого эффекта затем композитируется с исходным изображением дважды, чтобы получить окончательное изображение, отображаемое в окне.

Ниже приведена схема графа изображений.

диаграмма графа эффектов .

Этот граф эффектов состоит из четырех объектов ID2D1Effect, каждый из которых представляет различные встроенные эффекты. Вы можете создавать и подключать пользовательские эффекты таким же образом, после регистрации их с помощью ID1D1Factory1::RegisterEffect. Код здесь создает эффекты, задает свойства и подключает граф эффектов, показанный ранее.

  1. Создайте эффект размытия Gaussian с помощью метода ID2D1DeviceContext::CreateEffect и указания соответствующего clSID. CLSID для встроенных эффектов определён в d2d1effects.h. Затем вы задаете стандартное отклонение размытия с помощью метода ID2D1Effect::SetValue.

    // Create the Gaussian Blur Effect
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1GaussianBlur, &gaussianBlurEffect)
        );
    
    // Set the blur amount
    DX::ThrowIfFailed(
        gaussianBlurEffect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, sc_gaussianBlurStDev)
        );
    

    Эффект размытия Гаусса размывает все каналы изображения, включая альфа-канал.

  2. Создайте эффект спекулярного освещения и задайте свойства. Позиция света является вектором из 3 значений с плавающей запятой, поэтому необходимо объявить ее отдельной переменной и передать ее в метод setValue.

    // Create the Specular Lighting Effect
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1PointSpecular, &specularLightingEffect)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_LIGHT_POSITION, sc_specularLightPosition)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_SPECULAR_EXPONENT, sc_specularExponent)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_SURFACE_SCALE, sc_specularSurfaceScale)
        );
    
    DX::ThrowIfFailed(
        specularLightingEffect->SetValue(D2D1_POINTSPECULAR_PROP_SPECULAR_CONSTANT, sc_specularConstant)
        );
    

    Эффект зеркального освещения использует альфа-канал входа для создания карты высоты освещения.

  3. Существует два различных составных эффекта, которые можно использовать: составной эффект и арифметический составной . Этот граф эффектов использует оба.

    Создайте составной эффект и задайте режим D2D1_COMPOSITE_MODE_SOURCE_IN, который выводит пересечение исходных и целевых образов.

    Арифметический составной эффект комбинирует два входных изображения на основе формулы, определенной консорциумом Всемирной паутины (W3C) для стандарта масштабируемой векторной графики (SVG). Создайте арифметический состав и задайте коэффициенты для формулы.

    // Create the Composite Effects
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1Composite, &compositeEffect)
        );
    
    DX::ThrowIfFailed(
        compositeEffect->SetValue(D2D1_COMPOSITE_PROP_MODE, D2D1_COMPOSITE_MODE_SOURCE_IN)
        );
    
    DX::ThrowIfFailed(
        m_d2dContext->CreateEffect(CLSID_D2D1ArithmeticComposite, &m_arithmeticCompositeEffect)
        );
    
    DX::ThrowIfFailed(
        m_arithmeticCompositeEffect->SetValue(D2D1_ARITHMETICCOMPOSITE_PROP_COEFFICIENTS, sc_arithmeticCoefficients)
        );
    

    Здесь показаны коэффициенты арифметического составного эффекта.

    D2D1_VECTOR_4F sc_arithmeticCoefficients   = D2D1::Vector4F(0.0f, 1.0f, 1.0f, 0.0f);
    

    В этом графе эффектов оба составных эффекта используют выходные данные других эффектов и промежуточную поверхность в качестве входных данных и комбинируют их.

  4. Наконец, вы подключаете эффекты для формирования графа, задав входные данные соответствующим изображениям и растровым изображениям.

    Первый эффект, Гауссово размытие, получает входные данные от промежуточной поверхности, в которую вы отрендерили примитивы. Входные данные задаются с помощью метода ID2D1Effect::SetInput и указания индекса объекта ID2D1Image. Гауссово размытие и эффекты зеркального освещения имеют только один вход. Эффект зеркального освещения использует альфа-канал гауссового размытия.

    Составные и арифметические арифметические эффекты имеют несколько входных данных. Чтобы убедиться, что изображения собраны в правильном порядке, необходимо указать правильный индекс для каждого входного изображения.

    // Connect the graph.
    // Apply a blur effect to the original image.
    gaussianBlurEffect->SetInput(0, m_inputImage.Get());
    
    // Apply a specular lighting effect to the result.
    specularLightingEffect->SetInputEffect(0, gaussianBlurEffect.Get());
    
    // Compose the original bitmap under the output from lighting and blur.
    compositeEffect->SetInput(0, m_inputImage.Get());
    compositeEffect->SetInputEffect(1, specularLightingEffect.Get());
    
    // Compose the original bitmap under the output from lighting and blur.
    m_arithmeticCompositeEffect->SetInput(0, m_inputImage.Get());
    m_arithmeticCompositeEffect->SetInputEffect(1, compositeEffect.Get());
    
  5. Передайте объект арифметического составного эффекта в метод ID2DDeviceContext::DrawImage, и он обработает и отобразит выходные данные графа.

        // Draw the output of the effects graph.
        m_d2dContext->DrawImage(
            m_arithmeticCompositeEffect.Get(),
            D2D1::Point2F(
                (size.width - sc_inputBitmapSize.width) / 2,
                (size.height - sc_inputBitmapSize.height) / 2 + sc_offset
                )
            );