cocos-shader---3.实例上手

一、使用内置shader

使用内置 shader 非常简单,直接通过一个 key 值从 GLProgramCache 缓冲区取到一个 GLProgram,然后设置给 Node 即可;
默认 shader 的 key 值在 GLProgram 中定义

auto sprite = Sprite::create("colormap.jpg");
sprite->setPosition(visibleSize / 2);
addChild(sprite);
auto program = ShaderCache::getInstance()->programForKey(GLProgram::SHADER_NAME_POSITION_GRAYSCALE);
sprite->setShaderProgram(program);

这里使用的SHADER_NAME_POSITION_GRAYSCALE 是设置图像变灰的功能,其使用的顶点着色器和片段着色器分别是 ccPositionTextureColor_noMVP_vertccPositionTexture_GrayScale_frag

ccPositionTextureColor_noMVP_vert 顶点着色器不乘以 CC_MVPMatrix 矩阵,默认都会乘上这个矩阵,这是 2.x 留下的习惯,用于将局部坐标转换为世界坐标;而 3.x 顶点在传入 shader 之前就已经做转换了,所以可以不用乘上这个矩阵,只有带上 _noMVP 的着色器才不会乘上 CC_MVPMatrix 矩阵

//ccPositionTextureColor_noMVP_vert
const char* ccPositionTextureColor_noMVP_vert = STRINGIFY(
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

\n#ifdef GL_ES\n
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
\n#else\n
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
\n#endif\n

void main()
{
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}
);

ccPositionTexture_GrayScale_frag 为每一个颜色乘上一个数值,达到变灰的效果

//ccPositionTexture_GrayScale_frag
const char* ccPositionTexture_GrayScale_frag = STRINGIFY(

#ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

void main(void)
{
  vec4 c = texture2D(CC_Texture0, v_texCoord);
    gl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b);
    gl_FragColor.w = c.w;
}
);

二、使用自定义shader

首先,先上完整代码

auto sprite = Sprite::create("colormap.jpg");
sprite->setPosition(visibleSize / 2);
addChild(sprite);

//第一步,读取着色器源代码
auto fragSource = (GLchar*)(String::createWithContentsOfFile(FileUtils::getInstance()->fullPathForFilename("water.fs"))->getCString());

//第二步,创建 GLProgram
//从缓冲区取
auto glProgram = GLProgramCache::getInstance()->getProgram("water_frag_shader");
if (!glProgram)
{
    //方式1
    //glProgram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource);
    //方式2
    glProgram = new GLProgram();
    glProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource);
    glProgram->link();
    glProgram->updateUniforms();
    glProgram->autorelease();
    //添加到缓冲区
    GLProgramCache::getInstance()->addProgram(glProgram, "water_frag_shader");
}

//第三步,创建并设置 GLProgramState
//方式1,通过缓冲区管理
//sprite->setShaderProgram(glProgram);
//方式2,与方式1一样
//auto glProgramState = GLProgramState::getOrCreateWithGLProgram(glProgram);
//sprite->setGLProgramState(glProgramState);
//方式3,不经过缓冲区
auto glProgramState = GLProgramState::create(glProgram);
sprite->setGLProgramState(glProgramState);

//第四步,设置 uniform 变量的值
auto normalMapTexture = TextureCache::getInstance()->addImage("water_normal.jpg");
glProgramState->setUniformTexture("u_normalMap", normalMapTexture);

这段程序实现一个水波效果,需要用到一个片段着色器,而顶点着色器即使用默认的就行,也就是 ccPositionTextureColor_noMVP_vert 这个着色器。创建一个着色器程序分为四步:

第一步,读取着色器源代码;

第二步,创建 GLProgram,这里列了两种方式,其实第二种方式就是第一种方式的内部实现,这两种方式是一样的,创建完 GLProgram 之后可以将其添加到 GLProgramCache 缓冲区,这样下次再使用同样的 GLProgram 时直接从缓冲区取即可;

第三步,创建 GLProgramState 并设置给结点,这里列出了三种方式,同样前两种方式是一样的,第三种方式不使用 getOrCreateWithGLProgram 方法来获取 GLProgramState,这样就跳过了 GLProgramStateCache 缓冲区;

第四步,不是必须的,如果着色器程序中有用到 uniform 变量,则通过 GLProgramState->setUniform*() 来设置它的值。

猜你喜欢

转载自blog.csdn.net/wade333777/article/details/81611523
今日推荐