转自:http://blog.ch-wind.com/cocos2d-x%E4%B8%ADmask%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8F%8A%E4%BC%98%E5%8C%96/

关于cocos2d-x内的Mask来做类似光点或者视野控制等功能的思路,最早是在一篇外文上看到的。拿来用过之后发现效果还是不错,于是直接放进了程序里。可是在实际运用时发现其运行效率不是那么理想,尤其是以pc平台为目标时由于配置不同造成的帧率下降比较明显。对代码进行分析之后发现,Mask的功能使用的是CCRenderTexture动态生成纹理并覆盖在目标层上的。在每一次绘制中,这个纹理都会重新生成一次,这就造成了极大的效率上的浪费。同时CCRenderTexture貌似使用了FBO,在某些旧的显卡上会引发极大的帧率丢失。

于是着手对其进行改造,事实上之所以要每次循环都重新生成纹理是因为mask本身的位置会不断更新。而如果打算单独使用sprite+glblencfunc来解决的话,由于绘制顺序的关系很难找到一个好的动态mask解决方案。当然准备一个大概四倍视口的mask图片是可以的,但是这样的话效率也比较低下,只能留作备选方案。

最终选择的解决方案是使用clippingnode,clippingnode是使用模板测试来实现的,这是gl的基础功能,不会对硬件有太大的需求。以一个CCColorlayer为Clipping的content,首先进行模板测试,然后再叠加作为遮罩的sprite就好了。

csb_st = CCSpriteBatchNode::create("Images/circle.png");

cp_board = CCClippingNode::create();
cp_board->setContentSize(visibleSize);
cp_board->setPosition(CCPointZero);
cp_board->setAnchorPoint(CCPointZero);
cp_board->setStencil(csb_st);
cp_board->setInverted(true); ////////////////////////////////////////////////////////////////////////// CCLayerColor* clc = CCLayerColor::create(ccc4BFromccc4F(m_renderColor),visibleSize.width,visibleSize.height);
clc->setAnchorPoint(CCPointZero);
clc->setPosition(CCPointZero);
cp_board->addChild(clc); //content
cn_borad->addChild(cp_board,m_iLaDep+); CC_BREAK_IF(!f_refresh_circles());

sprite的话使用传说中的经典地图遮罩blend就好了:

ccBlendFunc cbf = {GL_DST_COLOR, GL_ZERO};

cns_blocks = CCSpriteBatchNode::create("Images/circle.png");
cns_blocks->setBlendFunc(cbf);
cp_board->addChild(cns_blocks); ////////////////////////////////////////////////////////////////////////////
m_AkaruCircle = CCSprite::create("Images/circle.png");
m_AkaruCircle->setBlendFunc(cbf);
m_AkaruCircle->setPosition(ccp(,));
m_AkaruCircle->setScale();
m_Board->addChild(m_AkaruCircle,m_iLaDep);

当然,这样的话由于GLZERO的blend结果是(0,0,0,0),如果不是做纯黑的不透明遮罩,即便精心的准备遮罩图片,多少还是会有一些违和感存在,如果出现这种情况而无法从其他方面进行修正的话,还是必须使用rendertexture。由于rendertexture的效率因素,我们必须尽量减少其负担,只是对sprite进行处理,除非需要动态改变遮罩的背景色,我们都不会对sprite进行重新生成。

ccBlendFunc cbf = {GL_ZERO, GL_ONE_MINUS_SRC_ALPHA};

CCSprite* t_sp = CCSprite::create("Images/circle.png");
t_sp->setPosition(CCPointZero);
t_sp->setAnchorPoint(CCPointZero);
t_sp->setBlendFunc(cbf); CCSize vs = t_sp->getContentSize();
CCRenderTexture* t_crt = CCRenderTexture::create(vs.width, vs.height);
t_crt->beginWithClear(m_renderColor.r, m_renderColor.g, m_renderColor.b, m_renderColor.a); t_sp->visit(); t_crt->end(); m_AkaruCircle = CCSprite::createWithTexture(t_crt->getSprite()->getTexture());
//m_AkaruCircle->autorelease();
m_AkaruCircle->setScale();
m_Board->addChild(m_AkaruCircle,m_iLaDep);

这样一来Mask的总体效率就是一次模板测试加上两次spritebachnode的绘制,可以作为频繁使用CCRenderTexture的替代方案使用了。代码如下,由于目前的代码结构的关系,要测试的话spotlight类需要被继承,然后在适当的地方调用f_init才行。

