通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL ES中的Shader编程
来源:互联网 发布:卖域名 赚钱么 编辑:程序博客网 时间:2024/05/02 04:36
在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编程
- 通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL
- Cocos2d-x使用CCGLProgram和Shader文件实现精灵置灰
- 基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)
- 通过opengl es 2.0来实现yuv的显示
- 通过opengl es 2.0来实现yuv(NV21)的显示
- cocos2d-x 强大的 shader 系列:【OpenGL】Shader实例分析(二)- Heart
- cocos2d-x 强大的shader系列:【OpenGL】Shader实例分析(一)-Wave
- Cocos2d-X的shader
- 我所理解的Cocos2d-x OpenGL ES 2.0 概览
- cocos2d-x用shader来实现阴影
- cocos2d 2.x在opengl es 2.0 下自定义着色器来创建特别酷的特效(译)
- cocos2dx shader分析之CCGLProgram
- cocos2dx shader分析之CCGLProgram
- OpenGL ES Shader 实现代码
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)
- Android OpenGL ES 1.x 教程的Native实现
- 通过例子分析Cocos2d-x的Resolution
- 传输线理论
- 用Qt实现窗体的无边框、可移动、透明不规则显示(需背景透明的图片)
- ENGINE=InnoDB DEFAULT CHARSET=gbk AUTO_INCREMENT=1 这句话是什么意思呢?
- Linux LVM逻辑卷配置过程详解(创建、扩展、缩减、删除、卸载、快照创建)
- 圆图及其应用
- 通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL ES中的Shader编程
- pku 2239 Selecting Courses (无权值二分图)
- 工作中小知识点汇总(sql)
- ASP.NET JSON字符串与实体类的互转换
- POJ 2976 Dropping tests 01分数规划
- 关于try/catch的笔记
- 新浪微博分享
- poj 2728 Desert King(最优比例生成树)
- 五子棋必胜