通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL
来源:互联网 发布:潮汕话软件 编辑:程序博客网 时间:2024/05/03 03:41
http://blog.csdn.net/while0/article/details/9666829
在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的Resolution
- 通过opengl来实现yuv的显示
- cocos2d-x节点(CCShaderCache.h)API
- cocos2d-x节点(CCGLProgram.h)API
- 【cocos2d-x 2.x 学习与应用总结】13: 借助CCGLProgram实现自定义绘制
- 通过opengl es 2.0来实现yuv的显示
- 通过opengl es 2.0来实现yuv(NV21)的显示
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- (转)cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调 .
- cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
- C# String.Format大全
- 模拟文本框自动完成功能
- dwr推技术(服务器向jsp页面推送弹出框--bs)
- ASP.NET系统用户权限设计与实现
- PHP 页面跳转到另一个页面的几种方法分享
- 通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL
- 什么事情都有一个折中
- PostgreSQL学习手册(表的继承和分区)
- ECMALL QQ 支付宝 新浪 快捷登录一键登录插件功能
- Hopper 反汇编
- Android适配器之ArrayAdapter、SimpleAdapter和BaseAdapter的简单用法与有用代码片段
- 《建立一个属于自己的AVR的RTOS》笔记——OSTaskSuspend
- 黑马程序员_学习笔记第9天——内部类、异常
- Netty4.0 用户指南