MFC Support for Direct2D – Composite Effects

We can combine two or more images and/or effects by using the composite effect. Here is an example.

Drawing shadows using Direct2D composite effects

void CD2DStaticCtrl::_DrawImageWithShadow(CHwndRenderTarget* pRenderTarget)
{
    ASSERT(pRenderTarget && pRenderTarget->IsValid());
    ASSERT(m_pBitmap && m_pBitmap->IsValid());

    // get ID2D1DeviceContext interface; note: must include <d2d1_1.h>
    CComQIPtr<ID2D1DeviceContext> spDeviceContext =
        pRenderTarget->GetRenderTarget();

    // create shadow effect and set the input image
    CComPtr<ID2D1Effect> spShadowEffect;
    spDeviceContext->CreateEffect(CLSID_D2D1Shadow, &spShadowEffect);
    spShadowEffect->SetInput(0, m_pBitmap->Get());
    spShadowEffect->SetValue(D2D1_SHADOW_PROP_BLUR_STANDARD_DEVIATION, m_fBlurStandardDeviation);
    spShadowEffect->SetValue(D2D1_SHADOW_PROP_COLOR, CRenderTarget::COLORREF_TO_D2DCOLOR(m_shadowColor));

    // create flood effect
    CComPtr<ID2D1Effect> spFloodEffect;
    spDeviceContext->CreateEffect(CLSID_D2D1Flood, &spFloodEffect);
    // Note: shadow will be composed in the top of a surface having the background color
    D2D1_COLOR_F color = CRenderTarget::COLORREF_TO_D2DCOLOR(m_backColor);
    spFloodEffect->SetValue(D2D1_FLOOD_PROP_COLOR, D2D1::Vector4F(color.r, color.g, color.b, color.a));

    // create 2D affine transform effect in order to translate the shadow
    CComPtr<ID2D1Effect> spAffineTransformEffect;
    spDeviceContext->CreateEffect(CLSID_D2D12DAffineTransform, &spAffineTransformEffect);
    spAffineTransformEffect->SetInputEffect(0, spShadowEffect);
    D2D1_MATRIX_3X2_F translation = D2D1::Matrix3x2F::Translation(m_fShadowDistance, m_fShadowDistance);
    spAffineTransformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, translation);
    
    // create the composite effect and combine the effects
    CComPtr<ID2D1Effect> spCompositeEffect;
    spDeviceContext->CreateEffect(CLSID_D2D1Composite, &spCompositeEffect);
    // set input effects
    spCompositeEffect->SetInputEffect(0, spFloodEffect);
    spCompositeEffect->SetInputEffect(1, spAffineTransformEffect);
    // set input image; because the default input count is 1, he have to set it to 3
    spCompositeEffect->SetInputCount(3);
    spCompositeEffect->SetInput(2, m_pBitmap->Get());

    // finally perform drawing
    spDeviceContext->DrawImage(spCompositeEffect);
}

Demo project

Download: Composite Effect Demo.zip (1257 downloads)
You can set the amount of blur and the color as well as the distance of the shadow.

Composite Effect Demo
Composite Effect Demo

Resources and related articles

Leave a Comment