首页 > 其他分享 >OpenGL 利用 Alpha 透明度进行测试

OpenGL 利用 Alpha 透明度进行测试

时间:2022-10-13 16:33:31浏览次数:77  
标签:MatrixState OpenGL 透明度 0f Alpha GLES20 向量 分量


公众号回复:OpenGL,领取学习资源大礼包


在前面的博客文章中有提到 ​​OpenGL 裁剪测试及注意点​​,并且裁剪测试只能裁剪一个矩形区域,相当于就是把整个内容都绘制上去了,但是透过一个小矩形区域来看绘制的物体。

除了透过矩形区域,还可以实现透过任意形状区域来观察物体,这就是要用到 OpenGL 的 Alpha 透明度测试。

关于 Alpha 透明度测试,在 ​​用 OpenGL 对视频帧内容进行替换​​ 也用实践用到过。

在 OpenGL 中,每个颜色都有四个色彩通道 --- RGBA,其中 A 就是 Alpha 透明度通道,可以利用它的值进行检测。

Alpha 测试的基本原理为,当绘制一个片元时,首先检测其 Alpha 值,若 Alpha 值满足要求,就通过测试,绘制此片元,否则丢弃此片元,不进行绘制。

比如如下的场景:

OpenGL 利用 Alpha 透明度进行测试_2d

如果是裁剪测试,只能屏幕上透过一个矩形区域来观察实际场景。

OpenGL 利用 Alpha 透明度进行测试_着色器_02

而换成 Alpha 测试,就可以实现透过任意形状的观察,效果如下:

OpenGL 利用 Alpha 透明度进行测试_着色器_03

图上的内容实际由三部分组成,树、地形、中间带透明度的边框。

正因为绘制的边框带透明度,才不会全部遮住后面的内容。

具体绘制代码如下:

 1            GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT or GLES20.GL_COLOR_BUFFER_BIT)
