参考文章:https://www.byjth.com/jiqiao/92.html
本人shader也很水,里面有好多不懂的地方,先说一下,之前那个有几个问题
1、不能使用系统自带的那个shader,系统自带的那个
ccPositionTextureA8Color_vert,这个顶点会计算深度,如果这里的树木用的是GlobalZOrder的话,会有一个深度问题,移动的时候坐标不对。
2、原shader里面是只能在一张texture里面运行的,如果精灵用的是一张组图,运行的时候图片会串,而且组图的坐标不一样。
我这里不清楚怎么使用单独一个图的相对坐标,就只能按照整体的坐标进行计算了。如果有大神清楚 请指正。
Building.h
#ifndef __Building_H__
#define __Building_H__
#include "cocos2d.h"
USING_NS_CC;
class Building :public Node
{
public:
protected:
virtual bool init();
Sprite * m_bg;
//heartSetFunc
void getHeart();
//particle
ParticleSystemQuad* m_par;
//data
BuildingData m_baseData;
static int _tagnum;
//shader
int m_nTimeUniformLocation;
float m_fTime;
};
#endif
Building.cpp
#include "Building.h"
#include "MyRandom.h"
VoidBuildingFunc Building::removeInMap = nullptr;
VoidSpriteFunc Building::setZorderInMapFunc = nullptr;
static const GLchar* szGrassShaderX =
" \n\
#ifdef GL_ES \n\
precision mediump float; \n\
#endif \n\
\n\
varying vec2 v_texCoord; \n\
//uniform sampler2D u_texture; \n\
uniform float u_time; \n\
uniform float u_hight; \n\
uniform float u_mid; \n\
uniform float u_midx; \n\
\n\
// 1 \n\
const float speed = 2.0; \n\
const float bendFactor = 0.2; \n\
void main() \n\
{ \n\
// 获得高度,texCoord从下到上为0到1 \n\
float height = -(v_texCoord.y-u_hight)*2; \n\
float weight = u_midx-abs(u_mid - v_texCoord.x); \n\
// 获得偏移量,一个幂函数,值愈大,导数越大,偏移量愈大 \n\
float offset = pow(height, 2.5)*weight; \n\
// 偏移量随时间变化,并乘以幅度,设置频率 \n\
offset *= (sin(u_time * speed) * bendFactor); \n\
// 使x坐标偏移,fract取区间值(0,1) \n\
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x+ offset , v_texCoord.y))); \n\
//gl_FragColor = texture2D(CC_Texture0, v_texCoord); \n\
}";
static const GLchar* szGrassShader =
" \n\
#ifdef GL_ES \n\
precision mediump float; \n\
#endif \n\
\n\
varying vec2 v_texCoord; \n\
//uniform sampler2D u_texture; \n\
uniform float u_time; \n\
uniform float u_hight; \n\
uniform float u_mid; \n\
uniform float u_midx; \n\
\n\
// 1 \n\
const float speed = 2.0; \n\
const float bendFactor = 0.2; \n\
void main() \n\
{ \n\
// 获得高度,texCoord从下到上为0到1 \n\
float height = (v_texCoord.x-u_hight)*2; \n\
float weight = u_midx-abs(u_mid - v_texCoord.y); \n\
// 获得偏移量,一个幂函数,值愈大,导数越大,偏移量愈大 \n\
float offset = pow(height, 2.5)*weight; \n\
// 偏移量随时间变化,并乘以幅度,设置频率 \n\
offset *= (sin(u_time * speed) * bendFactor); \n\
// 使x坐标偏移,fract取区间值(0,1) \n\
gl_FragColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x , v_texCoord.y+ offset))); \n\
//gl_FragColor = texture2D(CC_Texture0, v_texCoord); \n\
}";
static const GLchar* szGrassShadervsh =
" \n\
attribute vec4 a_position; \n\
attribute vec2 a_texCoord; \n\
attribute vec4 a_color; \n\
\n\
//varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
\n\
void main() \n\
{ \n\
gl_Position = CC_PMatrix * a_position; \n\
//v_fragmentColor = a_color; \n\
v_texCoord = a_texCoord; \n\
}";
bool Building::ini(){
m_bg = Sprite::createWithSpriteFrameName("XXX.png");
addChild(m_bg);
//init shader
m_fTime = CCRANDOM_0_1();
// 加载顶点着色器和片元着色器
GLProgram* pShader = new GLProgram();
float m_baseH;
float m_baseW;
float m_baseWx;
auto txSize = m_bg->getTexture()->getContentSize();
auto bgrect = m_bg->getTextureRect();
if (m_bg->isTextureRectRotated())
{
pShader->initWithByteArrays(szGrassShadervsh, szGrassShader);//顶点着色器,后一个参数则指定了像素着色器:
m_baseH = bgrect.getMinX() / txSize.width;
m_baseW = bgrect.getMidY() / txSize.height;
m_baseWx = bgrect.size.height / (2 * txSize.height);
}
else {
pShader->initWithByteArrays(szGrassShadervsh, szGrassShaderX);//顶点着色器,后一个参数则指定了像素着色器:
m_baseH = bgrect.getMaxY() / txSize.height;
m_baseW = bgrect.getMidX() / txSize.width;
m_baseWx = bgrect.size.width / (2 * txSize.width);
}
m_bg->setGLProgram(pShader);
pShader->release();
CHECK_GL_ERROR_DEBUG();
// 自定义着色器链接
m_bg->getGLProgram()->link();//因为绑定了属性,所以需要link一下,否则vs无法识别属性
CHECK_GL_ERROR_DEBUG();
// 设置移动、缩放、旋转矩阵
m_bg->getGLProgram()->updateUniforms();//绑定了纹理贴图
CHECK_GL_ERROR_DEBUG();
m_nTimeUniformLocation = glGetUniformLocation(m_bg->getGLProgram()->getProgram(), "u_time");
auto m_hight = glGetUniformLocation(m_bg->getGLProgram()->getProgram(), "u_hight");
auto m_mid = glGetUniformLocation(m_bg->getGLProgram()->getProgram(), "u_mid");
auto m_midx = glGetUniformLocation(m_bg->getGLProgram()->getProgram(), "u_midx");
glUniform1f(m_hight, m_baseH);
glUniform1f(m_mid, m_baseW);
glUniform1f(m_midx, m_baseWx);
m_bg->getGLProgram()->use();//调用glUseProgram()方法
// 开启帧更新
this->scheduleUpdate();
return true;
}
void Building::update(float delta)
{
m_fTime += delta;
m_bg->getGLProgram()->use();
glUniform1f(m_nTimeUniformLocation, m_fTime);
}
最后说一句,不要用cocos2dx自带的那个 什么随风抖动的效果,那个东西在小游戏中使用没毛病,如果你场景里面树木很多,用哪个的话就很傻了,能卡出翔,而且不支持GlobalZOrder