什么是Layers?

Layer,中文译成图层,在Direct2D中可以用来完成一些特殊效果,使用Layer的时候,先将Layer Push到render target,然后进行绘制,此时是直接绘制在Layer上的,绘制完毕后,将Layer Pop出来,刚刚绘制在Layer上的内容就会组合到render target上。在Direct2D中,Layer使用接口ID2D1Layer来表示。

和画刷一样,Layer由render target创建,属于设备相关的资源,Layer可以用于任何render target上,只要二者在相同的资源作用域内,在同一时间内,Layer只能用于一个render target。

尽管Layer为创建特效提供了强大的技术支持,但是过度使用Layer将导致D2D程序性能下降,因为操作Layer是比较耗时的,比如清除Layer上的内容,将Layer上绘制的内容混合到render target上都需要时间。

使用Layer的步骤

在Direct2D中,使用Layer的步骤非常简单,首先创建一个Layer,在创建的时候,会指定一系列Layer的属性,在绘制之前,先将Layer Push到当前的render target上,然后进行绘制操作,绘制完毕后将Layer Pop出来即可。

创建Layer

创建Layer使用CreateLayer函数,该函数定义如下:

virtual HRESULT CreateLayer([in, optional]  D2D1_SIZE_F *size,[out]           ID2D1Layer **layer
) = 0;

参数说明:

size,这是一个矩形区域,定义了创建的Layer的大小(像素尺寸),通常这个值设置为NULL,当调用PushLayer函数时,会自动为Layer分配最小的所需尺寸(通常是render target的尺寸)。

layer,这是一个ID2D1Layer**类型的变量,用来接收创建好的Layer。

创建Layer代码如下。

ID2D1Layer* g_pLayer = NULL ;// Create layer
hr = g_pRenderTarget->CreateLayer(NULL, &g_pLayer) ;
if (FAILED(hr))
{MessageBox(hWnd, "Create layer failed!", "Error", 0) ;return ;
}

Push Layer

在BeginDraw函数调用完之后,并且在具体绘制开始之前,将Layer Push到render target。

PushLayer函数定义如下:

void PushLayer(const D2D1_LAYER_PARAMETERS &layerParameters,[in]   ID2D1Layer *layer
);

参数说明:

layerParameters,这是一个D2D1_LAYER_PARAMETERS类型的变量,它可以指定一系列Layer属性,D2D1_LAYER_PARAMETERS结构体定义如下:

struct D2D1_LAYER_PARAMETERS {D2D1_RECT_F         contentBounds;ID2D1Geometry       *geometricMask;D2D1_ANTIALIAS_MODE maskAntialiasMode;D2D1_MATRIX_3X2_F   maskTransform;FLOAT               opacity;ID2D1Brush          *opacityBrush;D2D1_LAYER_OPTIONS  layerOptions;
};

参数说明

  • contentBounds,这是一个矩形区域,指定了Layer的绘制范围,也就是说在该范围之外的内容都不会被绘制。
  • geometricMask,这是一个几何图形,它指定了Layer的哪一部分被显示,比如你可以设置一Path Geometry,然后绘制一个位图,这样,只有PathGeometry内部的位图会显示,相当于给几何图形加上了位图纹理。
  • maskAntialiasMode,这个暂时用不到,不理它。
  • maskTransform,这是一个变换矩阵,指定了施加在第二个参数上的几何变换。
  • opacity,这是一个透明值,指定了Layer与render target混合时使用的透明值。
  • opacityBrush,这是一个画刷,用来改变Layer的透明值。
  • layerOptions,一个D2D1_LAYER_OPTIONS变量,基本用不到,从windows 8开始,使用D2D1_LAYER_OPTIONS1来代替。

Direct2D提供了一个函数LayerParameters来初始化上面这些参数,这个函数为上面每个参数都提供了一个默认值,如下:

D2D1_LAYER_PARAMETERS LayerParameters(_In_      const D2D1_RECT_F &contentBounds = D2D1::InfiniteRect(),_In_opt_  ID2D1Geometry *geometricMask = NULL,D2D1_ANTIALIAS_MODE maskAntialiasMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,D2D1_MATRIX_3X2_F maskTransform = D2D1::IdentityMatrix(),FLOAT opacity = 1.0,ID2D1Brush *opacityBrush = NULL,D2D1_LAYER_OPTIONS layerOptions = D2D1_LAYER_OPTIONS_NONE
);

