在OpenGL ES中,Shader是着色器,包括两种:顶点着色器(Vertex Shader)和片元着色器(Fragment Shader)。每个program对象有且仅有一个Vertex Shader对象和一个Fragment Shader对象连接到它。

Shader和Program编程步骤:

1. 创建Shader
      1)编写Vertex Shader和Fragment Shader源码。

2)创建两个shader 实例:GLuint   glCreateShader(GLenum type);

3)给Shader实例指定源码。 glShaderSource

4)在线编译shaer源码 void   glCompileShader(GLuint shader)

2. 创建Program

1)创建program  GLuint   glCreateProgram(void)

2)绑定shader到program 。 void   glAttachShader(GLuint program, GLuint shader)。每个program必须绑定一个Vertex Shader 和一个Fragment Shader。

3)链接program 。 void   glLinkProgram(GLuint program)

4)使用porgram 。 void   glUseProgram(GLuint program)

在cocos2d-x中使用两个类CCGLProgram和CCShaderCache来完成这些操作,其中CCGLProgram类是基本类,封装了对OpenGL ES接口的调用,而CCShaderCache通过CCGLProgram来完成对shaders的缓存和管理。

bool CCGLProgram::initWithVertexShaderByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray)
{
m_uProgram = glCreateProgram(); //创建一个Program,id为m_uProgram
CHECK_GL_ERROR_DEBUG(); m_uVertShader = m_uFragShader = 0; if (vShaderByteArray)
{
//创建顶点着色器并编译,id为m_uVertShader,vShaderByteArray是顶点着色器的源码
if (!compileShader(&m_uVertShader, GL_VERTEX_SHADER, vShaderByteArray))
{
CCLOG("cocos2d: ERROR: Failed to compile vertex shader");
}
} // Create and compile fragment shader
if (fShaderByteArray)
{
//创建片元着色器并编译,id为m_uFragShader,fShaderByteArray是片元着色器的源码。
if (!compileShader(&m_uFragShader, GL_FRAGMENT_SHADER, fShaderByteArray))
{
CCLOG("cocos2d: ERROR: Failed to compile fragment shader");
}
} if (m_uVertShader)
{
//绑定顶点着色器
glAttachShader(m_uProgram, m_uVertShader);
}
CHECK_GL_ERROR_DEBUG(); if (m_uFragShader)
{
//绑定片元着色器
glAttachShader(m_uProgram, m_uFragShader);
}
m_pHashForUniforms = NULL; CHECK_GL_ERROR_DEBUG(); return true;
} bool CCGLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source)
{
GLint status; if (!source)
{
return false;
} const GLchar *sources[] = {
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
(type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
#endif
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"//CC INCLUDES END\n\n",
source,
}; *shader = glCreateShader(type); //创建shader
glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, NULL); //指定源码
glCompileShader(*shader); //编译shader glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); //获得shader编译的结果 if (! status) //编译失败打印log
{
GLsizei length;
glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length);
GLchar* src = (GLchar *)malloc(sizeof(GLchar) * length); glGetShaderSource(*shader, length, NULL, src);
CCLOG("cocos2d: ERROR: Failed to compile shader:\n%s", src); if (type == GL_VERTEX_SHADER)
{
CCLOG("cocos2d: %s", vertexShaderLog());
}
else
{
CCLOG("cocos2d: %s", fragmentShaderLog());
}
free(src); abort();
}
return (status == GL_TRUE);
}

下面是初始化Shader的过程,通过CCShaderCache::loadDefaultShaders来完成。

