转自:http://blog.csdn.net/dawn_moon/article/details/8631783
好吧,终于抽时间写这篇文章了。
手头上有很多人物行走图,技能特效图等,但这些图都有个纯黑色背景,怎么样将内容显示出来,让背景透明呢?前段时间搞了一下,感谢群里的童鞋们,提供了思路和方法。
这里用shader处理了像素,使黑色背景透明,直接上代码
ShaderSprite.h
1 #ifndef __TestShader__ShaderSprite__ 2 #define __TestShader__ShaderSprite__ 3 4 #include "cocos2d.h" 5 USING_NS_CC; 6 7 class ShaderSprite : public CCSprite { 8 9 public: 10 static ShaderSprite* create(const char* pszFileName); 11 virtual bool initWithTexture(CCTexture2D *pTexture, const CCRect& rect); 12 virtual void draw(void); 13 }; 14 15 #endif /* defined(__TestShader__ShaderSprite__) */
ShaderSprite.cpp
1 #include "ShaderSprite.h" 2 3 static CC_DLL const GLchar *transparentshader = 4 #include "tansparentshader.h" 5 6 ShaderSprite* ShaderSprite::create(const char *pszFileName) 7 { 8 ShaderSprite *pRet = new ShaderSprite(); 9 if (pRet && pRet->initWithFile(pszFileName)) { 10 pRet->autorelease(); 11 return pRet; 12 } 13 else 14 { 15 delete pRet; 16 pRet = NULL; 17 return NULL; 18 } 19 } 20 21 bool ShaderSprite::initWithTexture(CCTexture2D *pTexture, const CCRect& rect) 22 { 23 do{ 24 // CCLog("override initWithTexture!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 25 CC_BREAK_IF(!CCSprite::initWithTexture(pTexture, rect)); 26 27 // 加载顶点着色器和片元着色器 28 m_pShaderProgram = new CCGLProgram(); 29 m_pShaderProgram ->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, transparentshader); 30 31 CHECK_GL_ERROR_DEBUG(); 32 33 // 启用顶点着色器的attribute变量,坐标、纹理坐标、颜色 34 m_pShaderProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 35 m_pShaderProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 36 m_pShaderProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 37 38 CHECK_GL_ERROR_DEBUG(); 39 40 // 自定义着色器链接 41 m_pShaderProgram->link(); 42 43 CHECK_GL_ERROR_DEBUG(); 44 45 // 设置移动、缩放、旋转矩阵 46 m_pShaderProgram->updateUniforms(); 47 48 CHECK_GL_ERROR_DEBUG(); 49 50 return true; 51 52 }while(0); 53 return false; 54 } 55 56 void ShaderSprite::draw(void) 57 { 58 // CCLog("override draw!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 59 CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw"); 60 61 CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called"); 62 63 CC_NODE_DRAW_SETUP(); 64 65 // 66 // 启用attributes变量输入,顶点坐标,纹理坐标,颜色 67 // 68 ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex ); 69 ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst); 70 71 m_pShaderProgram->use(); 72 m_pShaderProgram->setUniformsForBuiltins(); 73 74 // 绑定纹理到纹理槽0 75 ccGLBindTexture2D(m_pobTexture->getName()); 76 77 78 79 #define kQuadSize sizeof(m_sQuad.bl) 80 long offset = (long)&m_sQuad; 81 82 // vertex 83 int diff = offsetof( ccV3F_C4B_T2F, vertices); 84 glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff)); 85 86 // texCoods 87 diff = offsetof( ccV3F_C4B_T2F, texCoords); 88 glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff)); 89 90 // color 91 diff = offsetof( ccV3F_C4B_T2F, colors); 92 glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff)); 93 94 95 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 96 97 CHECK_GL_ERROR_DEBUG(); 98 99 CC_INCREMENT_GL_DRAWS(1); 100 CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw"); 101 }
片段着色器代码
tansparentshader.h
1 " \n\ 2 #ifdef GL_ES \n\ 3 precision lowp float; \n\ 4 #endif \n\ 5 varying vec4 v_fragmentColor; \n\ 6 varying vec2 v_texCoord; \n\ 7 uniform sampler2D u_texture; \n\ 8 void main() \n\ 9 { \n\ 10 float ratio=0.0; \n\ 11 vec4 texColor = texture2D(u_texture, v_texCoord); \n\ 12 ratio = texColor[0] > texColor[1]?(texColor[0] > texColor[2] ? texColor[0] : texColor[2]) :(texColor[1] > texColor[2]? texColor[1] : texColor[2]); \n\ 13 if (ratio != 0.0) \n\ 14 { \n\ 15 texColor[0] = texColor[0] / ratio; \n\ 16 texColor[1] = texColor[1] / ratio; \n\ 17 texColor[2] = texColor[2] / ratio; \n\ 18 texColor[3] = ratio; \n\ 19 } \n\ 20 else \n\ 21 { \n\ 22 texColor[3] = 0.0; \n\ 23 } \n\ 24 gl_FragColor = v_fragmentColor*texColor; \n\ 25 }";
注意shader编程没有隐士数据类型转换,所以都显示为float了。
然后ratio是指在rgb中找最大的,如果ratio为0直接将alpha设为0,否则alpha设为ratio,然后各rgb除以ratio,这里是为了做渐变,否则变化太生硬。
上图:
好了,上面两张图是一样的。只是屏幕背景一个是白色,一个是黑色。图片背景透明了。