通过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的缓存和管理。

[cpp] view plaincopy
  1. bool CCGLProgram::initWithVertexShaderByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray)  
  2. {  
  3.     m_uProgram = glCreateProgram(); //创建一个Program,id为m_uProgram  
  4.     CHECK_GL_ERROR_DEBUG();  
  5.   
  6.     m_uVertShader = m_uFragShader = 0;  
  7.   
  8.     if (vShaderByteArray)  
  9.     {  
  10.         //创建顶点着色器并编译,id为m_uVertShader,vShaderByteArray是顶点着色器的源码      
  11.         if (!compileShader(&m_uVertShader, GL_VERTEX_SHADER, vShaderByteArray))  
  12.         {  
  13.             CCLOG("cocos2d: ERROR: Failed to compile vertex shader");  
  14.         }  
  15.     }  
  16.   
  17.     // Create and compile fragment shader  
  18.     if (fShaderByteArray)  
  19.     {  
  20.         //创建片元着色器并编译,id为m_uFragShader,fShaderByteArray是片元着色器的源码。      
  21.         if (!compileShader(&m_uFragShader, GL_FRAGMENT_SHADER, fShaderByteArray))  
  22.         {  
  23.             CCLOG("cocos2d: ERROR: Failed to compile fragment shader");  
  24.         }  
  25.     }  
  26.   
  27.     if (m_uVertShader)  
  28.     {  
  29.         //绑定顶点着色器  
  30.         glAttachShader(m_uProgram, m_uVertShader);  
  31.     }  
  32.     CHECK_GL_ERROR_DEBUG();  
  33.   
  34.     if (m_uFragShader)  
  35.     {  
  36.         //绑定片元着色器      
  37.         glAttachShader(m_uProgram, m_uFragShader);  
  38.     }  
  39.     m_pHashForUniforms = NULL;  
  40.       
  41.     CHECK_GL_ERROR_DEBUG();  
  42.   
  43.     return true;  
  44. }  
  45.   
  46. bool CCGLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source)  
  47. {  
  48.     GLint status;  
  49.    
  50.     if (!source)  
  51.     {  
  52.         return false;  
  53.     }  
  54.       
  55.     const GLchar *sources[] = {  
  56. #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32 && CC_TARGET_PLATFORM != CC_PLATFORM_LINUX && CC_TARGET_PLATFORM != CC_PLATFORM_MAC)  
  57.         (type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),  
  58. #endif  
  59.         "uniform mat4 CC_PMatrix;\n"  
  60.         "uniform mat4 CC_MVMatrix;\n"  
  61.         "uniform mat4 CC_MVPMatrix;\n"  
  62.         "uniform vec4 CC_Time;\n"  
  63.         "uniform vec4 CC_SinTime;\n"  
  64.         "uniform vec4 CC_CosTime;\n"  
  65.         "uniform vec4 CC_Random01;\n"  
  66.         "//CC INCLUDES END\n\n",  
  67.         source,  
  68.     };  
  69.   
  70.     *shader = glCreateShader(type); //创建shader  
  71.     glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, NULL);  //指定源码  
  72.     glCompileShader(*shader); //编译shader  
  73.   
  74.     glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); //获得shader编译的结果  
  75.   
  76.     if (! status)  //编译失败打印log  
  77.     {  
  78.         GLsizei length;  
  79.         glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length);  
  80.         GLchar* src = (GLchar *)malloc(sizeof(GLchar) * length);  
  81.           
  82.         glGetShaderSource(*shader, length, NULL, src);  
  83.         CCLOG("cocos2d: ERROR: Failed to compile shader:\n%s", src);  
  84.           
  85.         if (type == GL_VERTEX_SHADER)  
  86.         {  
  87.             CCLOG("cocos2d: %s", vertexShaderLog());  
  88.         }  
  89.         else  
  90.         {  
  91.             CCLOG("cocos2d: %s", fragmentShaderLog());  
  92.         }  
  93.         free(src);  
  94.   
  95.         abort();  
  96.     }  
  97.     return (status == GL_TRUE);  
  98. }  

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

