android opengl 纹理压缩 使用带透明通道的etc1

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

TestETC1

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值