• [Direct2D开发] 绘制网格


    转载请注明出处:http://www.cnblogs.com/Ray1024

    一、引言

    最近在使用Direct2D进行绘制工作中,需要实现使用Direct2D绘制网格的功能。在网上查了很多资料,终于实现了,把方法贴到这里供大家参考。

    二、绘制网格

    2.1 API接口

    首先介绍一下绘制网格中使用到的重要接口ID2D1BitmapRenderTarget,它继承自ID2D1RenderTarget,会写入到中间纹理。对于创建与 ID2D1BitmapBrush 结合使用的图案,或缓存要反复使用的绘制数据,这十分有用。它仅仅比基类多了一个函数GetBitmap,此函数可以将内部的绘制数据输出到位图ID2D1Bitmap中,如下:

    语法:	virtual HRESULT GetBitmap([out]  ID2D1Bitmap **bitmap) = 0;
    功能:	检索此呈现器目标的位图。返回的位图可用于绘制操作。
    参数:	bitmap 		此方法返回时,包含指向此呈现器目标的位图的指针地址。此位图可用于绘制操作。
    返回值:HRESULT		如果该方法成功,则返回 S_OK。 否则,将返回错误代码。HRESULT.
    

    创建ID2D1BitmapRenderTarget对象的函数为ID2D1RenderTarget::CreateCompatibleRenderTarget,这个函数有6个重载,我们只介绍其中一个,有兴趣的朋友可以查看msdn文档,介绍如下:

    语法:HRESULT CreateCompatibleRenderTarget(D2D1_SIZE_F desiredSize,[out]  ID2D1BitmapRenderTarget **bitmapRenderTarget);
    功能:创建新位图呈现器目标,以供在中间屏幕外绘制期间使用。新位图呈现器目标与当前呈现器目标兼容,并且与当前呈现器目标有相同的像素格式。
    参数:
    	desiredSize			以与设备无关的像素表示的新呈现器目标的所需大小。
    	bitmapRenderTarget 	此方法返回时将包含一个指针的地址,该指针指向一个新位图呈器现目标。此参数以未初始化的状态传递。
    返回值:HRESULT 如果该方法成功,则返回 S_OK。 否则,将返回错误代码。HRESULT.
    

    我们还要用到位图画刷ID2D1BitmapBrush,这个接口不用特殊介绍,我们介绍一下创建画刷时需要的一个结构体,这个结构体用来描述 ID2D1BitmapBrush 的扩展模式和内插模式:

    struct D2D1_BITMAP_BRUSH_PROPERTIES {
      D2D1_EXTEND_MODE               extendModeX;		//一个值,用来描述画笔对超过其位图范围的区域进行水平平铺的方式。
      D2D1_EXTEND_MODE               extendModeY;		//一个值,用来描述画笔对超过其位图范围的区域进行垂直平铺的方式。
      D2D1_BITMAP_INTERPOLATION_MODE interpolationMode;	//一个值,用来指定对位图进行缩放或旋转时使用的内插方式。
    };
    

    这个结构体前两个成员的类型都是枚举类型D2D1_EXTEND_MODE,它指定画笔如何在其常规内容区域之外的区域进行绘制。如下:

    typedef enum  {
      D2D1_EXTEND_MODE_CLAMP    = 0,//在常规内容区域以外的所有区域重复画笔内容边上的像素。
      D2D1_EXTEND_MODE_WRAP     = 1,//重复画笔的内容。
      D2D1_EXTEND_MODE_MIRROR   = 2 //与 D2D1_EXTEND_MODE_WRAP 相同,但画笔的内容将翻转显示。(画笔的常规内容在绘制时不会进行转换。)
    } D2D1_EXTEND_MODE;
    

    还有一个枚举类型D2D1_BITMAP_INTERPOLATION_MODE,用来指定缩放或旋转图像时所使用的算法。如下:

    typedef enum  {
      D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR   = 0,//使用离当前呈现像素最近的位图像素的精确颜色。
      D2D1_BITMAP_INTERPOLATION_MODE_LINEAR             = 1 //从离当前呈现像素最近的四个位图像素来内插颜色。
    } D2D1_BITMAP_INTERPOLATION_MODE;
    

    要拉伸图像,原始图像中的每个像素都必须映射到较大的图像中的一组像素。要压缩图像,原始图像中的一组像素必须映射到较小的图像中的单个像素。我们这里用不到这些,就不过多介绍了。

     

    到这里我们所需要的API接口就介绍完了。

    2.2 思路介绍

    介绍完需要的API接口之后,我们来看一下实现网格绘制的思路:

      a.创建一个网格粒度大小的ID2D1BitmapRenderTarget;

      b.在ID2D1BitmapRenderTarget上绘制两条直线,分别在ID2D1BitmapRenderTarget的左边和上边;

      c.从ID2D1BitmapRenderTarget创建位图;

      d.指定画刷的的属性,让它对超过位图画刷范围外的区域进行重复绘制。

    也就是说在一个位图画刷上保存一个网格,并指定画刷绘制的时候对范围外的区域进行重复绘制,如下图所示:

    2.3 代码实现

    这是绘制网格的代码部分:

    // 网格粒度
    float meshLength = 20.f;
    
    // 创建bitmapRT
    if (SUCCEEDED(hr))
    {
    	hr = m_pRT->CreateCompatibleRenderTarget(
    	D2D1::SizeF(meshLength,meshLength),
    	&m_pBitmapRT);
    }
    
    // 创建bitmapBrush
    if (SUCCEEDED(hr))
    {
    	m_pBitmapRT->BeginDraw();
    	m_pBitmapRT->DrawLine(D2D1::Point2F(0,0),D2D1::Point2F(meshLength,0),m_pBrush);
    	m_pBitmapRT->DrawLine(D2D1::Point2F(0,0),D2D1::Point2F(0,meshLength),m_pBrush);
    	m_pBitmapRT->EndDraw();
    
    	m_pBitmapRT->GetBitmap(&m_pBitmap);
    
    	D2D1_BITMAP_BRUSH_PROPERTIES bbp;
    	bbp.extendModeX = D2D1_EXTEND_MODE_WRAP;
    	bbp.extendModeY = D2D1_EXTEND_MODE_WRAP;
    	bbp.interpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
    	m_pRT->CreateBitmapBrush(m_pBitmap, bbp, &m_pBitmapBrush);
    }
    

    上面的代码中先创建了bitmapRT,然后在bitmapRT上绘制一个网格的两个边,再从bitmapRT上获取位图,根据位图创建位图画刷。

    下面是绘制部分的代码:

    RECT clientRect;
    GetClientRect(m_hwnd, &clientRect);
    D2D1_RECT_F rc = D2D1::RectF(clientRect.left,clientRect.top,clientRect.right,clientRect.bottom);
    
    // 开始绘制
    m_pRT->BeginDraw();
    
    m_pRT->SetTransform(D2D1::Matrix3x2F::Identity());
    m_pRT->Clear(D2D1::ColorF(D2D1::ColorF::Black));
    
    // 绘制
    m_pRT->FillRectangle(
    	rc,
    	m_pBitmapBrush);
    		
    // 结束绘制
    hr = m_pRT->EndDraw();
    

    绘制的演示效果如下图:

    在这里完整代码代码就不贴出了,有兴趣的朋友可以点击此处下载Demo源码,Demo源码是Direct2DTests目录下的D2DMesh文件。

    三、结语

    这样我们就成功地利用Direct2D绘制出了网格,希望可以帮到大家。

  • 相关阅读:
    ZOJ-3725 Painting Storages DP
    ZOJ-3720 Magnet Darts 计算几何,概率
    ZOJ-3721 Final Exam Arrangement 贪心
    POJ-2096 Collecting Bugs 概率DP
    [转]数据输入加速
    POJ-3468 A Simple Problem with Integers Splay Tree区间练习
    HDU-4419 Colourful Rectangle 矩形多面积并
    POJ-1177 Picture 矩形覆盖周长并
    HDU-1255 覆盖的面积 覆盖的矩形面积并
    POJ-1151 Atlantis 矩形面积并
  • 原文地址:https://www.cnblogs.com/Ray1024/p/6103981.html
Copyright © 2020-2023  润新知