Cocos流体之 LiquidFun流体纹理shader的编写(二)

 

Cocos流体之 集成LiquidFun&&并自定义到CocosFrameWork(一)


贴图效果:

b2_waterParticle:


b2_elasticParticle:



创建b2ParticleSystem

b2ParticleSystemDef particleSystemDef;
    particleSystemDef.dampingStrength = 0.2f;//阻尼
    particleSystemDef.radius = 0.1f;//每个粒子的半径,半径越小模拟程度越高,但同时对硬件性能要求更高
    _particleSystem = _world->CreateParticleSystem(&particleSystemDef);//创建b2ParticleSystem
    _particleSystem->SetGravityScale(0.4f);//重力比例
    _particleSystem->SetDensity(0.8f);//粒子的密度

    b2ParticleGroupDef pd;//粒子组
    pd.position.Set(s.width / 2 / PTM_RATIO, s.height / 2 / PTM_RATIO);
    pd.flags = b2ParticleFlag::b2_waterParticle;
    //pd.groupFlags = b2ParticleGroupFlag::b2_rigidParticleGroup;
    //粒子组的形状,如下粒子组形状为5*6的box(盒子),通俗讲,即创建出一盒子的粒子
    b2PolygonShape shape2;
    shape2.SetAsBox(5.0f, 6.0f, b2Vec2(0.0f, 0.0f), 0.0);
    pd.shape = &shape2;
    _particleSystem->CreateParticleGroup(pd);
//LiquidSprite是自定义类,用于绘制贴图
	auto ls = LiquidSprite::create(_particleSystem, PTM_RATIO);
	this->addChild(ls);




下面是LiquidSprite类的实现:

LiquidSprite::create(_particleSystem, PTM_RATIO);
要传入两个参数,_particleSystem是粒子系统,可用其获取所有粒子的位置、颜色等信息,然后传入Shader作为坐标顶点(a_position)、纹理坐标(a_texCoord)进行着色。

PTM_RATIO是物理坐标与像素坐标的比例关系。


Shader:

vs部分:liquid.vert

attribute vec4 a_position;//需传入所有粒子的坐标
attribute vec2 a_texCoord;//纹理贴图的纹理坐标
uniform vec4 u_color;//颜色混合
uniform float u_pointSize;//传入粒子的大小
uniform float u_ratio;//传入的屏幕坐标系与物理坐标系的比例
uniform vec2 u_texSize;
#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying lowp vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif

void main()
{
    vec4 pos = vec4(a_position.xy*u_ratio, 1, 1); //将物理世界坐标系转化为像素坐标系
    gl_Position = CC_MVPMatrix * pos;
    gl_PointSize = u_pointSize;
    v_fragmentColor = u_color;
	//vec2 newCoord = vec2(clamp(a_texCoord.x, 0.0, 1.0), clamp(a_texCoord.y, 0.0, 1.0));
    v_texCoord = a_texCoord;
}


PS部分:liquid.frag

#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying lowp vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
uniform sampler2D u_texture;//传入Texture2D 纹理贴图
void main()
{
    gl_FragColor = texture2D(u_texture, v_texCoord)*v_fragmentColor;//将纹理采样颜色与v_fragmentColor混合,然后输出
}

创建并应用shader:

auto uTexture = Director::getInstance()->getTextureCache()->addImage("HelloWorld.png");
auto texSize = uTexture->getContentSize();
auto program = GLProgram::createWithFilenames("shader/liquid.vert", "shader/liquid.frag");
auto pState = GLProgramState::getOrCreateWithGLProgram(program);
pState->setUniformTexture("u_texture", uTexture);//纹理贴图传入shader
//pState->setUniformVec2("u_texSize", texSize);//纹理的大小
pState->setUniformVec4("u_color", Vec4(1, 1, 1, 0.7));  //要进行混合的颜色
pState->setUniformVec4("u_ratio", _ratio);
pState->setUniformFloat("u_pointSize", _pSystem->GetRadius()*_ratio*2);//绘制点的大小,粒子半径*比例*2即粒子直径
this->setGLProgramState(pState);//应用Shader

将顶点位置传入Shader:

auto vertsCount = _pSystem->GetParticleCount();//b2ParticleSystem函数,获取粒子数量

posVerts = _pSystem->GetPositionBuffer();//b2ParticleSystem函数,获取粒子位置数组
//顶点转换
for (int i = 0; i < vertsCount; i++)
{
	b2Vec2 vec = posVerts[i];
	texCoords.push_back(Vec2(vec.x * _ratio / texSize.width,
			1 - vec.y * _ratio / texSize.height));
}
	
pState->setVertexAttribPointer("a_position", 2, GL_FLOAT, GL_FALSE, sizeof(Vec2), &posVerts[0]);//传入shader
pState->setVertexAttribPointer("a_texCoord", 2, GL_FLOAT, GL_FALSE, sizeof(Vec2), &texCoords[0]);//传入shader

使用GL_POINTS模式进行绘制:
glDrawArrays(GL_POINTS, 0, posVerts.size());

源码下载: 链接:http://yun.baidu.com/s/1pJEdz8B


你可能感兴趣的:(Cocos,Cocos,Shader,LiquidFun,Box2D,流体)