cocos2D-X源码分析之从cocos2D-X学习OpenGL6---cocos内置着色器

上一篇我们介绍了cocos2d-x绘制基本图形的基本流程,我们还留下了一个着色器的部分没有讲,本篇内容将从openGL的渲染流程讲起,介绍cocos2d-x中的着色器,openGL的渲染流程如图所示:

openGL的绘制通常就是将顶点数据传输到openGL服务端。我们可以将一个顶点视为一个需要统一处理的数据包,这个包中的数据可以是我们需要的任何数据,通常其中几乎始终会包含位置数据。其他数据可能用来决定一个像素的最终颜色。

顶点着色器:一个复杂的应用程序可能包含许多个顶点着色器,但是在同一时刻只能有一个顶点着色器起作用,它用来进行顶点的变换,可能会非常简单,简单到传递着色器,也可能包含大量的计算。

几何着色器:对几何图元做处理,可以创建新的图元,这个阶段是可选的

细分着色器:顶点着色器存在一些限制,一个就是它们在执行的过程中无法创建额外的几何图形,它们仅仅更新与它们当前所处理的顶点相关数据,无法访问当前图元中其他顶点数据,它包含细分控制着色器和细分计算着色器。

像素着色器(片元着色器):通过编程控制在屏幕上显示颜色的阶段,在这个阶段中,我们使用着色器来计算片元的最终颜色和它的深度值。片元着色器非常强大,在这里我们会使用纹理映射的方式,对顶点处理阶段进行补充。可能还会丢弃不需要处理的片元

简而言之,顶点着色器决定一个图元应该位于屏幕什么位置,而片元着色器使用这些信息来决定摸个片元的颜色是什么。这两个着色器是必选的。另外因为顶点着色器阶段处理的顶点比较少,而在像素着色阶段处理的像素会很多,所以有时会在顶点阶段处理颜色和光照,其余的像素进行插值处理,为了节约效率,当然效果要差些了。

下面来看cocos2d-x的着色器流程,回到上一篇讲的DrawNode的init函数

    //设置着色器
    setGLProgramState(GLProgramState::getorCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR));
这句话调用setGLProgramState设置着色器状态,setGLProgramState函数代码如下:
void Node::setGLProgramState(cocos2d::GLProgramState* glProgramState)
{
    if (glProgramState != _glProgramState)
    {
        CC_SAFE_RELEASE(_glProgramState);
        _glProgramState = glProgramState;
        CC_SAFE_RETAIN(_glProgramState);

        if (_glProgramState)
            _glProgramState->setNodeBinding(this);
    }
}
这段代码判断设置的着色器是否与之前设置的相同,不同就重新设置,在onDraw函数中,会使用设置的着色器
auto glProgram = getGLProgram();
glProgram->use();
glProgram->setUniformsForBuiltins(transform);
其中getGLProgram函数就是获得着色器,代码如下:
GLProgram * Node::getGLProgram() const
{
    return _glProgramState ? _glProgramState->getGLProgram() : nullptr;
}
或者干脆直接在使用时传递使用哪个着色器
auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR);
glProgram->use();
glProgram->setUniformsForBuiltins(transform);
无论哪种方式,我们这里都使用的是cocos2d-x的内置的着色器代码,它们在“cocos目录/cocos/renderer”目录中
具体的详细加载可以看GLProgramCache类的loadDefaultGLProgram函数,这是一个单例类,在初始化的时候就会加载所有的内置着色器,然后这些着色器的代码文本以键值对的方式存储程序中,当使用的时候就通过getGLProgram调用,我们看一下这里使用的 GLProgram :: SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR:

顶点着色器:ccShader_PositionColorLengthTexture.vert

像素着色器:ccShader_PositionColorLengthTexture.frag


const char* ccPositionColorLengthTexture_vert = STRINGIFY(

\n#ifdef GL_ES\n
attribute mediump vec4 a_position;
attribute mediump vec2 a_texcoord;
attribute mediump vec4 a_color;

varying mediump vec4 v_color;
varying mediump vec2 v_texcoord;

\n#else\n

attribute vec4 a_position;
attribute vec2 a_texcoord;
attribute vec4 a_color;

varying vec4 v_color;
varying vec2 v_texcoord;

\n#endif\n

void main()
{
    v_color = vec4(a_color.rgb * a_color.a,a_color.a);
    v_texcoord = a_texcoord;

    gl_Position = CC_MVPMatrix * a_position;
}
);

cocos2d-x的内置着色器采用字符串的方式存储,可读性上会差一些,忽略掉“\n”之类的应该还好,着色器使用GLSL,在下一篇中会详细介绍,它类似于C语言,main函数是入口,这里处理了输入进来的颜色,贴图和位置信息,并做相应处理,位置进行了MVP的转换。

下一篇会介绍GLSL

能力不足,水平有限,如有错误,欢迎指出。

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...