本文翻译自《Integrating LiquidFun with Cocos2d-x: Part II》
在第一部分中,介绍了如何在Cocos2d-x中集成LiquidFun。本文(第二部分)将介绍如何使用一个基本的水效果来渲染粒子效果。
第一部分中,使用glDrawArrays(GL_POINTS, 0, total);来绘制粒子系统。这个函数可用于绘制粒子,但是不能绘制“水”。
绘制“水”需要更复杂的渲染算法,就如这个例子中使用的算法。本文将介绍一个类似的算法。
算法功能
1.选择一个白色的圆圈,并使其模糊化
你可以在运行时使这个圆圈模糊化
你也可以在离线时使其模糊化
2.创建一个新的帧缓存(例如,一个用于渲染的off-screen缓冲区)
3.在新创建的帧缓冲区,使用上述模糊化的圆圈渲染例子效果
4.在主颜色缓冲区使用一个阈值渲染帧缓存。阈值可以是这样的:
如果pixel.r < 0.1, 去掉像素(不绘制这个像素)
如果pixel.r < 0.2, 绘制蓝色像素(作为边界)
其他,绘制白色像素(作为水的内部)
如何使用Cocos2d-x和LiquidFun实现
对第一部分中的LFParticleSystemNode进行扩展:
首先在LFParticleSystemNode类中添加“off-screen”帧缓冲。Cocos2d-x中在RenderTexture类中创建这个“off-screen”缓冲区。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
bool
LFParticleSystemNode::init(b2ParticleSystem* particleSystem,
float
ratio)
{
// create an off-screen frame-buffer with the size of the screen
auto s = Director::getInstance()->getWinSize();
_renderTexture = cocos2d::RenderTexture::create(s.width, s.height, Texture2D::PixelFormat::RGBA8888);
this
->addChild(_renderTexture);
_renderTexture->setAnchorPoint(Point::ANCHOR_MIDDLE);
_renderTexture->setPosition(Point(s.width/2, s.height/2));
// Change the default shader. Use a the threshold shader
auto program = GLProgram::createWithByteArrays(_renderTextureShaderVert, _renderTextureShaderFrag);
auto programState = GLProgramState::getOrCreateWithGLProgram(program);
programState->setUniformFloat(
"u_threshold_discard"
, 0.15);
programState->setUniformFloat(
"u_threshold_border"
, 0.3);
}
|
另外,正如之前提到的,RenderTexture(off-screen帧缓冲)需要一个着色器阈值。定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform
float
u_threshold_discard;
uniform
float
u_threshold_border;
void
main()
{
vec4 color = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
if
( color.r < u_threshold_discard)
// black or discard
color = vec4(0,0,0,0);
else
if
( color.r < u_threshold_border)
// blue for the border
color = vec4(0.2,0.2,0.9,1);
else
// white for the center
color = vec4(1,1,1,1);
gl_FragColor = color;
}
|
在运行时定义uthresholddiscard和uthresholdborder的值。这个例子中,值分别为0.15和0.3。
其次,在RenderTexture类中渲染粒子:
1
2
3
4
5
6
7
8
9
10
11
12
|
void
LFParticleSystemNode::draw(Renderer *renderer,
const
Mat4 &transform, uint32_t transformFlags)
{
// tell RenderTexture to "capture" the particles
_renderTexture->beginWithClear(0,0,0,0);
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(LFParticleSystemNode::onDraw,
this
, transform, transformFlags);
renderer->addCommand(&_customCommand);
// tell RenderTexture to stop "capturing" the particles
_renderTexture->end();
}
|
运行结果:
进一步改善
以上所描述的是渲染水的简单算法。但是,更高级和渲染效果更好的算法可以通过同样的原则实现:
在off-screen缓冲区渲染模糊(或其他效果)的粒子。
使用特殊的着色器渲染off-screen缓冲区。
Google提供的官方例子“LiquidFun–EyeCandy”使用了更复杂的着色器,包括照明、折射以及背景扭曲。
在Cocos2d-x 3.1及以上版本中自定义着色器
Cocos2d-x 3.1提供了一个自定义着色器的新方法。与3.0版本中的GLProgram类似,但是如果你想要添加自定义属性或者外观,不需要使用GLProgram类,你可以使用GLProgramState类定义。
GLProgram类仍可用,但是推荐使用GLProgramState类,如下:
1
2
3
4
5
6
7
8
|
// you create a GLProgram like in v3.0
GLProgram* glprogram = GLProgram::createWithByteArrays(_particleShaderVert, _particleShaderFrag);
// and then you create a GLProgramState with it
GLProgramState* glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
// attach the ProgramState to a Node
sprite->setGLProgramState( glprogramstate );
|
接下来就是使用GLProgramState API来添加自定义外观或者属性。
添加自定义外观:
1
2
3
4
5
6
7
8
9
10
|
// setting a float
glprogramstate->setUniformFloat(
"u_name_1"
, 0.15f);
// setting a vec2
glprogramstate->setUniformVec2(
"u_name_2"
, Vec2(0.2, 0.3));
// setting a callback
glprogramstate->setUniformCallback(
"uniform_name_2"
, [](GLProgram* program, Uniform* uniform){
glUniform4fv( uniform->location, 10, _buffer);
});
|
添加自定义属性:
1
2
3
4
5
6
7
|
// setting an attribute pointer
glprogramstate->setVertexAttribPointer(
"a_position"
, 2, GL_FLOAT, GL_FALSE, 0, _particleSystem->GetPositionBuffer());
// setting a callback
glprogramstate->setVertexAttribCallback(
"a_color"
, [](VertexAttrib* vertexAttrib) {
glVertexAttrib4f(vertexAttrib->index, 0.2, 0.8, 0.7, 1.0);
});
|
下载并运行例子
复制 Cocos2d-x Samples 仓库,并按照其向导进行。然后运行“LiquidFun – EyeCandy” demo。
1
|
$ git clone https:
//github.com/cocos2d/cocos2d-x-samples.git
|
按照此网站说明,然后运行:
1
2
|
$ cd samples/LiquidFun-EyeCandy/proj.ios_mac
$ open LiquidFun-EyeCandy.xcodeproj
|
PS:以上为全文翻译,有不够准确的地方,敬请勘误。