Cocos2d-x 使用nanovg绘画库

云里来.雾里去2014-09-28 14:35:24281 次阅读

在《Cocos2d-x反走样画线》一文中已经介绍了Cocos2d-x的绘画方法,但是这些方法还是只能绘制一些比较简单的东西,没有办法满足高级的需求,比如像html canvas 提供的一些绘画方法就没办法支持。


所以最近一直在寻找跨平台绘画的库,找到的都是一些比较出名的C++绘画库,比如cairo、skia、agg 等,但是这些库都有个比较大的缺点就是 过于庞大,不适用于放到Cocos2d-x中,而且看到除了skia,其他的都没有怎么更新了。想过分离skia核心的部分来用,但是尝试了下还是算了。


比较幸运的是尝试了上面的库后,发现了一个非常不错的轻量级矢量图绘画库:


nanovg

Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.

The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you’re up to speed with NanoVG in no time.


nanovg 非常轻量级,只有一个.c文件加几个.h文件,代码量也不过3000多行。

但是他支持的功能确实非常多:反走样绘制,设置笔帽样式,渐变色,路径等等。

并且他可以通过宏设置当前opengl版本,gl2, gl3, gles2, gles3。

1411884264974669.jpg


编译 nanovg

源码下载:nanovg-master.zip

Github地址:https://github.com/memononen/nanovg


nanovg使用premake工具来生成编译文件,Mac平台安装只需要运行brew install premake即可完成安装。

然后cd到nanovg目录,执行premake4 –help可以看到支持生成的工程文件选择premake4 xcode3

可以在nanovg/build目录下找到生成的工程文件。

这是编译后运行的demo截图,gif效果有折扣,看上面的截图会比较清晰(点击这里看大图)。

navovg-2-200.gif

在Cocos2d-x中使用

为了测试nanovg在Cocos2d-x中使用效果,做了个小demo。

先上 Demo效果图(点击这里看大图):

navovg-1-300.gif

git 地址:https://github.com/2youyouo2/nanovg-test.git


因为nanovg足够轻量,所以直接将它的代码包含进工程基本就可直接使用。

1
2
3
4
5
6
7
8
9
10
11
#include "nanovg.h"
 
// 移动平台使用 gles2, 桌面平台使用gl2
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#define NANOVG_GLES2_IMPLEMENTATION
#else
#define NANOVG_GL2_IMPLEMENTATION
#endif
 
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"


创建 context 也需要根据平台区分

1
2
3
4
5
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
     vg = nvgCreateGLES2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#else
     vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif


绘画函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
void  HelloWorld::onDraw( const  Mat4 &transform, uint32_t flags)
{
     auto origin =  Director::getInstance()->getVisibleOrigin();
     
     nvgBeginFrame(vg, width, height, 1);
     
     // draw background
     nvgBeginPath(vg);
     nvgRect(vg, 0,0, width,height);
     nvgFillColor(vg, nvgRGBA(255,255,255,255));
     nvgFill(vg);
     
     nvgStrokeColor(vg, nvgRGBA(0,0,0,50));
     for  ( int  i=0; i<nbPts-1; i++) {
         for  ( int  j=i+1; j<nbPts; j++) {
             if  (dist(x[i], y[i], x[j], y[j])<RADIUS+10) {
                 nvgBeginPath(vg);
                 nvgMoveTo(vg, x[i], y[i]);
                 nvgLineTo(vg, x[j], y[j]);
                 nvgStroke(vg);
                 nbConnex[i]++;
                 nbConnex[j]++;
             }
         }
     }
     
     for  ( int  i=0; i<nbPts; i++) {
         angle[i] += speed[i];
         x[i] = ease(x[i], width/2 +  cos (angle[i]) * rad[i], 0.1);
         y[i] = ease(y[i], height/2 +  sin (angle[i]) * rad[i], 0.1);
         diam[i] = ease(diam[i], min(nbConnex[i], 7)*max(0.5,(rad[i]/RADIUS/5.0)), 0.1);
         
         nvgBeginPath(vg);
         nvgFillColor(vg, nvgRGBA(0,0,0,100));
         nvgEllipse(vg, x[i], y[i], diam[i] + 3, diam[i] + 3);
         nvgFill(vg);
         
         nvgBeginPath(vg);
         nvgFillColor(vg, nvgRGBA(0,0,0,255));
         nvgEllipse(vg, x[i], y[i], diam[i], diam[i]);
         nvgFill(vg);
         
         nbConnex[i] = 0;
     }
     
     nvgBeginPath(vg);
     nvgMoveTo(vg, 0,0);
     nvgLineTo(vg, 100, 40);
     nvgStrokeColor(vg, nvgRGB(255,255,255));
     nvgStrokeWidth(vg, 3);
     nvgStroke(vg);
     
     nvgEndFrame(vg);
     
     GL::bindTexture2D(0);
     GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_NONE);
     
     GL::useProgram(0);
}


nanovg api都以 nvg 前缀开始,使用类似于 html canvas。

绘画必须包含在nvgBeginFrame和nvgEndFrame之中。

1
2
// width, height 表示绘画区域,最后一个参数是指定像素比例,在高清设备上可以设置2来使绘画更清楚
nvgBeginFrame(vg, width, height, 1);


需要注意的是nvgEndFrame内部会调用gl函数清除gl状态,但是Cocos2d-x默认是做了gl状态缓存的。

比如GL::useProgram中会判断缓存状态有没有更改来决定是否执行gl函数

1
2
3
4
5
6
7
8
9
10
11
void  useProgram( GLuint program )
{
#if CC_ENABLE_GL_STATE_CACHE
     if ( program != s_currentShaderProgram ) {
         s_currentShaderProgram = program;
         glUseProgram(program);
     }
#else
     glUseProgram(program);
#endif // CC_ENABLE_GL_STATE_CACHE
}

这样就会造成nvgEndFrame直接清除了gl状态,但是没有修改cocos2dgl缓存状态,导致Cocos2d-x绘制错误。


所以需要在后面手动清除cocos2dgl缓存状态,如果出现绘制问题,很可能是有些缓存状态没有清除

1
2
3
GL::bindTexture2D(0);
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_NONE);
GL::useProgram(0);

更简单的方法就是直接设置CC_ENABLE_GL_STATE_CACHE为0。


processing

在这个demo中还使用了另外一个库,processing的C++版本


Processing是一种具有革命前瞻性的新兴计算机语言,它的概念是在电子艺术的环境下介绍程序语言,并将电子艺术的概念介绍给程序设计师。它是Java语言的延伸,并支持许多现有的Java语言架构,不过在语法(syntax)上简易许多,并具有许多贴心及人性化的设计(摘自百度百科)。


processing提供了比较简单了方法做出十分酷炫的东西,他有许多优秀的扩展版本,比如:paper.js,p5.js,processing.js


其中paper.js是我比较喜欢的一个版本。


http://openprocessing.org/是一个可以在线编辑processing的网站,其中许多demo都非常酷炫,即使不使用processing语言也可以从上面获取到灵感或是找到相关算法。


cprocessing如其名,是processing的一个C++版本,也比较轻量,他没有移植所有processing功能,只是一些基本的函数。


来源网址:http://cocokele.com/cocos2d-x_nanovg_lib/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值