1.第一种方法针对的是整个图层的渲染
重写visit()函数,并且在visit()函数中直接向CommandQueue添加CustomCommand,设置好回调函数.
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
USING_NS_CC;
class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override;
void onDraw();
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
private:
CustomCommand command;
};
#endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !Layer::init() )
{
return false;
}
// 从Cocos2D-X的shader缓存中取出一个带有position和color顶点属性的shader,然后传给HelloWorld这个Layer
this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
return true;
}
void HelloWorld::visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags)
{
Layer::visit(renderer, parentTransform, parentFlags);
command.init(_globalZOrder);
command.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&command);
}
void HelloWorld::onDraw()
{
// 获取当前的shader
auto glProgram = getGLProgram();
// 使用此shader
glProgram->use();
// 设置该shader的一些内置uniform,主要是MVP,即model-view-project矩阵
glProgram->setUniformsForBuiltins();
auto visiableSize = Director::getInstance()->getVisibleSize();
// 指定将要绘制的三角形的三个顶点
float vertercies[] = { 0,0, //第一个点的坐标
visiableSize.width,0, //第二个点的坐标
visiableSize.width / 2, visiableSize.height}; //第三个点的坐标
// 指定每一个顶点的颜色,颜色值是RGBA格式的,取值范围是0-1
float color[] = { 0, 1,0, 1, //第一个点的颜色,绿色
1,0,0, 1, //第二个点的颜色, 红色
0, 0, 1, 1}; //第三个点的颜色, 蓝色
// 激活名字为position和color的vertex attribute
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
//分别给position和color指定数据源
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertercies);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, 0, color);
//绘制三角形,所谓的draw call就是指这个函数调用
glDrawArrays(GL_TRIANGLES, 0, 3);
//通知cocos2d-x 的renderer,让它在合适的时候调用这些OpenGL命令
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 3);
//如果出错了,可以使用这个函数来获取出错信息
CHECK_GL_ERROR_DEBUG();
}
2.第二种方法针对个别精灵
有时候,我们只要对个别精灵进行特效的处理,这个精灵需要使用我们自己编写的Shader,而图层其他的元素按默认处理就行了。设置好Shader,向精灵添加Shader,最后在重写draw函数,在draw函数中进行特效的处理。代码来自捕鱼达人 第二节 波光处理
bool FishLayer::init()
{
...省略了不相关的代码。
// 将vsh与fsh装配成一个完整的Shader文件。
auto glprogram = GLProgram::createWithFilenames("UVAnimation.vsh", "UVAnimation.fsh");
// 由Shader文件创建这个Shader
auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
// 给精灵设置所用的Shader
m_Sprite->setGLProgramState(glprogramstate);
//创建海龟所用的贴图。
auto textrue1 = Director::getInstance()->getTextureCache()->addImage("tortoise.png");
//将贴图设置给Shader中的变量值u_texture1
glprogramstate->setUniformTexture("u_texture1", textrue1);
//创建波光贴图。
auto textrue2 = Director::getInstance()->getTextureCache()->addImage("caustics.png");
//将贴图设置给Shader中的变量值u_lightTexture
glprogramstate->setUniformTexture("u_lightTexture", textrue2);
//注意,对于波光贴图,我们希望它在进行UV动画时能产生四方连续效果,必须设置它的纹理UV寻址方式为GL_REPEAT。
Texture2D::TexParams tRepeatParams;
tRepeatParams.magFilter = GL_LINEAR_MIPMAP_LINEAR;
tRepeatParams.minFilter = GL_LINEAR;
tRepeatParams.wrapS = GL_REPEAT;
tRepeatParams.wrapT = GL_REPEAT;
textrue2->setTexParameters(tRepeatParams);
//在这里,我们设置一个波光的颜色,这里设置为白色。
Vec4 tLightColor(1.0,1.0,1.0,1.0);
glprogramstate->setUniformVec4("v_LightColor",tLightColor);
//下面这一段,是为了将我们自定义的Shader与我们的模型顶点组织方式进行匹配。模型的顶点数据一般包括位置,法线,色彩,纹理,以及骨骼绑定信息。而Shader需要将内部相应的顶点属性通道与模型相应的顶点属性数据进行绑定才能正确显示出顶点。
long offset = 0;
auto attributeCount = m_Sprite->getMesh()->getMeshVertexAttribCount();
for (auto k = 0; k < attributeCount; k++) {
auto meshattribute = m_Sprite->getMesh()->getMeshVertexAttribute(k);
glprogramstate->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib],
meshattribute.size,
meshattribute.type,
GL_FALSE,
m_Sprite->getMesh()->getVertexSizeInBytes(),
(GLvoid*)offset);
offset += meshattribute.attribSizeBytes;
}
//uv滚动初始值设为0
m_LightAni.x = m_LightAni.y = 0;
return true;
}
void FishLayer::draw(Renderer* renderer, const Mat4 &transform, uint32_t flags)
{
if(m_Sprite)
{
//乌龟从右向左移动,移出屏幕后就回到最右边
auto s = Director::getInstance()->getWinSize();
m_Sprite->setPositionX(m_Sprite->getPositionX()-1);
if(m_Sprite->getPositionX() < -100)
{
m_Sprite->setPositionX(s.width + 10);
}
auto glprogramstate = m_Sprite->getGLProgramState();
if(glprogramstate)
{
m_LightAni.x += 0.01;
if(m_LightAni.x > 1.0)
{
m_LightAni.x-= 1.0;
}
m_LightAni.y += 0.01;
if(m_LightAni.y > 1.0)
{
m_LightAni.y-= 1.0;
}
glprogramstate->setUniformVec2("v_animLight",m_LightAni);
}
}
Node::draw(renderer,transform,flags);
}
转载于:https://www.cnblogs.com/jhsy/p/4337822.html