一、前言
關於為什么使用ETC1格式的圖片以及ETC紋理壓縮和Alpah通道處理。在這里不再細說。有興趣的朋友可以看看下面的文章:
1、http://blog.csdn.net/langresser_king/article/details/9339313
2、http://malideveloper.arm.com/resources/sample-code/etcv1-texture-compression-and-alpha-channels/
從技術上來說,主要是通過工具和程序來解決ETC1格式的不帶alpha信息和透明問題。
工具可以用:
Mali(http://malideveloper.arm.com/resources/tools/mali-gpu-texture-compression-tool/)
TexutrePacker(http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/TexturePacker.shtml)
程序主要用工具生成帶有alpha信息的紋理圖片。編寫shade代碼來實現。
二、使用一張紋理圖片
1、創建一張原始圖片和帶有alpha通道的紋理圖片。可以使用Mali工具生成。創建的時候選擇Create atlas。
原圖 新圖
2、編寫具體的Shader代碼。得到壓縮后的紋理圖片后,代碼中唯一需要的就是在着色器上重新映射紋理坐標。將上半部分的圖像,移到下半部分獲取Alpha通道信息。
頂點着色器(vertex shader):test.vsh
attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; varying vec4 v_fragmentColor; varying vec2 v_texCoord; varying vec2 v_alphaCoord; void main() { gl_Position = CC_PMatrix * a_position; v_texCoord = a_texCoord * vec2(1.0, 1.0); v_alphaCoord = a_texCoord + vec2(0.0, 0.5); }
片段着色器(fragment shader):test.fsh
varying vec2 v_texCoord; varying vec4 v_fragmentColor; varying vec2 v_alphaCoord; void main() { vec4 v4Colour = texture2D(CC_Texture0, v_texCoord); v4Colour.a = texture2D(CC_Texture0, v_alphaCoord).r; v4Colour.xyz = v4Colour.xyz * v4Colour.a; gl_FragColor = v4Colour; }
測試用例:
var sprite = new cc.Sprite("res/grossini.pkm", cc.rect(0, 0, 40, 40)); sprite.x = cc.winSize.width / 2; sprite.y = cc.winSize.height / 2; this.addChild(sprite);
var shader = new cc.GLProgram('res/shaders/test.vsh', 'res/shaders/test.fsh'); shader.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION); shader.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS); shader.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR); shader.link(); shader.updateUniforms(); sprite.shaderProgram = shader;
二、使用兩張紋理圖片
一張原始圖片,一張存放alpha信息。渲染的時候加載這兩張紋理。通過shader將alpha信息的圖片傳入到原始圖片。
原圖 新圖
1、頂點着色器(vertex shader):test.vsh
attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; varying vec4 v_fragmentColor; varying vec2 v_texCoord; void main() { gl_Position = CC_PMatrix * a_position; v_fragmentColor = a_color; v_texCoord = a_texCoord; }
2、片段着色器(fragment shader):test.fsh
varying vec2 v_texCoord; varying vec4 v_fragmentColor; uniform sampler2D u_alphaTexture; void main() { vec4 v4Colour = texture2D(CC_Texture0, v_texCoord); v4Colour.a = texture2D(u_alphaTexture, v_texCoord).r; v4Colour.xyz = v4Colour.xyz * v4Colour.a; gl_FragColor = v4Colour; }
3、測試用例:
var sprite = new cc.Sprite("res/grossini.pkm"); sprite.x = cc.winSize.width / 2; sprite.y = cc.winSize.height / 2; this.addChild(sprite);
var shader = new cc.GLProgram("res/shaders/test.vsh", "res/shaders/test.fsh"); shader.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION); shader.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS); shader.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR); shader.link(); shader.updateUniforms(); var alphaTexture = cc.textureCache.addImage("res/grossini_alpha.pkm"); var glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(shader); glProgramState.setUniformTexture("u_alphaTexture", alphaTexture); sprite.setGLProgramState(glProgramState);
四、其他
將alpha作為原始的8位單通道圖像提供,在着色器中和紋理合並。