OpenGL ES学习(8)——剪裁测试认识

发布于:2022-12-27 ⋅ 阅读:(1275) ⋅ 点赞:(0)

本文介绍常见测试和任意剪裁平面:剪裁测试、Alpha测试、模板测试和任意剪裁平面.

1.1 剪裁测试

在这里插入图片描述

剪裁测试,用来在渲染场景时限制绘制区域,实现同时在屏幕上绘制主视角与次视角场景。

1.1.1 剪裁测试原理

启用剪裁测试后,绘制将会在指定矩形区域进行,不在此区域内的片元会被丢弃,在区域内的片元进入帧缓冲。

1.1.2 核心代码

 GLES20.glEnable(GLES20.GL_SCISSOR_TEST);//启用剪裁测试
 GLES20.glScissor(0, 0, 230, 200);//设置区域
 GLES20.glDisable(GLES20.GL_SCISSOR_TEST);//禁用剪裁测试

1.2 Alpha测试

在这里插入图片描述

Alpha测试可以实现任意形状绘制区域的。

1.2.1 Alpha测试原理

OpenGL ES中每个颜色都有4个通道————RGBA,A代表了透明度(Alpha)通道。当绘制一个片元时,首先检测其Alpha值,若Alpha值满足要求,则通过测试,绘制此片元,否则丢弃此片元,不进行绘制。

1.2.2 编程实现

OpenGL ES 2.0中没有支持Alpha测试的API,我们需要通过自定义着色器来实现Alpha测试。如下所示:

precision mediump float;
varying vec2 vTextureCoord; //接收从顶点着色器过来的参数
uniform sampler2D sTexture;//纹理内容数据
void main() {
   vec4 bcolor = texture2D(sTexture, vTextureCoord);//给此片元从纹理中采样出颜色值
   if(bcolor.a<0.6) {
   		discard;//丢弃当前片元
   } else {
      gl_FragColor=bcolor;
  }
}

上面代码中的“discard”操作即为丢弃当前片元。

1.3 模板测试

想要将绘制限定在某一不规则区域内,可以采用本节学习的模板测试。
在这里插入图片描述

1.3.1 模板测试原理

模板测试就是通过模板缓冲中记录的模板信息来完成。渲染管线在模板缓冲区中为每个位置的片元保存了一个“模板值”,当像素需要进行模板测试时,将设定的模板参考值与该片元对应位置的模板值进行比较,符合条件的片元通过测试,不符合条件的则被丢弃,不进行渲染。

1.3.2 核心代码

            GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT);//清除模板缓冲
            GLES20.glEnable(GLES20.GL_STENCIL_TEST);//允许模板测试
            GLES20.glStencilFunc(GLES20.GL_ALWAYS, 1, 1);//设置模板测试参数
            GLES20.glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_REPLACE);//模板测试后的操作
            GLES20.glDisable(GLES20.GL_STENCIL_TEST);//禁用模板测试

1.3.3 模板测试的比较模式

上述代码中“GLES20.glStencilFunc(GLES20.GL_ALWAYS,1,1)”第一个参数“GLES20.GL_ALWAYS”是比较模式参数,它包括下表所示的8种:

比较模式 含义
GL_NEVER 从不通过模板测试
GL_ALWAYS 总是通过模板测试
GL_LESS 只有参考值<(模板缓冲区的值&mask)时才通过
GL_LEQUAL 只有参考值<=(模板缓冲区的值&mask)时才通过
GL_EQUAL 只有参考值=(模板缓冲区的值&mask)时才通过
GL_GEQUAL 只有参考值>=(模板缓冲区的值&mask)时才通过
GL_GREATER 只有参考值>(模板缓冲区的值&mask)时才通过
GL_NOTEQUAL 只有参考值!=(模板缓冲区的值&mask)时才通过

表中“&”代表位与操作。

1.3.4 glStencilOp(…)参数含义

  • 参数1表示模板测试未通过时此片元对应的模板值如何变化;
  • 参数2表示模板测试通过,但深度测试未通过时此片元对应的模板值如何变化(没有启用深度测试,默认深度测试总是通过);
  • 参数3表示模板测试和深度测试均通过时此片元对应的模板值如何变化

3个参数可选值参考表:

参数值 模板值变化情况
GL_KEEP 不改变
GL_ZERO 回零
GL_REPLACE 使用测试条件中的设定值来代替当前模板值
GL_INCR 增加1,但如果已经是最大值,则保持不变
GL_NCR_WRAP 增加1,但如果已经是最大值,则重新从零开始
GL_DECR 减少1,但如果已经是零,则保持不变
GL_DECR_WRAP 减少1,但如果已经是零,则重新设置为最大值
GL_INVERT 按位取反

1.4 任意剪裁平面

在这里插入图片描述

仅绘制某一特定平面所确定半空间中的物体部分,其他部分不绘制,如同切掉物体一部分一样。

1.4.1 基本原理

用户可以指定任意一个平面进行剪裁,剪裁平面可以用于删除场景中无关的物体部分,比如显示物体的剖面图。

OpenGL ES 2.0中想要实现任意剪裁平面需要在片元着色器中通过编程实现。

  1. 定义剪裁平面参数A、B、C、D,4个参数代表平面解析方程(Ax+By+Cz+D=0)中的4个系数;
  2. 剪裁平面4个参数传入渲染管线,给着色器使用;
  3. 顶点着色器中判断顶点是否在平面的某一侧(使用平面方程验证),完成计算得到的值传入片元着色器
  4. 片元着色器根据接收到的值与0之间的关系得到顶点与剪裁平面之间的位置关系,以决定是否丢弃片元。

若Ax+By+Cz+D>0,则顶点在平面的一侧,反之在另一侧。

【参考】

  1. https://www.khronos.org/opengles/
  2. 《OpenGL ES应用开发实践指南 Android卷 Kevin Brothaler》
  3. https://en.wikipedia.org/wiki/OpenGL_ES
  4. https://developer.android.google.cn/guide/topics/graphics/opengl
  5. https://developer.android.google.cn/training/graphics/opengl
  6. 《Android3D游戏开发技术宝典OpenGL ES 2.0》
  7. 字节流动OpenGL ES开发极简教程