【官方教程】《捕鱼达人3》系列 IV:如何打造旋涡特效

大家好,经过前面三节课的学习,我们已经可以将鱼加载到游戏中进行显示,并且做出鱼在水中受波光影响的效果,也学会了如何产生闪电链。这一节课,我们来学习一下如何开发旋涡特效。

在《捕鱼达人3》里,有这样一个效果,它实现了对屏幕画面进行旋转扭曲,感觉就像带着玩家通过旋涡进入了海底的世界。如图:

da65b894b0ca61f80fad7930527b00b8.jpeg

看起来是不是很流弊!具体怎么实现呢?哈哈,现在我们来学习一下。

要现实这样的效果主要分为三个步骤:

一.将屏幕画面渲染到一张纹理上。

二.创建一个平面网格模型,然后将第一步取得的纹理做为贴图传入一个顶点纹理坐标扭曲Shader进行渲染。

三.随着时间的增加,更新Shader中顶点纹理坐标扭曲的角度和半径。

为了方便使用,我们创建一个基于Layer的派生类,命名为VortexLayer,然后我们在其中加入一个CCRenderTexture成员指针,在初始化时创建为屏幕大小,通过它我们在draw的时候将目标Layer结点中的所有物体绘制到它的纹理中。

void VortexLayer::draw(Renderer* renderer, const Mat4 &transform, uint32_t flags)

{

if( m_pTarget && m_TargetLayer)

{

m_pTarget->clear(0,0,0,0);

m_pTarget->begin();

m_TargetLayer->visit();

m_pTarget->end();

}

}

然后我们需要加入一个Mesh成员对象指针,并设置它的顶点数据,使它在形成一个与屏幕大小相等的平面网格。

auto visibleSize = Director::getInstance()->getVisibleSize();

//行,列数

int cows = 100;

int rows = 100;

//每一行,列的顶点位置偏移

float vertexStepX = visibleSize.width/cows;

float vertexStepY = visibleSize.height/rows;

//第一行,列的纹理坐标偏移

float uStep = 1.0/rows;

float vStep = 1.0/cows;

//顶点,法线,色,纹理的容器

vector<float> positions;

vector<float> normals;

vector<float> colors;

vector<float> texs;

for ( unsigned int x = 0; x <= cows; ++x )

{

for ( unsigned int y = 0; y <= rows; ++y )

{

unsigned int offset = x + y * ( cows + 1 );

positions.push_back(x*vertexStepX);

positions.push_back(y*vertexStepY);

positions.push_back(10);

texs.push_back(x*uStep);

texs.push_back(y*vStep);

}

}

std::vector<unsigned short> tTriangle;

for ( unsigned int x = 0; x < cows; ++x )

{

for ( unsigned int y = 0; y < rows; ++y )

{

unsigned short* ptr = &(m_IndiceArray[(x+y*cows)*6]);

tTriangle.push_back((x+0) + (y+0)*(cows+1));

tTriangle.push_back((x+0) + (y+1)*(cows+1));

tTriangle.push_back((x+1) + (y+0)*(cows+1));

tTriangle.push_back((x+0) + (y+1)*(cows+1));

tTriangle.push_back((x+1) + (y+1)*(cows+1));

tTriangle.push_back((x+1) + (y+0)*(cows+1));

}

}

//创建模型

m_RenderMesh = Mesh::create(positions,normals,texs,tTriangle);

m_RenderMesh->retain();

//设置顶点格式

long offset = 0;

auto attributeCount = m_RenderMesh->getMeshVertexAttribCount();

for (auto k = 0; k < attributeCount; k++) {

auto meshattribute = m_RenderMesh->getMeshVertexAttribute(k);

m_ProgramState->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib],

meshattribute.size,

meshattribute.type,

GL_FALSE,

m_RenderMesh->getVertexSizeInBytes(),

(GLvoid*)offset);

offset += meshattribute.attribSizeBytes;

}

m_meshCommand.genMaterialID(0, m_ProgramState, m_RenderMesh, m_BlendFunc);

这样模型网格就创建好了,下面我们重点研究一下所需要的Shader文件Vortex.vsh:

// 输入的顶点格式

attribute vec4 a_position;

attribute vec2 a_texCoord;

//输出给PS的变量

varying vec2 v_texCoord;

//用户自定义的变量

uniform float radius ;

uniform float angle ;

//旋涡的计算函数

vec2 vortex( vec2 uv )

{

//先减去贴图中心点的纹理坐标,这样是方便旋转计算

uv -= vec2(0.5, 0.5);

//计算当前坐标与中心点的距离。

float dist = length(uv);

//计算出旋转的百分比

float percent = (radius - dist) / radius;

if ( percent < 1.0 && percent >= 0.0)

{

//通过sin,cos来计算出旋转后的位置。

float theta = percent * percent * angle * 8.0;

float s = sin(theta);

float c = cos(theta);

uv = vec2(dot(uv, vec2(c, -s)), dot(uv, vec2(s, c)));

}

//再加上贴图中心点的纹理坐标,这样才正确。

uv += vec2(0.5, 0.5);

return uv;

}

void main()

{

//计算出顶点的位置

gl_Position = CC_MVPMatrix * a_position;

//调用函数计算出纹理坐标

v_texCoord = vortex( a_texCoord );

}

在draw函数中通过计算时间间隔来不断的修改角度和半径的值,就可以实现顶点的UV值绕贴图中心点旋转的效果了:

//计算时间间隔

timeval currtime;

gettimeofday( &currtime, nullptr);

float dt = (currtime.tv_sec - m_lasttime.tv_sec) + (currtime.tv_usec - m_lasttime.tv_usec) / 1000000.0f;

if ( m_Time < m_maxTime )

{

setAngle( getAngel()+m_angleSpeed*dt );

setRadius( getRadius()+m_radiusSpeed*dt );

m_Time += dt;

}

else

{

m_Time = 0.0;

setAngle( 0.0f );

setRadius( 0.0f );

}

m_lasttime = currtime;

//设置Shader的参数。

GLProgramState* programstate = getGLProgramState();

programstate->setUniformFloat("radius",m_radius);

programstate->setUniformFloat("angle",m_angle);

programstate->setUniformTexture("u_texture", m_pTarget->getSprite()->getTexture());

现在我们运行一下,就可以看到这个旋涡了。

416b3f00327cba55ce9a08c490ee73ed.jpeg

至此,我们完成了《捕鱼达人3》第一波4篇教程的分享,不知大家有没有收获呢?大家还希望看到哪方面的教程呢?欢迎提出意见与建议!

若有对Cocos引擎3D技术感兴趣的X-Men,也欢迎联系官方团队,参与探讨并获取技术支持。技术交流邮箱:lvlong@chukong-inc.com。

9882a650483142a4d41dc8be552ef94f.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值