在这里,我们使用这个函数创建一个Layer,在随后的介绍中,会指定某些特定的参数来达到特殊的效果。

g_pRenderTarget->PushLayer(D2D1::LayerParameters(),g_pLayer
) ;

绘制

这里可以绘制任意内容,几何图形,文本,图片等,为了演示Layer的特殊效果,这里通常绘制位图。

Pop Layer

绘制完毕后,将Layer Pop出来,这样已经在Layer上绘制的内容就会与render target上的内容混合。

Demo

下面几个Demo都是通过位图来演示的,原始的位图如下,三个可爱的企鹅。

限定位图绘制区域

在PushLayer的时候指定一个矩形区域,在这个区域内的图形将被显示,而这个区域外的图形都将被屏蔽掉,为了方便查看结果,这里绘制一个位图,可以清楚的看到位图的那一部分被绘制了。

代码

g_pRenderTarget->BeginDraw() ;g_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));g_pRenderTarget->PushLayer(D2D1::LayerParameters(D2D1::RectF(100, 100, 400, 400)),g_pLayer
) ;D2D1_SIZE_F size = g_pBitmap->GetSize() ;
D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f) ;// Draw bitmap
g_pRenderTarget->DrawBitmap(g_pBitmap,D2D1::RectF(upperLeftCorner.x,upperLeftCorner.y,upperLeftCorner.x + size.width,upperLeftCorner.y + size.height)
) ;// Pop layer before EndDraw
g_pRenderTarget->PopLayer() ;g_pRenderTarget->EndDraw() ;

效果图

透明效果

在PushLayer调用完之后,先绘制一个位图,然后再绘制三个矩形,这三个矩形使用绿颜色的画刷来绘制,所以最终的结果就是位图和矩形混合后的结果,可以看到矩形呈透明状,创建绿色画刷的代码省略。

代码

g_pRenderTarget->BeginDraw() ;g_pRenderTarget->PushLayer(D2D1::LayerParameters(), g_pLayer) ;g_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));D2D1_SIZE_F size = g_pBitmap->GetSize() ;
D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f) ;// Draw bitmap
g_pRenderTarget->DrawBitmap(g_pBitmap,D2D1::RectF(upperLeftCorner.x,upperLeftCorner.y,upperLeftCorner.x + size.width,upperLeftCorner.y + size.height)
) ;// Opacity mask 1
g_pRenderTarget->FillRectangle(D2D1::RectF(100, 100, 200, 200), g_pBlackBrush) ;// Opacity mask 2
g_pRenderTarget->FillRectangle(D2D1::RectF(200, 200, 300, 300), g_pBlackBrush) ;// Opacity mask 3
g_pRenderTarget->FillRectangle(D2D1::RectF(300, 300, 400, 400), g_pBlackBrush) ;// Pop layer before EndDraw
g_pRenderTarget->PopLayer() ;g_pRenderTarget->EndDraw() ;

效果图

圆形渐变画刷

先创建一个圆形的渐变色画刷,调用PushLayer的时候将这个画刷作为参数传递给PushLayer的第一个参数。接下来绘制一个位图,当调用PopLayer的时候两次绘制的内容将被混合到一起,最后形成一个夜视镜的效果。

代码

g_pRenderTarget->BeginDraw() ;// Clear background color to white
g_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));g_pRenderTarget->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(),NULL,D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,D2D1::IdentityMatrix(),1.0f,g_pRadialGradientBrush,D2D1_LAYER_OPTIONS_NONE),g_pLayer
);D2D1_SIZE_F size = g_pBitmap->GetSize() ;
D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f) ;// Draw bitmap
g_pRenderTarget->DrawBitmap(g_pBitmap,D2D1::RectF(upperLeftCorner.x,upperLeftCorner.y,upperLeftCorner.x + size.width,upperLeftCorner.y + size.height)
) ;// Pop layer before EndDraw
g_pRenderTarget->PopLayer() ;g_pRenderTarget->EndDraw() ;

效果图

最后一个例子代码下载。

== Happy Coding ==

本文转自zdd博客园博客,原文链接:http://www.cnblogs.com/graphics/archive/2013/04/15/2781969.html,如需转载请自行联系原作者

