Применение эффектов к примитивам
В этом разделе показано, как применить ряд эффектов к Примитивам Direct2D и DirectWrite.
Api эффектов Direct2D можно использовать для применения графов эффектов к примитивам, отображаемым Direct2D, к изображению. В приведенном здесь примере есть два скругленные прямоугольника и текст "Direct2D". Используйте Direct2D для рисования прямоугольников и DirectWrite для рисования текста.
С помощью эффектов Direct2D можно сделать это изображение похожим на следующее изображение. Чтобы создать изображение, примените эффекты Gaussian Blur, Point Specular Lighting, Arithmetic Composite и Composite к двухмерным примитивам.
После отрисовки прямоугольников и текста на промежуточной поверхности их можно использовать в качестве входных данных для объектов ID2D1Effect в графе изображений.
В этом примере задайте исходное изображение в качестве входных данных для эффекта размытия Гауссиана , а затем задайте выходные данные размытия в качестве входных данных для эффекта точечного зеркального освещения. Результат этого эффекта затем композитируется с исходным изображением дважды, чтобы получить окончательное изображение, которое отображается в окне.
Ниже приведена схема графа изображений.
Этот граф эффектов состоит из четырех объектов ID2D1Effect , каждый из которых представляет отдельный встроенный эффект. Пользовательские эффекты можно создавать и подключать таким же образом после их регистрации с помощью ID1D1Factory1::RegisterEffect. Приведенный здесь код создает эффекты, задает свойства и соединяет граф эффектов, показанный ранее.
Создайте эффект размытия 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) );
Эффект размытия Гауссов размывает все каналы изображения, включая альфа-канал.
Создайте эффект зеркального освещения и задайте свойства. Положение света представляет собой вектор из 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) );
Эффект зеркального освещения использует альфа-канал входных данных для создания карты высоты для освещения.
Существует два разных составных эффекта, которые можно использовать как составной эффект, так и арифметический составной. В этом графе эффектов используются оба варианта.
Создайте составной эффект и задайте режим 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);
В этом графе эффектов оба составных эффекта принимают выходные данные других эффектов и промежуточную поверхность в качестве входных и композитных их.
Наконец, вы подключаете эффекты для формирования графа, задавая входные данные для соответствующих изображений и растровых изображений.
Первый эффект, гауссовское размытие, получает входные данные от промежуточной поверхности, на которую были отрисованы примитивы. Входные данные задаются с помощью метода 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());
Передайте объект арифметического составного эффекта в метод ID2DDeviceContext::D rawImage , и он обрабатывает и рисует выходные данные графа.
// 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 ) );