[cpp] view plaincopy
  1. void CCShaderCache::loadDefaultShaders()  
  2. {  
  3.     // Position Texture Color shader  
  4.     CCGLProgram *p = new CCGLProgram(); //创建CCGLProgram对象来操作OpenGL的shader  
  5.     loadDefaultShader(p, kCCShaderType_PositionTextureColor); //完成该CCGLProgram对象的初始化,如shaders的创建,编译和绑定  
  6.                                                               //此处创建的是顶点纹理颜色的program.  
  7.   
  8.     m_pPrograms->setObject(p, kCCShader_PositionTextureColor); //存入字典,key为kCCShader_PositionTextureColor  
  9.     p->release();  
  10.   
  11.     // Position Texture Color alpha test  
  12.     p = new CCGLProgram();  
  13.     loadDefaultShader(p, kCCShaderType_PositionTextureColorAlphaTest);  
  14.   
  15.     m_pPrograms->setObject(p, kCCShader_PositionTextureColorAlphaTest);  
  16.     p->release();  
  17.   
  18.     //  
  19.     // Position, Color shader  
  20.     //  
  21.     p = new CCGLProgram();  
  22.     loadDefaultShader(p, kCCShaderType_PositionColor);  //此处创建的是顶点颜色的program.  
  23.   
  24.     m_pPrograms->setObject(p, kCCShader_PositionColor);  
  25.     p->release();  
  26.   
  27.     //  
  28.     // Position Texture shader  
  29.     //  
  30.     p = new CCGLProgram();  
  31.     loadDefaultShader(p, kCCShaderType_PositionTexture);  //此处创建的是顶点纹理的program.  
  32.   
  33.     m_pPrograms->setObject(p, kCCShader_PositionTexture);  
  34.     p->release();  
  35.   
  36.     //  
  37.     // Position, Texture attribs, 1 Color as uniform shader  
  38.     //  
  39.     p = new CCGLProgram();  
  40.     loadDefaultShader(p, kCCShaderType_PositionTexture_uColor);  
  41.   
  42.     m_pPrograms->setObject(p ,kCCShader_PositionTexture_uColor);  
  43.     p->release();  
  44.   
  45.     //  
  46.     // Position Texture A8 Color shader  
  47.     //  
  48.     p = new CCGLProgram();  
  49.     loadDefaultShader(p, kCCShaderType_PositionTextureA8Color);  
  50.       
  51.     m_pPrograms->setObject(p, kCCShader_PositionTextureA8Color);  
  52.     p->release();  
  53.   
  54.     //  
  55.     // Position and 1 color passed as a uniform (to simulate glColor4ub )  
  56.     //  
  57.     p = new CCGLProgram();  
  58.     loadDefaultShader(p, kCCShaderType_Position_uColor);  
  59.       
  60.     m_pPrograms->setObject(p, kCCShader_Position_uColor);  
  61.     p->release();  
  62.       
  63.     //  
  64.     // Position, Legth(TexCoords, Color (used by Draw Node basically )  
  65.     //  
  66.     p = new CCGLProgram();  
  67.     loadDefaultShader(p, kCCShaderType_PositionLengthTexureColor);  
  68.       
  69.     m_pPrograms->setObject(p, kCCShader_PositionLengthTexureColor);  
  70.     p->release();  
  71. }  
  72.   
  73. void CCShaderCache::loadDefaultShader(CCGLProgram *p, int type)  
  74. {  
  75.     switch (type) {  
  76.         case kCCShaderType_PositionTextureColor:  
  77.             //shaders的创建,编译和绑定,不同的program的顶点着色源码和片元着色源码不同。  
  78.             p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColor_frag);  
  79.               
  80.             //绑定属性名称和索引,属性名称在shader源码中已经定义。  
  81.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  82.             p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);  
  83.             p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);  
  84.               
  85.             break;  
  86.         case kCCShaderType_PositionTextureColorAlphaTest:  
  87.             p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColorAlphaTest_frag);  
  88.               
  89.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  90.             p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);  
  91.             p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);  
  92.   
  93.             break;  
  94.         case kCCShaderType_PositionColor:    
  95.             p->initWithVertexShaderByteArray(ccPositionColor_vert ,ccPositionColor_frag);  
  96.               
  97.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  98.             p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);  
  99.   
  100.             break;  
  101.         case kCCShaderType_PositionTexture:  
  102.             p->initWithVertexShaderByteArray(ccPositionTexture_vert ,ccPositionTexture_frag);  
  103.               
  104.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  105.             p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);  
  106.   
  107.             break;  
  108.         case kCCShaderType_PositionTexture_uColor:  
  109.             p->initWithVertexShaderByteArray(ccPositionTexture_uColor_vert, ccPositionTexture_uColor_frag);  
  110.               
  111.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  112.             p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);  
  113.   
  114.             break;  
  115.         case kCCShaderType_PositionTextureA8Color:  
  116.             p->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, ccPositionTextureA8Color_frag);  
  117.               
  118.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  119.             p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);  
  120.             p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);  
  121.   
  122.             break;  
  123.         case kCCShaderType_Position_uColor:  
  124.             p->initWithVertexShaderByteArray(ccPosition_uColor_vert, ccPosition_uColor_frag);      
  125.               
  126.             p->addAttribute("aVertex", kCCVertexAttrib_Position);      
  127.               
  128.             break;  
  129.         case kCCShaderType_PositionLengthTexureColor:  
  130.             p->initWithVertexShaderByteArray(ccPositionColorLengthTexture_vert, ccPositionColorLengthTexture_frag);  
  131.               
  132.             p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);  
  133.             p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);  
  134.             p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);  
  135.               
  136.             break;  
  137.         default:  
  138.             CCLOG("cocos2d: %s:%d, error shader type", __FUNCTION__, __LINE__);  
  139.             return;  
  140.     }  
  141.       
  142.     p->link(); //调用glLinkProgram链接  
  143.     p->updateUniforms();  
  144.       
  145.     CHECK_GL_ERROR_DEBUG();  
  146. }  
  147.   
  148. 上面创建的几种类型的program说明如下:  
  149. enum {      
  150.     kCCShaderType_PositionTextureColor, //顶点格式为位置+纹理UV+材质色    
  151.     kCCShaderType_PositionTextureColorAlphaTest, //顶点格式为顶点格式为位置+纹理UV+材质色+用于AlphaTest的ALPHA值    
  152.     
  153.     kCCShaderType_PositionColor, // 顶点格式为位置+材质色    
  154.     
  155.     kCCShaderType_PositionTexture, //顶点格式为位置+纹理UV     
  156.     
  157.     kCCShaderType_PositionTexture_uColor, //顶点格式为位置+纹理UV+材质色    
  158.     
  159.     kCCShaderType_PositionTextureA8Color, //顶点格式为位置+纹理UV+灰度    
  160.     
  161.     kCCShaderType_Position_uColor, //顶点格式为位置+材质色     
  162.         
  163.     kCCShaderType_MAX,  //枚举结束值    
  164. };   

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