Direct2D教程(十二)图层相关推荐

  1. Wix 安装部署教程(十二) -- 自动更新WXS文件

    原文:Wix 安装部署教程(十二) -- 自动更新WXS文件 上一篇分享了一个QuickWIX,用来对比两个工程前后的差异,但是这样还是很繁琐,而且昨天发现有Bug,目录对比有问题.这次改变做法,完全 ...

  2. 【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8586540 作者:毛星云(浅墨 ...

  3. 【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/zhmxy555/article/details/8586540 作者:毛星云(浅墨) ...

  4. VML极道教程(十二) VML编程大结局

    本系列文章导航 VML极道教程(一) VML介绍 VML极道教程(二) VML入门 VML极道教程(三) 标记实战与line线 VML极道教程(四) oval圆rect矩型 VML极道教程(五) Ro ...

  5. PyQt5教程(十二)——实现QQ登录界面(六、实现鼠标拖动界面,鼠标事件)

    PyQt5教程(十二)--实现QQ登录界面(五.实现鼠标拖动界面,鼠标事件) 一.实现界面可以随着鼠标进行拖动 1.主要就是对鼠标事件的实现: def mousePressEvent(self, ev ...

  6. twisted系列教程十二–为server 增加一个service

    One More Server 在第九部分和第十部分我们介绍了关于诗歌的变形引擎的想法,最后我们实现了cummingsifier,我们还让它抛出随机的异常来模拟错误.但是假如这个变形的引擎在另外一台服 ...

  7. nCode:DesignLife案例教程十二

    nCode:DesignLife 案例十二--Virtual Strain Gauge Correlation 12.1 案例文件 12.2 背景 12.3 创建流程 12.4 保存虚拟应变计 12. ...

  8. Direct2D教程(二)来看D2D世界中的Hello,World

    引子 任何一门语言的第一个教程几乎都是Hello,world.我们也不例外,但是这里不是教大家打印Hello,world,而是编写一个简单的D2D绘制程序,让大家对Direct2D的程序结构及编程方法 ...

  9. NVisionXR_iOS教程十二 —— 多图识别

    本章节教大家多个识别切换多个场景,接着上一章多场景切换的教程  1.打开StonesAndChips.xml,我们可以看到有两张识别图stones和chips,这两张图都可以进行识别,接下来我们会根据 ...

  10. 【QT】QT从零入门教程(十二):实现工具箱QButtonGroup

      工具箱有两种实现方式,一是运用工具栏QToolBar,二是运用QButtonGroup,在按钮组内创建多个QPushButton,每个按钮对应不同的槽函数.   本节的"工具箱" ...

最新文章

  1. Redis 笔记(01)— 安装、启动配置、开启远程连接、设置密码、远程连接
  2. Golang range解析
  3. hihoCoder1233(2015北京网络赛H题)
  4. String.format() 格式化字符串
  5. c语言扫描图片的坐标,tc 如何在指定坐标处 输出bmp图片??
  6. 如何设制 select 不可编辑 只读
  7. 在Excel工作表区域内快速移动或滚动
  8. datatables 一列显示两个字段的数据_5个超实用的Excel数据透视表技巧,学会少加班...
  9. BTA 2018 区块链核心技术专场:12 位专家全方位剖析区块链核心技术原理与业务实践
  10. Nginx Location 工作流程图及总结
  11. R语言大作业(全国2000-2019年人口各项数据分析)
  12. scrollHeight,clientHeight,scrollTop
  13. CVE-2020-11946 ManageEngine OpManager 命令执行
  14. 英雄联盟官网服务器状态查询,官方新功能:各大区服务器状态可查询!
  15. PAT(甲级)2021年冬季考试 7-2 Rank a Linked List
  16. 蛮力法 第4关:韩信点兵问题
  17. godis之aof持久化
  18. 关于h5使用高德地图,没有获取经纬度
  19. Linux环境下java安装、配置
  20. 第157章 SQL函数 WEEK

热门文章

  1. [SoapUI] Mock Service
  2. Eclipse自定义文档注释和方法注释
  3. 接口测试--ApiPost组成介绍
  4. c语言case语句块,JavaScript使用Switch语句来选择将要执行的代码块
  5. python全网表情包_Python爬虫爬取最右公众号表情包资源
  6. python2.7中文字符串_python2.7 怎样将中文字符串转为字节流?
  7. 软件测试面试技巧|项目常识篇
  8. java可选项_在Java中链接可选项8
  9. ipad导入pdf_Ipad笔记法①日常笔记篇
  10. Java教程:Java字符串的替换(replace()、replaceFirst()和replaceAll())