2 // 打开深度检测
3 GLES20.glEnable(GLES20.GL_DEPTH_TEST)
4 // 设置相机和观察矩阵,绘制地形和树
5 MatrixState.setProjectFrustum(-ratio!!, ratio!!, -1f, 1f, 1f, 100f)
6 MatrixState.setCamera(cx, 0f, cz, 0f, 0f, 0f, 0f, 1.0f, 0f)
7
8 MatrixState.pushMatrix()
9 MatrixState.translate(0f, -2f, 0f)
10 // 绘制地形
11 desert!!.drawSelf(desertId)
12 MatrixState.popMatrix()
13 // 开启混合,因为树要和地形有混合的地方
14 GLES20.glEnable(GLES20.GL_BLEND)
15 // 设置混合因子
16 GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA)
17 MatrixState.pushMatrix()
18 MatrixState.translate(0f, -2f, 0f)
19 // 绘制树
20 tg!!.drawSelf(treeId)
21 MatrixState.popMatrix()
22 // 关闭混合
23 GLES20.glDisable(GLES20.GL_BLEND)
24 // 清除深度缓冲
25 GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT)
26 // 设置相机和投影矩阵来绘制带透明度的边框
27 MatrixState.pushMatrix()
28 MatrixState.setProjectOrtho(-1f, 1f, -1f, 1f, 1f, 100f)
29 MatrixState.setCamera(0f, 0f, 3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
30 rect!!.drawSelf(maskTextureId)
31 MatrixState.popMatrix()

这里面绘制带透明度的边框时清除了一次深度缓冲,因为带透明度边框不属于主场景,不应该和主场景中的物体以同一标准进行深度检测,否则可能会产生不正确的视觉效果。

具体实现

Alpha 测试的重点在于片段着色器的处理,在这里可以对每一个片段进行处理,根据 Alpha 来决定是否抛弃它。

 1precision mediump float;
2varying vec2 vTextureCoord; //接收从顶点着色器过来的参数
3uniform sampler2D sTexture;//纹理内容数据
4void main() {
5 //给此片元从纹理中采样出颜色值
6 vec4 bcolor = texture2D(sTexture, vTextureCoord);
7 if(bcolor.a<0.6) {
8 discard;
9 } else {
10 gl_FragColor=bcolor;
11}}

根据具体的图片透明度,这里,如果透明度小于 0.6 ,就抛弃这个片元,否则的话就赋值给原本采样的颜色。

其中,在 GLSL 着色器语言中,​​discard​​ 代表放弃该片元。

而 texture2D 方法代表纹理采样,它的结果类型是一个向量,向量在着色器代码中的地位非常重要,可以方便地存储以及操作 颜色位置纹理坐标 等不仅包含一个组成部分的量。

对于一个向量,有时需要单独访问向量中的某个分量,基本语法为 ​​<向量名>.<分量名>​​,从不同的角度来看,它的每个分量代表的含义是不同的:

  • 将向量看作颜色时,可以使用 r、g、b、a 四个分量名,分别代表红、绿、蓝、透明度 4 个色彩通道。
1vec4 aColor;
2aColor.r = 0.6;
3aColor.g = 0.8;

若向量是 4 维的,可以使用的分量名为 r、g、b、a;若向量是 3 维的,可以使用的分量名为 r、g、b;若是 2 维的,可以使用的 r、g 两个分量名。

  • 将向量看作位置时,可以使用 x、y、z、w 四个分量名,分别代表 x 轴、y 轴、z 轴分量及 w 值。
1vec4 aPosition;
2aPosition.x = 34.2
3aPosition.z = 12.2

若向量是 4 维的,可以使用的分量名为 x、y、z、w;若向量是 3 维的,可以使用的分量名为 x、y、z;若是 2 维的,可以使用的 x、y 两个分量名。

  • 将向量看作纹理坐标时,可以使用 s、t、p、q 四个分量名,分别代表纹理坐标的不同分量。
1vec4 aTexCoor;
2aTexCoor.s = 0.45;
3aTexCoor.t = 0.22;

若向量是 4 维的,可以使用的分量名为 s、t、p、q;若向量是 3 维的,可以使用的分量名为 s、t、p;若是 2 维的,可以使用的 s、t 两个分量名。

除了使用 ​​.​​ 的形式来访问分量名,还可以将向量看作一个数组,用下标来进行访问:

1aColor[0] = 0.4;
2aPostion[2] = 0.34;
3aTexCoorp[1] = 0.12;

理解了 discard 的作用和向量各分量的含义,就很容易明白 Alpha 测试的原理了。

实际上,Alpha 测试并不是渲染管线上要进行的操作流程,而是我们自己想出的根据 Alpha 透明度值对片元进行处理罢了。

具体的实现可以参考我的 Github 项目,求一波 Star 。

​https://github.com/glumes/AndroidOpenGLTutorial​

OpenGL 相关文章推荐:

  1. ​用 OpenGL 对视频帧内容进行替换​
  2. ​OpenGL ES 学习资源分享​
  3. ​OpenGL 裁剪测试及注意点​
  4. ​OpenGL 学习系列---观察矩阵​


OpenGL 利用 Alpha 透明度进行测试_公众号_04


扫码关注公众号【音视频开发进阶】,一起学习多媒体音视频开发~~~

OpenGL 利用 Alpha 透明度进行测试_2d_05


喜欢就点个吧 ▽

标签:MatrixState,OpenGL,透明度,0f,Alpha,GLES20,向量,分量
From: https://blog.51cto.com/u_12127193/5753720

相关文章

  • 神经网络alpha阶逆系统
    逆系统方法的本质上是用反馈线性化方法来研究控制系统设计理论的一种途径,是一种比较一般性的方法。逆系统方法的基本思想是:首先,利用对象的逆系统构成一种可用反馈方法实现的......
  • OpenGL之ShadowMap
    流程:先创建一个RenderTexture,然后用灯光的视口渲染。然后切换到正常相机,进行渲染,使用RenderTexture中的深度或者颜色纹理,然后还原当前顶点在灯光中的深度,两者对比,比缓存中......
  • OpenGL 学习系列---基本形状的绘制
    在之前的一篇博客中,讲述了​​OpenGL基础绘制流程​​ 及相关的代码,其中关于OpenGL程序编译部分都是可以在其他项目中接着复用的,接下来会讲到如何去绘制其他的基本图元......
  • ​OpenGL 学习系列---坐标系统
    在前面​​绘制基本图形​​中,遇到了很明显的问题,圆形不像圆形,正多边形不像正多边形?就像下面图形一样:不规则的形状好好的正五边形却东倒西歪的,这就是因为我们前面的绘制都是......
  • OpenGL 之 GPUImage 源码分析
    GPUImage是iOS上一个基于OpenGL进行图像处理的开源框架,后来有人借鉴它的想法实现了一个Android版本的GPUImage,本文也主要对Android版本的GPUImage进行分析。概......
  • OpenGL之多线程渲染
    随着Vulkan的引入,我们的图形技术的发展到达了一个新的顶点,但是呢,我们的老干爹OpenGL作为落日余晖,他在一些Vulkan才有的新功能上,也提供了一些支持。现在我们来讨论一下OpenG......
  • [CG从零开始] 4. pyopengl 绘制一个正方形
    在做了1~3的基础工作后,我们的开发环境基本OK了,我们可以开始尝试利用pyopengl来进行绘制了。本文主要有三个部分利用glfw封装窗口类,并打开窗口;封装shader类,进......
  • Opengl ES之FBO
    FBO介绍FBO帧缓冲对象,它的主要作用一般就是用作离屏渲染,例如做Camera相机图像采集进行后期处理时就可能会用到FBO。假如相机出图的是OES纹理,为了方便后期处理,一般先将OES......
  • [CG从零开始] 2. 彻底弄清OpenGL 涉及的工具库
    1.跨平台窗口管理为了将OpenGL渲染的内容在操作系统的窗口中显示出来,我们不可避免的需要调用操作系统的API创建窗口、渲染上下文等等,每个操作系统的API都不一样,为......
  • Opengl ES之EBO
    前面我们介绍了VBO与VAO等缓冲对象,今天我们来介绍一下EBO。对于VBO或VAO可以查看之前的文章:OpenglES之VBO和VAOEBO是个啥EBO(ElementBufferObject,也叫IBO:IndexBuf......