ccShader_PositionTextureColor_vert.h内容为:

[cpp] view plaincopy
  1. "                                                   \n\  
  2. attribute vec4 a_position;                          \n\  
  3. attribute vec2 a_texCoord;                          \n\  
  4. attribute vec4 a_color;                             \n\  
  5.                                                     \n\  
  6. #ifdef GL_ES                                        \n\  
  7. varying lowp vec4 v_fragmentColor;                  \n\  
  8. varying mediump vec2 v_texCoord;                    \n\  
  9. #else                                               \n\  
  10. varying vec4 v_fragmentColor;                       \n\  
  11. varying vec2 v_texCoord;                            \n\  
  12. #endif                                              \n\  
  13.                                                     \n\  
  14. void main()                                         \n\  
  15. {                                                   \n\  
  16.     gl_Position = CC_MVPMatrix * a_position;        \n\  
  17.     v_fragmentColor = a_color;                      \n\  
  18.     v_texCoord = a_texCoord;                        \n\  
  19. }                                                   \n\  
  20. ";  

ccShader_PositionTextureColor_frag.h内容为:

[cpp] view plaincopy
  1. "                                           \n\  
  2. #ifdef GL_ES                                \n\  
  3. precision lowp float;                       \n\  
  4. #endif                                      \n\  
  5.                                             \n\  
  6. varying vec4 v_fragmentColor;               \n\  
  7. varying vec2 v_texCoord;                    \n\  
  8. uniform sampler2D CC_Texture0;              \n\  
  9.                                             \n\  
  10. void main()                                 \n\  
  11. {                                           \n\  
  12.     gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);            \n\  
  13. }                                           \n\  
  14. ";  
0 0
原创粉丝点击