void CCShaderCache::loadDefaultShaders()
{
// Position Texture Color shader
CCGLProgram *p = new CCGLProgram(); //创建CCGLProgram对象来操作OpenGL的shader
loadDefaultShader(p, kCCShaderType_PositionTextureColor); //完成该CCGLProgram对象的初始化,如shaders的创建,编译和绑定
//此处创建的是顶点纹理颜色的program. m_pPrograms->setObject(p, kCCShader_PositionTextureColor); //存入字典,key为kCCShader_PositionTextureColor
p->release(); // Position Texture Color alpha test
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_PositionTextureColorAlphaTest); m_pPrograms->setObject(p, kCCShader_PositionTextureColorAlphaTest);
p->release(); //
// Position, Color shader
//
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_PositionColor); //此处创建的是顶点颜色的program. m_pPrograms->setObject(p, kCCShader_PositionColor);
p->release(); //
// Position Texture shader
//
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_PositionTexture); //此处创建的是顶点纹理的program. m_pPrograms->setObject(p, kCCShader_PositionTexture);
p->release(); //
// Position, Texture attribs, 1 Color as uniform shader
//
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_PositionTexture_uColor); m_pPrograms->setObject(p ,kCCShader_PositionTexture_uColor);
p->release(); //
// Position Texture A8 Color shader
//
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_PositionTextureA8Color); m_pPrograms->setObject(p, kCCShader_PositionTextureA8Color);
p->release(); //
// Position and 1 color passed as a uniform (to simulate glColor4ub )
//
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_Position_uColor); m_pPrograms->setObject(p, kCCShader_Position_uColor);
p->release(); //
// Position, Legth(TexCoords, Color (used by Draw Node basically )
//
p = new CCGLProgram();
loadDefaultShader(p, kCCShaderType_PositionLengthTexureColor); m_pPrograms->setObject(p, kCCShader_PositionLengthTexureColor);
p->release();
} void CCShaderCache::loadDefaultShader(CCGLProgram *p, int type)
{
switch (type) {
case kCCShaderType_PositionTextureColor:
//shaders的创建,编译和绑定,不同的program的顶点着色源码和片元着色源码不同。
p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColor_frag); //绑定属性名称和索引,属性名称在shader源码中已经定义。
p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); break;
case kCCShaderType_PositionTextureColorAlphaTest:
p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColorAlphaTest_frag); p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); break;
case kCCShaderType_PositionColor:
p->initWithVertexShaderByteArray(ccPositionColor_vert ,ccPositionColor_frag); p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); break;
case kCCShaderType_PositionTexture:
p->initWithVertexShaderByteArray(ccPositionTexture_vert ,ccPositionTexture_frag); p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); break;
case kCCShaderType_PositionTexture_uColor:
p->initWithVertexShaderByteArray(ccPositionTexture_uColor_vert, ccPositionTexture_uColor_frag); p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); break;
case kCCShaderType_PositionTextureA8Color:
p->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, ccPositionTextureA8Color_frag); p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); break;
case kCCShaderType_Position_uColor:
p->initWithVertexShaderByteArray(ccPosition_uColor_vert, ccPosition_uColor_frag); p->addAttribute("aVertex", kCCVertexAttrib_Position); break;
case kCCShaderType_PositionLengthTexureColor:
p->initWithVertexShaderByteArray(ccPositionColorLengthTexture_vert, ccPositionColorLengthTexture_frag); p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); break;
default:
CCLOG("cocos2d: %s:%d, error shader type", __FUNCTION__, __LINE__);
return;
} p->link(); //调用glLinkProgram链接
p->updateUniforms(); CHECK_GL_ERROR_DEBUG();
} 上面创建的几种类型的program说明如下:
enum {
kCCShaderType_PositionTextureColor, //顶点格式为位置+纹理UV+材质色
kCCShaderType_PositionTextureColorAlphaTest, //顶点格式为顶点格式为位置+纹理UV+材质色+用于AlphaTest的ALPHA值 kCCShaderType_PositionColor, // 顶点格式为位置+材质色 kCCShaderType_PositionTexture, //顶点格式为位置+纹理UV kCCShaderType_PositionTexture_uColor, //顶点格式为位置+纹理UV+材质色 kCCShaderType_PositionTextureA8Color, //顶点格式为位置+纹理UV+灰度 kCCShaderType_Position_uColor, //顶点格式为位置+材质色 kCCShaderType_MAX, //枚举结束值
};

以类型为kCCShaderType_PositionTextureColor的program为例,它的顶点着色源码和片元着色源码分别为ccShader_PositionTextureColor_vert.h和

ccShader_PositionTextureColor_frag.h。

ccShader_PositionTextureColor_vert.h内容为:

"                                                   \n\
attribute vec4 a_position; \n\
attribute vec2 a_texCoord; \n\
attribute vec4 a_color; \n\
\n\
#ifdef GL_ES \n\
varying lowp vec4 v_fragmentColor; \n\
varying mediump vec2 v_texCoord; \n\
#else \n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
#endif \n\
\n\
void main() \n\
{ \n\
gl_Position = CC_MVPMatrix * a_position; \n\
v_fragmentColor = a_color; \n\
v_texCoord = a_texCoord; \n\
} \n\
";

ccShader_PositionTextureColor_frag.h内容为:

"                                           \n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
uniform sampler2D CC_Texture0; \n\
\n\
void main() \n\
{ \n\
gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); \n\
} \n\
";

