博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在使用 CCRenderTexture、shader 绘制几何图元时需要注意的一些细节问题
阅读量:4958 次
发布时间:2019-06-12

本文共 4912 字,大约阅读时间需要 16 分钟。

一直对 cocos2d 的 opengl 混合机制不太明晰,昨日纠查 bug 的时候连带着注意了一下,

CCNode 中包含了一个 m_glServerState 的成员,这个东西是与 混合开启与否相关联的,

混合默认是开启的。

CCLayerColor、CCSprite 等类型里面包含了一个 m_blendFunc 成员,这个东西是与采用怎么样的混合方式相关联的。

在 CCProtocols.h 的 CCBlendProtocol 的 @brief 注释里面可以看到,

默认是采用 {GL_ONE, GL_ONE_MINUS_SRC_ALPHA} 或 

{GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA} 的混合方式,选择哪种与 premultiplied alpha 相关。

当一个场景被绘制的时候,会根据子节点的 z 值来决定绘制的先后顺序,

在具体绘制某个可视子节点的时候,会根据该节点的 m_blendFunc 成员来决定用什么样的方式混合。

cocos2d 只是对 opengles 简化使用的一种封装!这里存在一个问题:

在 CCRenderTexture 上面绘制东西的时候,绘制几何图元 或 拿 sprite 对象执行 visit 动作的时候,

如果不调用  glBlendFunc 来指定混合方式的话,就会沿用绘制上一个 sprite 的混合方式。

显然这就让此次操作的结果带有不确定性,因为谁也没办法预料之前绘制的最后一个 sprite 采用的是何种混合方式。

(这里说的有点儿夸张了,实际上很多数情况下都不会对 sprite 的 blendFunc 做设置)

最稳妥的方式就是:在 CCRenderTexture 上面绘制的东西的时候即时设置一下混合方式,消除不确定性

代码:ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

需求多变,但是记住默认的混合参数是没有害处的,默认的为 {GL_ONE, GL_ONE_MINUS_SRC_ALPHA}。

另外一个问题就是,该采用何种的 shader?

毫无疑问,我在刚接触 shader 的时候也是碰了一鼻子灰,

经过一连串开发的磨砺,我才逐渐得以一窥全貌

(不敢托大,这里的全貌指的是有了一个大体的正确认识,gles1都还未能摸透就被迫迁移到2,这令我亚历山大)

cocos2d 缓存了一些常用的 shader,分别是用于一些特别的绘制情形。

打个比方来说,现在有一个需求,要绘制 50 个相同颜色的点,

要达到最高的性能,可以用 kCCShader_Position_uColor 这个枚举值所代表的 shader 来画,

这个 uColor 的 u 表示 uniform,具有 “统一” 的意思,

也就是说,不管花多少个点,都只能采用同一种颜色。

但如果我要绘制五十个不同颜色的点呢?

这确实是个问题,很显然已经超出上面那个缓存的 shader 对象所掌管的能力范围了。

不过这依然不是一个难题,用 kCCShader_PositionColor 从缓存里面拿相应的 shader 就能满足需求了~

具体方式是传入一个长度为 50 的颜色数组,再传入一个长度为 50 的位置数组,然后绘制。

挺能的啊,再出个难题!那五光十色的材质是怎么贴出来的呢?

答案也是  shader,而且是具备贴材质能力的 shader,

具体是那种我就不指明了,自己去摸索吧~

(提示:请于之前提及过的两个枚举值的定义处寻找答案)

又扩展了一些知识,当然这些知识是与主体有所关联的,

因为在 CCRenderTexture 上面绘制东西的时候也有关于 shader 方面的东西要注意,

与混合方式差不多的意思,不过这里的是 shader 是否启用 vertexArrayAttribute

没做仔细测试,不清楚 cocos2d  缓存的 kCCShader_Position_uColor 是否默认就启用了 Position 的 vertexArrayAttribute

同上,为了消除不确定因素,这里最好也是使用一下下面的代码:

ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);

上一些代码来看一看吧(一个专门用来往 RenderTexture 上面画东西的单例类):

ItemRender.h

