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混合透明和紋理