Direct2D实现文字镜像阴影

一、实现思路
先绘制文字阴影部分,绘制阴影文本后应用3DTransform与高斯模糊特效,最后再正常绘制一次文本主体。

二、实现代码

      hr = m_pDWriteFactory->CreateTextFormat(
    			sc_fontName,
    			NULL,
    			DWRITE_FONT_WEIGHT_NORMAL,
    			DWRITE_FONT_STYLE_NORMAL,
    			DWRITE_FONT_STRETCH_NORMAL,
    			sc_fontSize,
    			L"", //locale
    			&pTextFormat
    		);
    		
        pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
 		pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
 		static const WCHAR sc_helloWorld[] = L"你好\nWorld!";
 		ID2D1SolidColorBrush *pGrayBrush = nullptr;
 		hr = m_pOffScreenRenderTarget->CreateSolidColorBrush(
 			D2D1::ColorF(D2D1::ColorF::DarkGray),
 			&pGrayBrush);
    
    
   		hr = m_pDWriteFactory->CreateTextLayout(
   			sc_helloWorld,
   			ARRAYSIZE(sc_helloWorld) - 1,
   			pTextFormat,
   			m_width,
   			m_height,
   			&m_pTextLayout
   		);
    
   		m_pOffScreenRenderTarget->BeginDraw();
   		m_pOffScreenRenderTarget->Clear(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f));
   		m_pOffScreenRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
    		
        // 绘制文字阴影部分
   		m_pOffScreenRenderTarget->DrawTextLayout(D2D1::Point2F(0.0f, 0.0f), m_pTextLayout, pGrayBrush);
   
   		hr = m_pOffScreenRenderTarget->EndDraw();		
   
   		// 创建特效并渲染到Bitmap
   		m_pOffScreenRenderTarget->QueryInterface(&m_pDeviceContext);
   		m_pOffScreenRenderTarget->CreateBitmapFromWicBitmap(m_pWicBitmap, &m_pBitmap);
   
        // 高斯模糊
   		m_pDeviceContext->CreateEffect(CLSID_D2D1GaussianBlur, &m_pGaussianBlur);
   		m_pGaussianBlur->SetInput(0, m_pBitmap);
   		m_pGaussianBlur->SetValue(D2D1_GAUSSIANBLUR_PROP_BORDER_MODE, D2D1_BORDER_MODE_SOFT);
   		m_pGaussianBlur->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, 1.0f);
   
   		// 镜像阴影
   		ID2D1Effect *pPerspectiveTransformEffect = nullptr;
   		m_pDeviceContext->CreateEffect(CLSID_D2D13DPerspectiveTransform, &pPerspectiveTransformEffect);
   		pPerspectiveTransformEffect->SetInputEffect(0, m_pGaussianBlur);
   		pPerspectiveTransformEffect->SetValue(D2D1_3DPERSPECTIVETRANSFORM_PROP_ROTATION_ORIGIN,
   			D2D1::Vector3F(m_width / 2.0f, m_height / 2.0f, 0.0f));
   		pPerspectiveTransformEffect->SetValue(D2D1_3DPERSPECTIVETRANSFORM_PROP_ROTATION, 
   			D2D1::Vector3F(180.0f, 0.0f, 0.0f));
   		pPerspectiveTransformEffect->SetValue(D2D1_3DPERSPECTIVETRANSFORM_PROP_GLOBAL_OFFSET, 
   			D2D1::Vector3F(0.0f, sc_fontSize * GetTextLines(sc_helloWorld), 0.0f));
   
   		m_pDeviceContext->BeginDraw();
   		m_pDeviceContext->Clear(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f));
   		m_pDeviceContext->SetTransform(D2D1::Matrix3x2F::Identity());
   		m_pDeviceContext->DrawImage(pPerspectiveTransformEffect, D2D1_INTERPOLATION_MODE_LINEAR);
   		hr = m_pDeviceContext->EndDraw();
   
   		// 绘制文字本体部分
   		if (SUCCEEDED(hr))
   		{
   			m_pOffScreenRenderTarget->BeginDraw();
   			
   			ID2D1SolidColorBrush *pBlackBrush = nullptr;
   			hr = m_pOffScreenRenderTarget->CreateSolidColorBrush(
   				D2D1::ColorF(D2D1::ColorF::Black),
   				&pBlackBrush);
   			m_pOffScreenRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
   
   			m_pOffScreenRenderTarget->DrawTextLayout(D2D1::Point2F(0.0f, 0.0f), m_pTextLayout, pBlackBrush);
   
   			hr = m_pOffScreenRenderTarget->EndDraw();
   		}

三、绘制结果
1、单行文本:
Direct2D实现文字镜像阴影_第1张图片
2、多行文本
Direct2D实现文字镜像阴影_第2张图片

四、总结
1、整个实现过程包含了三次绘制,第一次绘制的文本是为后面应用特效做准备的,第二次绘制应用了高斯模糊和3D变换,将第一次绘制的文本变换为镜像阴影的效果,最后一次是正常绘制文本主体。
2、在对原文本进行3D变换的时候,这里先对文字绕X轴旋转180度,然后向下偏移n * fontSize,n为文本中包含的行数。
3、上面的实现方法只能将文本整体进行镜像处理,没法实现每一行文字单独镜像。如果要实现每行单独镜像,自己的思路是单独绘制每一行的文本,然后应用上面的方法绘制对应的阴影,重复上述过程,直到绘制完所有的文字。

PS:
本文代码是基于微软官方文档示例实现的,详情可参考这里。

你可能感兴趣的:(Direct2D)