cocos2d-x Mask的实现及优化的更多相关文章

  1. CVPR2019 | 超越Mask R-CNN!华科开源图像实例分割新方法MS R-CNN

    安妮 乾明 发自 凹非寺 本文转载自量子位(QbitAI) 实习生又立功了! 这一次,亮出好成绩的实习生来自地平线,是一名华中科技大学的硕士生. 他作为第一作者完成的研究Mask Scoring R- ...

  2. 论文阅读笔记二十三:Learning to Segment Instances in Videos with Spatial Propagation Network(CVPR2017)

    论文源址:https://arxiv.org/abs/1709.04609 摘要 该文提出了基于深度学习的实例分割框架,主要分为三步,(1)训练一个基于ResNet-101的通用模型,用于分割图像中的 ...

  3. 如何优化cocos2d程序的内存使用和程序大小

    在我完成第一个游戏项目的时候,我深切地意识到"使用cocos2d来制作游戏的开发者们,他们大多会被cocos2d的内存问题所困扰".而我刚开始接触cocos2d的时候,社区里面的人 ...

  4. (译)如何优化cocos2d程序的内存使用和程序大小:第二部分(完)

    前言:从上周发布教程的微博反应情况来看,cocos2der们对于游戏的内存问题还是非常关心的.本文是上一篇博文的续,旨在教大家如何减少cocos2d程序的大小. 全文如下: 减少你的程序的大小 把纹理 ...

  5. 如何优化cocos2d程序的内存使用和程序大小:第一部分

    译者: 在我完成第一个游戏项目的时候,我深切地意识到“使用cocos2d来制作游戏的开发者们,他们大多会被cocos2d的内存问题所困扰”.而我刚开始接触cocos2d的时候,社区里面的人们讨论了一个 ...

  6. 在cocos2d里面如何使用Texture Packer和像素格式来优化spritesheet

    免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作 ...

  7. cocos2d 如何优化内存使用

    如何优化内存使用 内存优化原理 为优化应用内存使用,开发人员首先应该知道什么最耗应用内存,答案就是纹理! 纹理几乎会占据90%应用内存.所以尽量最小化应用的纹理内存使用,否则应用很有可能会因为低内存而 ...

  8. 如何优化cocos2d程序的内存使用和程序大小:第一部分_(转)

    译者: 在我完成第一个游戏项目的时候,我深切地意识到“使用cocos2d来制作游戏的开发者们,他们大多会被cocos2d的内存问题所困扰”.而我刚开始接触cocos2d的时候,社区里面的人们讨论了一个 ...

  9. 如何优化cocos2d/x内存使用和程序大小的程序

    从最初的:http://www.himigame.com/iphone-cocos2d/1043.html 译者: 在我完毕第一个游戏项目的时候.我深切地意识到"使用cocos2d来制作游戏 ...

随机推荐

  1. busybox filesystem matrix-gui-2.0 undefined function json_encode()

    /******************************************************************************** * matrix-gui-2.0 u ...

  2. ffmpeg+rtsp+dss

    1. push stream to dss ffmpeg -f mpegts -re -i film.v -c:v libx264 -s 352x288 -aspect 4:3 -b:v 300k - ...

  3. Android 中屏幕点击事件的实现

    在Android中如何用代码触发按钮点击事件?我想要触发代码执行按钮点击.实现对于单击按钮事件的模拟,触发单击按钮进入另一个界面. 就是声明一下什么moonlightcheese被声明了:在andro ...

  4. golang语言部分保留字的举例

    golang和c的代码有很大不同的,一不小心就会误用. 1 /* go保留字: */ /* break default func interface select case defer go map ...

  5. 浅析基层检察院派驻乡镇检察室的健康发展 z

    时间:2011-03-22 10:08 作者:祝志方 新闻来源:正义网 一.前言 在我国,基层检察院派驻乡镇检察室的发展经过了一个曲折发展的历程,上世纪80年代,随着经济社会的发展,一批乡镇检察室应运 ...

  6. Jin Ge Jin Qu hao

    题意: n首歌和一首经典歌已知其长度,一首歌开始唱必须唱完,现在已知剩余时间,求最多能唱歌的个数并保证唱歌时间总长最大 分析: 留最后一个时间唱经典,然后对剩下的时间用背包求出最大个数,并求出总长最大 ...

  7. CCMoveTo 等函数理解

    CCMoveTo: 使用CCMoveTo action来让对象从右侧屏幕外移动到屏幕左侧.注意可以通过指定duration参数控制这一过程需要多久,这里我们随机给他2-4秒的时间. CCCallFun ...

  8. 【LR】关于宽带与比特之间的关系

    1.比特=bps 2M比特的意思是2宽带 1M宽带=12M比特=1*1024K比特=1*1024*1024比特=1057648比特 2M宽带=2*1024*1024比特=2097152比特 4M宽带= ...

  9. C ~ 一个串口接收思路

    void uart_rx_isr(void) //接收中断函数 { uchar c; c=SBUF;//c等于接收的字节: switch (recv_state) { : if (c==0x02) / ...

  10. 通过SQL进行远程访问

    通过SQL语句访问远程数据库 1.得建立链接服务器:  --删除链接服务器 if exists(select * from master.dbo.sysservers where isremote=0 ...