如何在 OpenGL ES 2 或 3 上进行裁剪平面?

Fra*_*ank 3 opengl-es clipping opengl-es-2.0 opengl-es-1.1 opengl-es-3.0

在 iOS 或 Android 上,我可以选择切换到 OpenGL ES 2 或 3。我不确定为什么要切换到 OpenGL ES 2 或 3,因为我不是在开发 3D 游戏,但如果我要切换,我将如何实现裁剪平面?据称这些在 ES 2 中已被删除。

我特别希望避免在剪切平面的矢量发生变化时重新编译任何着色器代码。

Rab*_*d76 5

在 OpenGL ES 中,您必须使用EXT_clip_cull_distance扩展。

在顶点着色器中,您必须设置gl_ClipDistance[i]输出。指定每个用户剪裁平面igl_ClipDistance[i]的剪裁距离。其中 0.0 表示顶点位于剪裁平面上,> 0.0 表示顶点位于剪裁平面内。

必须启用剪辑功能。
例如

glEnable( CLIP_DISTANCE0_EXT );
Run Code Online (Sandbox Code Playgroud)

使用的顶点着色器gl_ClipDistance可能如下所示,其中是Ax + By + Cz + Du_clipPlane形式的平面方程(将其想象为平面的法向量和到原点的距离):

#extension GL_EXT_clip_cull_distance : enable

precision highp float;

attribute vec3 inPos;   

uniform mat4 u_projectionMat44;
uniform mat4 u_viewMat44;
uniform mat4 u_modelMat44;
uniform vec4 u_clipPlane;

void main()
{   
    vec4 modelPos      = u_modelMat44 * vec4( inPos, 1.0 );
    gl_Position        = u_projectionMat44 * u_viewMat44 * modelPos;
    gl_ClipDistance[0] = dot(modelPos, u_clipPlane);
}
Run Code Online (Sandbox Code Playgroud)

另请参阅顶点后处理 - 用户定义的裁剪小 Grasshopper - 裁剪平面教程。


如果扩展不可用,则可以通过丢弃片段在片段着色器中模拟剪辑。请参阅片段着色器 - 特殊操作

另请参阅OpenGL ES 着色语言 1.00 规范;6.4 跳跃;第 58 页

丢弃关键字仅允许在片段着色器中使用它可以在片段着色器中使用以放弃对当前片段的操作。该关键字导致片段被丢弃,并且不会发生任何缓冲区的更新。它通常用在条件语句中,例如:

if (intensity < 0.0)
    discard;
Run Code Online (Sandbox Code Playgroud)

以下 WebGL 示例演示了这一点。请注意,WebGL 1.0上下文与 OpenGL ES 2.0 API 非常一致。

glEnable( CLIP_DISTANCE0_EXT );
Run Code Online (Sandbox Code Playgroud)
#extension GL_EXT_clip_cull_distance : enable

precision highp float;

attribute vec3 inPos;   

uniform mat4 u_projectionMat44;
uniform mat4 u_viewMat44;
uniform mat4 u_modelMat44;
uniform vec4 u_clipPlane;

void main()
{   
    vec4 modelPos      = u_modelMat44 * vec4( inPos, 1.0 );
    gl_Position        = u_projectionMat44 * u_viewMat44 * modelPos;
    gl_ClipDistance[0] = dot(modelPos, u_clipPlane);
}
Run Code Online (Sandbox Code Playgroud)
if (intensity < 0.0)
    discard;
Run Code Online (Sandbox Code Playgroud)