如何在Cocos2d-x中集成LiquidFun(二)

本文翻译自《Integrating LiquidFun with Cocos2d-x: Part II


第一部分中,介绍了如何在Cocos2d-x中集成LiquidFun。本文(第二部分)将介绍如何使用一个基本的水效果来渲染粒子效果。

1406857775443454.png

第一部分中,使用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();
}


运行结果:

1406858005877902.jpg

进一步改善

以上所描述的是渲染水的简单算法。但是,更高级和渲染效果更好的算法可以通过同样的原则实现:

  • 在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:以上为全文翻译,有不够准确的地方,敬请勘误。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值