通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL ES中的Shader编程的更多相关文章

  1. cocos2d JS 本地缓存存储登陆记住账号密码->相当于C++中的UserDefault

    在cocos-js 3.0以上的版本中,当我们用到本地存储的时候,发现以前用到的UserDefault在JS中并没有导出,而是换成了LocalStorage. 在LocalStorage.h文件中我们 ...

  2. cocos源码分析--ClippingNode绘图原理

    在OpenGL 绘制过程中,与帧缓冲有关的是模版,深度测试,混合操作.模版测试使应用程序可以定义一个遮罩,在遮罩内的片段将被保留或者丢弃,在遮罩外的片段操作行为则相反.深度测试用来剔除那些被场景遮挡的 ...

  3. [OpenGL ES 02]OpenGL ES渲染管线与着色器

    [OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...

  4. Cocos2d坐标系转换

    Cocos2d-x坐标系和OpenGL坐标系相同,都是起源于笛卡尔坐标系(高中数学里面那种). 笛卡尔坐标系 笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外,OpenGL坐标系为笛卡尔右 ...

  5. Cocos2d 初学基本知识

    1. 纹理(Texture) 游戏角色的图像文件在使用前必须解压缩,并转换成 iPhone 和 iPad 的 GPU 可以理解的 格式,同时要加载进 RAM(随机存储器),这样的图像称为纹理.GPU ...

  6. 【Cocos2d入门教程三】HelloWorld之一目了然

    什么程序都是从HelloWorld先开始.同样Cocos2d-x我们先从HelloWorld进行下手.下面是HelloWorld的运行完成图: 建立好的Cocos游戏项目中会有两个比较常用接触的文件夹 ...

  7. use SWF / Flash in cocos2d-x; cocos2d(cocos2d-x) 直接播放flash / SWF文件

    前段时间移植一个页游到手游,原先页游的项目里面有1000+的Flash人物,宠物动画,特效. 这要是全部重新做一遍,还不累死人?所以就想干脆直接在Cocos2d(x)里面播放SWF文件.(包括场景,过 ...

  8. 转载+自练(莫喷)怎样在cocos2d 2.1.4里面使用动画和Texture Packer

    本文实践自 Ray Wenderlich.Tony Dahbura 的文章<How to Use Animations and Sprite Sheets in Cocos2D 2.X>, ...

  9. Cocos2D iOS之旅:如何写一个敲地鼠游戏(七):弹出地鼠

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

随机推荐

  1. dede操作成功信息提示修改

    函数修改 include/common.func.php 文件 function ShowMsg()函数

  2. discuz二次开发技巧

    discuz二次开发技巧 二次开发大多时候知识设置和处理,如果能够获知模板文件获得的变量数组将大大提高我们的开发效率 获取页面已经定义的变量 <--{eval printf_r(get_defi ...

  3. #module-django.db.models

    Models A model is the single, definitive source of information about your data. It contains the esse ...

  4. MAC——laravel环境

    apache: 目录:etc/apache2 重启:sudo apachectl restart PHP: 把/etc/php.ini.default复制并重命名/ect/php.ini 打开Load ...

  5. ubuntu下配置protobuf

    http://blog.csdn.net/guoyilongedu/article/details/17093811 最近想研究protobuf ,尝试了很多次都没有成功,我用的是ubuntu,在虚拟 ...

  6. [BZOJ 1874] [BeiJing2009 WinterCamp] 取石子游戏 【博弈论 | SG函数】

    题目链接:BZOJ - 1874 题目分析 这个是一种组合游戏,是许多单个SG游戏的和. 就是指,总的游戏由许多单个SG游戏组合而成,每个SG游戏(也就是每一堆石子)之间互不干扰,每次从所有的单个游戏 ...

  7. OpenSource.com 评出 2014 年十佳开源软件

    Docker 应用容器平台 “电源管理和虚拟化以相同的方式允许我们从服务器利用率中获取最大的利益.如何真正的解决虚拟化,这世界第一难题仍然是普遍存在的.Docker 自从 2013 年开源以来,刚好在 ...

  8. 【Java】WebService教程

    Web Services Web Services可以将应用程序转换为网络应用程序. Web Services可以被其他应用程序利用. 基本的Web Services平台是XML + HTTP. WS ...

  9. 转:Lua简明教程

    需要注意的是:lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里. 这里很奇怪,为什么在函数内部声明的变量默认也是global的呢? 函数的返回值 和Go语言一样,可以一条语句上赋多 ...

  10. 《how to design programs》15章 相互引用的数据定义

    由结构体组成的表与结构体中的表. 在用追溯形式建立家家谱树时,我们通常从某个后代除法,依次处理它的父母,组父母等.而构建树时,我们会不断添加谁是谁的孩子,而不是写出谁是谁的父母,从而建立一颗后代家谱树 ...