一、前言
关于为什么使用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位单通道图像提供,在着色器中和纹理合并。