我所理解的cocos2dx - 精灵

用sprite绘制一个矩形区域

  精灵可以绘制一张纹理或者上面的一个矩形区域,最终会关联一个texture2d对象和上面的一个区域。createWithTexture不使用TextureCache创建纹理,所以需要额外的小心它的生命周期。

  精灵可以通过setTexture来修改关联的纹理,用SpriteFrame来高效播放精灵动画。

  

V3F_C4B_T2F_Quad结构体

  所有对sprite绘制属性的修改最终都是表现为对一个V3F_C4B_T2F_Quad结构体变量quad的修改。此结构拥有4个v3f_c4b_t2f顶点属性(坐标vec3,颜色color4B和纹理坐标tex2F)。opengl es不支持多边形图元,所以一个quad图元实际会分为2个三角形。对于图元修改,我们只需要修改每一个顶点的相关数据即可。

 

使用QuadCommand进行绘制

  每一个sprite生成一个quad,可以和相邻的quadCommand形成自动批绘制。每一帧调用draw的时候,sprite都会通过renderer提供的checkVisiblity来判断自身是否还在视窗可见范围内,不可见则不用发送绘制命令,减少cpu计算,command排序。

 

sprite的绘制属性

颜色混合

  多个图层叠加在一起进行显示的时候,就需要用到颜色混合。

  混合发生在opengl es绘图管线的最后一个阶段 每片元处理。这阶段是根据一些参数设置和条件对每一个片元执行测试和修改。

 

源,目标和缓冲区

  光栅化产生的片段的颜色值称为 源,缓冲区对应的位置的颜色值称为目标,混合模式就是将源上的rgba和目标的rgba通过一定的公式进行混合计算。

 

混合计算

  取决于混合计算方程和混合模式。混合计算方程定义了源和目标对应通道值按怎样的公式进行计算,每个通道取值的权重则由混合模式来定义。

  BlendEquation(enum mode) 和 BlendEquationSeparate(enum modeRGB, enum modeAlpha)制定rgb和alpha通道的计算方程,前者同时制定两者。他们必须为这几个值里FUNC_ADD,FUNC_SUBTRACT, FUNC_REVERSE_SUBTRACT。

d和s是目标和源上该通道的取值权重系统,由BlendFuncSeparate(enum srcRGB, enum dstRGB, enum srcAlpha, enum dstAlpha), BlendFunc(enum src, enum dst)决定。

默认情况下,GL_FUNC_ADD是BlendEquation的默认值,通常用来实现反锯齿,绘制半透明纹理和其他一些效果。cocox2dx里Sprite的_blendFunc默认为{GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}。

 

混合与深度测试

  深度测试在混合之前发生。如果全是非透明的图元,则按照深度测试选择颜色即可。如果有透明图元,则先绘制非透明的图元,再按深度从后到前绘制半透明

 

颜色叠加

  叠加一个颜色值到一个图层自身的每一个颜色通道上,例如角色被打后的闪烁红色效果。对node作用一个颜色叠加,这些效果会沿着ui树逐层向下作用每一个元素。

 

node的颜色叠加

  node里和cascade相关的方法就是用颜色叠加的。

  realColor记录真实的颜色,realOpacity记录真实透明度.displayColor 和 displayOpacity是叠加颜色后的绘制颜色属性。叠加公式是对应通道的值相乘。 _displayerColor.r = _realColor.r*parentColor.r/255 ...,设置了cascade的属性话,就会向下传递叠加。

 

精灵颜色的叠加

  在片段着色器中进行颜色叠加。计算出叠加的值存在定点数组quad里。默认的displayedColor是白色。片段着色器中,sprite的displayeColor最终叠加到每一个从纹理采样的片段。

 

alpha预乘

  半透明精灵的显示要纹理颜色值*alpha 和 背景颜色值乘以(1-alpha)计算出显示的像素颜色值。为了减少组合时候的计算量,可以把rbg存为已经乘以alpha后的值。但这只是一种思路,图片存储格式并不支持,所以需要程序去实现支持。cocos2dx提供了对premultiplied的支持,假设我们 传入一张已经预乘过的图:

  1.设置sprite的blendfunc使用。修改blendFunc设置为{gl_one, gl_one_minus_src_alpha}就可以正确显示纹理,但需要对每一张图设置

  2.构造Image的时候设置preMulti属性,他默认为false

  3.针对pvr格式的纹理PVRImagesHavePremultipliedAlpha(bool)

  预乘的缺点是当我们向用原来的颜色时,会导致质量损失,失真,所以应该谨慎使用。

 

精灵表

  就是把精灵纹理拼接在一起,常见的是plist,json和xml配合使用,通过配置表制定好每一个精灵帧的纹理大小和范围。cocos2dx使用SpriteFrameCache来加载,里面存的都是一个个的SpriteFrame,可以用来构成精灵。

 

精灵动画
  分开关键帧动画和骨骼动画,使用配置表控制表现,一般由设计师导出。

 

批绘制还是自动批绘制

  批绘制就是cocos2dx 3.0后加入的新功能,是由于元素不做绘制,只生成绘制命令这一架构产生的。其要求我们使用同一张纹理,相同的BlendFunc设置和相同的Shader程序。而老版本也提供了一个批绘制的功能,就是SpriteBatchNode。

 

SpriteBatchNode 

  其addChild限制了使用同一个Texture2D才能加入成为子对象,visit方法阻止了元素向下遍历,把绘制工作交给自己处理。其会使用BatchNodeCOmmand将绘制命令发送到RenderQueue,把子对象进行批绘制。

 

TextureAtlas

  SpriteBathNode实际上是使用TextureAtlas存储所有的子精灵顶点信息。其包含一个v3f_c4b_t2f_quad数组和一个Texture2d对象,提供对quad数组的增删改查。这样,SpriteBatchNode所做的只是把子元素顶点信息存储到TextureAtlas中。最后TextureAtlas提供绘制quads方法,通过BatchCommand的drawQuads绘制。此外,还有label,tilemap等元素都是通过这个实现。

  但这个东西限制很多,例如不能单独设置sprite,层级得相邻,不能是其他层级的元素间混合。

  应用:九宫格

 

posted on 2017-07-08 13:59  usp10  阅读(1140)  评论(1编辑  收藏  举报

导航