////  ItemRender.h//  DreamStack////  Created by Bruce Yang on 12-12-26.//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.//#ifndef DreamStack_ItemRender_h#define DreamStack_ItemRender_h#include "cocos2d.h"#include "Box2D.h"USING_NS_CC;class ItemRender {public:    void drawSolidPolygon(const b2Vec2* vertices, int32 vertexCount);        void drawSolidCircle(const b2Vec2& center, float32 radius);        static ItemRender* sharedInstance();    private:    // 采用 cocos2d 缓存的 shader 对象~    void setupCachedShader();        // 采用由自己亲手创建的 shader 对象~    void setupMyShader();        ItemRender();    ~ItemRender();        static ItemRender* m_pItemRender;	CCGLProgram* m_pGLProgram;	GLint m_iColorLocation;};#endif
ItemRender.cpp

////  ItemRender.cpp//  DreamStack////  Created by Bruce Yang on 12-12-26.//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.//#include "ItemRender.h"/** * p~ */void ItemRender::drawSolidPolygon(const b2Vec2* vertices, int32 vertexCount) {        m_pGLProgram->use();	m_pGLProgram->setUniformForModelViewProjectionMatrix();        ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);    ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);        glUniform4f( m_iColorLocation, 1.f, 1.f, 1.f, 1.f);    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices);	glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);    	CHECK_GL_ERROR_DEBUG();}void ItemRender::drawSolidCircle(const b2Vec2& center, float32 radius) {        m_pGLProgram->use();	m_pGLProgram->setUniformForModelViewProjectionMatrix();        ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);    ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);    	const float32 t_fSegsCount = 32.f;	int t_iVertsCount = 32;	const float32 t_fIncrement = 2.f * b2_pi / t_fSegsCount;	float32 theta = 0.f;    	GLfloat glVertices[t_iVertsCount * 2];	for (int32 i = 0; i < t_fSegsCount; ++ i) {		b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));		glVertices[i * 2] = v.x;		glVertices[i * 2 + 1] = v.y;		theta += t_fIncrement;	}    	glUniform4f( m_iColorLocation, 1.f, 1.f, 1.f, 1.f);	glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, glVertices);	glDrawArrays(GL_TRIANGLE_FAN, 0, t_iVertsCount);    	CHECK_GL_ERROR_DEBUG();}#pragma markItemRender* ItemRender::sharedInstance() {    if (!m_pItemRender) {        m_pItemRender = new ItemRender();    }    return m_pItemRender;}void ItemRender::setupCachedShader() {    m_pGLProgram = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_Position_uColor);    m_iColorLocation = glGetUniformLocation(m_pGLProgram->getProgram(), "u_color");}void ItemRender::setupMyShader() {    m_pGLProgram = NULL;    m_iColorLocation = (GLint)0;}ItemRender::ItemRender() {    this->setupCachedShader();}ItemRender::~ItemRender() {    }ItemRender* ItemRender::m_pItemRender = 0;

还有就是,带 ccGL- 前缀的方法都是 cocos2d 封装的一层带缓存作用的方法。

其内部机制也非常简单,就是判断一下当前要改变到的值和老值是否相同,不同的话才去修改该值。

后续还会对 cocos2d-x 2.x,opengles 2.0 做更深入细致的探索,敬请关注~

转载于:https://www.cnblogs.com/java20130723/archive/2012/12/27/3212070.html

你可能感兴趣的文章
linux消息队列编程实例
查看>>
webapi中使用Route标签
查看>>
LeetCode 43 字符串相乘
查看>>
[学习笔记] extends implements 的区别与联系 [转载]
查看>>
PHP的运行机制与原理(底层) [转]
查看>>
网页压力测试工具之Loadrunner
查看>>
MSSQL 视图/事务(TRAN[SACTION])/存储过程(PROC[EDURE])/触发器(TRIGGER )
查看>>
python访问mysql和redis
查看>>
整数中1出现的次数(从1到n整数中1出现的次数)(python)
查看>>
javafx实现一个很有意思的动画
查看>>
javafx实现自定义html编辑器
查看>>
Python自学之乐-继承的新式类与经典类
查看>>
解决新浪微博未安装客户端分享不能带链接问题
查看>>
ionic安装开发环境
查看>>
Java 生成 UUID
查看>>
AWR报告
查看>>
1125. Chain the Ropes (25)
查看>>
Python——Django运行问题
查看>>
编程珠玑
查看>>
x265编译arm平台处理器
查看>>