etc1网上资料很多,而带透明通道,也就是alpha通道的方法其实就是mask抠图,先看未处理时的纹理样子
再来看处理完的样子
带透明通道的etc1其实就是高度加了一倍,在下面加上一个mask来进行抠图,根据这个原理jpg我们也可以自己加上透明通道
说完原理来说代码
关于etc1的处理代码都在android.opengl.ETC1Util内
读取etc1数据用的是ETC1Util.createTexture()方法,而Android对etc1的支持只能是PKM格式,查看createTexture的源码你会发现它会把非PKM格式的数据给过滤掉了
public static ETC1Texture createTexture(InputStream input) throws IOException {
int width = 0;
int height = 0;
byte[] ioBuffer = new byte[4096];
{
if (input.read(ioBuffer, 0, ETC1.ETC_PKM_HEADER_SIZE) != ETC1.ETC_PKM_HEADER_SIZE) {
throw new IOException("Unable to read PKM file header.");
}
ByteBuffer headerBuffer = ByteBuffer.allocateDirect(ETC1.ETC_PKM_HEADER_SIZE)
.order(ByteOrder.nativeOrder());
headerBuffer.put(ioBuffer, 0, ETC1.ETC_PKM_HEADER_SIZE).position(0);
if (!ETC1.isValid(headerBuffer)) {
throw new IOException("Not a PKM file.");
}
width = ETC1.getWidth(headerBuffer);
height = ETC1.getHeight(headerBuffer);
}
int encodedSize = ETC1.getEncodedDataSize(width, height);
ByteBuffer dataBuffer = ByteBuffer.allocateDirect(encodedSize).order(ByteOrder.nativeOrder());
for (int i = 0; i < encodedSize; ) {
int chunkSize = Math.min(ioBuffer.length, encodedSize - i);
if (input.read(ioBuffer, 0, chunkSize) != chunkSize) {
throw new IOException("Unable to read PKM file data.");
}
dataBuffer.put(ioBuffer, 0, chunkSize);
i += chunkSize;
}
dataBuffer.position(0);
return new ETC1Texture(width, height, dataBuffer);
}
通过ETC1Util.createTexture()获取到ETC1Util.ETC1Texture,再通过ETC1Util.loadTexture()把ETC1Util.ETC1Texture的数据传给opengl,由于添加了透明通道所以在处理的时候要对高度除以2,比如显示的时候int height = texture.getHeight()/2;
在shader内进行处理的时候
vertexShader
attribute vec4 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
void main() {
vTexCoord = aTexCoord * vec2(1.0, 0.5);
gl_Position = aPosition;
}
fragmentShader
varying highp vec2 vTexCoord;
uniform sampler2D sTexture;
void main() {
highp vec4 color = texture2D(sTexture, vec2(vTexCoord.x,0.5 - vTexCoord.y));
gl_FragColor = mix(vec4(0.0),color,texture2D(sTexture,vec2(vTexCoord.x,1.0 - vTexCoord.y)).r);
}
最后的就是mask抠图代码,因为阴影部分要抠出半透明效果,所以要用mix,根据下半部分的mask混合透明和纹理