本来是因为工作项目的原因,需要做一个类似“刀光剑影”的特效,类似蓝杖剑圣的效果,因为是动态的,美术出图不太能实现这种效果,所以就想着用opengl的方式实现。
虽然读了不少opengl的书,英文中文的都有,基本每次读都有收获。网上也有不少的opengl教程,读的时候感觉都能理解,但是当自己下手写的时候,有种无从下手的感觉,就在群里问了下思路,大神们回答很简单,就是一个三角形带直接搞定。后来发现cocos2dx已经有一个现成的特效了,就是motionstreak,欣喜之余看了下源码,把自己的想法记录下来与大家共享,水平有限,错误之处请指正,共同进步。
opengles中有三种基本的图元,点线和三角形,点主要用在粒子系统,最常用的就是三角形,我们看到的做工精美的3D模型就是很多三角形组成的,三角形的数量也就决定了模型的精细程度,因为在我们的需求里用三角形就措措有余了,何况还是2d的特效
思路大体如下:我们的这个特效是个三角形带,这个特效不管是跟着刀刃走还是跟着人走(下文我们就把特效跟随的目标,就是这里的人或着刀刃,叫做特效的载体),其实都是动态变化的,也就要求我们动态更新这个三角形带,不断向三角行带中加入定点和移除定点。顶点什么时候移除有两种方式,一种是每个顶点都有个生存周期,过了生命周期的时间就会被移除。第二种是规定一个顶点个数的上限,超过顶点个数就会被移除。cocos2dx里面是通过给每个顶点设置一个生存时间来控制顶点移除的,带回代码里面会讲到。那么如何向三角形带中添加顶点呢,因为这个特效总是跟着载体走,因此我们首先想到应该用载体的位置来生成三角形的顶点加入到三角形带中,cocos2dx里面是把载体的位置放在了 Point* _pointVertexes 里面,而把生成的三角形带中的点放到了 Vertex2F* _vertices 里面。
这里需要注意一下的是,我们不能直接把载体的位置直接加载三角形带中,而是根据这个位置生成两个顶点,这个就是这个动态特效的关键。
那么如何根据一个载体的位置的点生成三角形带中的两个顶点呢?一般是取上一个载体的位置,跟当前载体的位置形成一个向量v1,再计算这个向量的垂直向量v2,因为我们这个特效是有宽度的,创建这个特效的时候会在参数里传入,根据我们传入的宽度stroke,得到v2向量上的两个点,放入到三角形带当中(可以把这两个顶点看做是一个小组,方便我们理解,并且在设置纹理坐标的时候,这两个顶点的v分量是相同的,u分量一个是0,一个是1,大家可以想像一下)。下面的代码中会有注释。依此类推,这样就产生了这个动态变化的三角形带。
这个特效是可以自定义纹理的,因此也就需要设置纹理坐标,上面稍微提到了一下。总的思路就是每次更新完三角形带,根据三角形带中顶点的个数重新设置下v分量。u分量比较简单,非1即0。(这个的u相当于x,v相当于y,并且范围从0到1)
通过OpenGL赋予纹理坐标和纹理贴图就可以画出来了。
啰嗦了这么多,下面是具体的代码。
最重要的两个函数是:
void MotionStreak::update(float delta)
void MotionStreak::onDraw(const kmMat4 &transform, bool transformUpdated)
我们应该从这两个方法入手,显然 update方法是动态更新三角形带的,而onDraw方法则是把当前的三角形带绘制出来。
下一篇主要讲代码。