学习OpenGL ES for Android(二十)— 混合

在之前使用物体时没考虑过透明的情况,而混合就是除了物体透明度的一种方式。在处理物体透明时一般有两种方式,一种是直接丢弃掉透明度达到一定程度的部分;另外一种就是混合。例如一扇窗户如果是全透明的我们看到的物体就是窗口后的物体;如果它是半透明的有色玻璃时,看到的就是玻璃和窗口后物体的叠加。之前我们使用纹理的颜色都是纹理的rgb颜色,没有用到最后一个alpha(也就是透明度),alpha的范围是0到1,1表示不透明,0表示全透明。

丢弃片段

有些物体的部分,要么是全透明,要么是不透明,不存在其他的情况下,我们选择丢弃掉透明的部分来显示。例如下面这个小草的图片,

首先我们先用它来显示不做任何处理的情况,我们改变位置显示几个纹理,一些关键代码

    private float[][] translate = new float[][]{
            {-1.5f, 0.0f, -0.48f},
            {1.5f, 0.0f, 0.51f},
            {0.0f, 0.0f, 0.7f},
            {-0.3f, 0.0f, -2.3f},
            {0.5f, 0.0f, -0.6f}};
    ……
    for (float[] vegetation : translate) {
         Matrix.setIdentityM(modelMatrix, 0);
         Matrix.translateM(modelMatrix, 0, vegetation[0], vegetation[1], vegetation[2]);
         //Matrix.rotateM(modelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f);

         Matrix.multiplyMM(mMVPMatrix, 0, viewMatrix, 0, modelMatrix, 0);
         Matrix.multiplyMM(mMVPMatrix, 0, projectionMatrix, 0, mMVPMatrix, 0);
         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
    }
    ……

因为我们没做任何的处理,在透明度为0的位置就显示了黑色,

这样显然是不能接受的。想要丢弃一部分片段,可以使用着色器内建的方法discard,这个方法的解释是:可以在片段着色器中使用它来放弃对当前片段的操作;此关键字导致片段被丢弃,并且不会对任何缓冲区进行更新。通常和条件判断一起使用,我们来修改下着色器代码,当alpha小于设置的值时丢弃片段,

……
void main() {
    vec4 texColor = texture2D(texture, TextCoord);
    if (texColor.a < 0.1){
       discard;
    }
    gl_FragColor = texColor;
}

这时的显示效果如下

混合

处理多个半透明时,使用丢弃就无法处理了,这时必须使用混合了。启用混合和启用其他类似,代码是

GLES20.glEnable(GLES20.GL_BLEND);

随后是设置混合的方式,使用方法glBlendFunc( int sfactor, int dfactor )或者glBlendFuncSeparate( int srcRGB, int dstRGB, int srcAlpha, int dstAlpha )。两个方法的区别,glBlendFunc直接设置rgba的混合方式,而glBlendFuncSeparate可以分别设置rgb和alpha的混合方式。对于具体的参数解析,可以参考文档https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/03%20Blending/。这里我们使用

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA)

使用源颜色向量的alpha作为源因子,使用1−alpha作为目标因子。我们使用下图的窗户代替小草展示效果,

绘制完成后的效果如下,

其中有些怪异的地方,最前面窗户的透明部分遮蔽了右侧背后的窗户。这是深度测试的原因,当写入深度缓冲时,深度缓冲不会检查片段是否是透明的,所以透明的部分会和其它值一样写入到深度缓冲中。结果就是窗户的整个四边形不论透明度都会进行深度测试。即使透明的部分应该显示背后的窗户,深度测试仍然丢弃了它们。要想让混合在多个物体上工作,我们需要最先绘制最远的物体,最后绘制最近的物体。因此我们需要计算各个物体与观察点的距离排序。这里我们使用TreeMap来排序,关键代码,

        Map<Float, float[]> map = new TreeMap<>(new Comparator<Float>() {
            @Override
            public int compare(Float o1, Float o2) {
                switch (o1.compareTo(o2)){
                    case 1:
                        return -1;
                    case -1:
                        return 1;
                    default:
                        return 0;
                }
            }
        });
        for (float[] vegetation : translate) {
            float result = (float) Math.sqrt((vegetation[0] - mViewPos[0]) * (vegetation[0] - mViewPos[0]) +
                    (vegetation[1] - mViewPos[1]) * (vegetation[1] - mViewPos[1]) +
                    (vegetation[2] - mViewPos[2]) * (vegetation[2] - mViewPos[2]));
            map.put(result, vegetation);
        }

        for (Map.Entry<Float, float[]> entry : map.entrySet()) {
            float[] vegetation = entry.getValue();
            ……绘制
        }

修改之后的显示效果

现在还没考虑到变换缩放等情况,而且对于非平面的物体需要更多的处理,不过已经是比较不错的混合实现效果了。

源码https://github.com/jklwan/OpenGLProject/blob/master/sample/src/main/java/com/chends/opengl/renderer/advanced/opengl/BlendingRenderer.java

In Pro OpenGL ES for Android, you'll find out how to harness the full power of OpenGL ES, and design your own 3D applications by building a fully-functional 3D solar system model using Open GL ES! OpenGL has set the standard for 3D computer graphics, and is an essential aspect of Android development. This book offers everything you need to know, from basic mathematical concepts to advanced coding techniques. You'll learn by building a fascinating 3D solar system simulator! After introducing Open GL ES, Pro OpenGL ES for Android explains the basics of 3D math and then orients you to the native Android 3D libraries you'll be using in your own 3D games and the solar system project you'll build using this book. Through the solar system example project, you'll learn how to incorporate a variety of graphic and animation techniques into your applications. You will also discover how the full spectrum of 3D development that awaits, with topics such as lighting, texture-mapping, modeling, shaders, blending modes, and several more advanced concepts. By the time you finish Pro OpenGL ES for Android, you'll have learned all the skills you'll need to build your own incredible 3D applications, based on one of the most powerful 3D libraries available. What you'll learn * The basics of 3D mathematics, and how they are applied in the OpenGL library * How to design and build your 3D worlds * To create 2D interfaces within the 3D world * To develop animation and 3D movement * How to implement 3D shading, coloring, and texturing * The differences between OpenGL and other 3D toolkits * To build a fully-functional 3D solar system simulator using OpenGL ES Who this book is for Experienced Android programmers who want to enter the 3D world of OpenGL ES programming. Table of Contents * Introduction to OpenGL ES and Our 3D Solar System Project * Generating a Basic OpenGL Program * Getting Past the 3D Math * Shading, Lighting and Colors * Materials and Textures * Animation * Creating a User Interface * Blending Modes, Buffer Objects, and Other Cool Stuff * Latest Features of OpenGL ES * Ray Tracing, Hidden Surfaces, and Other Advanced Topics Appendix A: APIs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值