Opengl es OpenGL ES 2.0中的裁剪平面

Opengl es OpenGL ES 2.0中的裁剪平面,opengl-es,glsl,shader,opengl-es-2.0,clipping,Opengl Es,Glsl,Shader,Opengl Es 2.0,Clipping,在OpenGL ES 2.0中,我需要在一个剪切平面下剪切几百个对象,如果有经验的人能够提供这个OpenGL子集,我将不胜感激 在OpenGLES1.x中有glClipPlane。在桌面上,着色器中有glClipPlane或gl_ClipDistance。OpenGL ES 2.0中没有这两个版本。这种功能似乎在2.0中完全消失了 似乎唯一的方法是A)在片段着色器中运行平面方程,或B)编写一个非常复杂的顶点着色器,如果顶点位于平面上,则将其放置在平面上 (A) 与glClipPlane相比速度较

在OpenGL ES 2.0中,我需要在一个剪切平面下剪切几百个对象,如果有经验的人能够提供这个OpenGL子集,我将不胜感激

在OpenGLES1.x中有glClipPlane。在桌面上,着色器中有glClipPlane或gl_ClipDistance。OpenGL ES 2.0中没有这两个版本。这种功能似乎在2.0中完全消失了

似乎唯一的方法是A)在片段着色器中运行平面方程,或B)编写一个非常复杂的顶点着色器,如果顶点位于平面上,则将其放置在平面上

(A) 与glClipPlane相比速度较慢,因为“常规”剪裁是在顶点着色器之后和片段着色器之前完成的,因此每个片段仍需部分处理和丢弃

(B) 很难使着色器之间兼容,因为我们不能丢弃顶点,我们必须将它们与平面对齐,并调整“切割”的属性。如果不发送纹理中的所有顶点并对其进行采样,则无法在着色器中的顶点之间进行插值,这将非常昂贵。通常情况下,可能无论如何都不可能正确插入数据

我还考虑将近平面与剪裁平面对齐,这将是一个有效的解决方案

在渲染整个场景并检查深度失败后绘制平面也不起作用(除非您的视线接近垂直于平面)

对单个对象有效的方法是将平面绘制到深度缓冲区,然后使用glDepthFunc(GL_更大)渲染对象,但正如预期的那样,当一个对象位于另一个对象之后时,该方法不起作用。我试图建立在这个概念上,但最终得到了与影子卷非常相似的东西,而且同样昂贵


那么我错过了什么?如何在OpenGL ES 2.0中进行平面剪裁?

我不知道这是否适用于OpenGL ES,但OpenGL具有glEnable启用的gl_ClipDistance可变输出(gl_CLIP_DISTANCE0)。启用后,将剪裁基本体,以便在顶点和几何体着色器之后gl_ClipDistance[0]>=0

剪辑距离可以指定为具有世界空间平面方程式的点积:


我发现了两种解决方案

  • 使用Harri Smatt的着色器:

    uniform mat4 uModelM;
    uniform mat4 uViewProjectionM;
    attribute vec3 aPosition;
    varying vec3 vPosition;
    void main() {
      vec4 pos = uModelM * vec4(aPosition, 1.0);
      gl_Position = uViewProjectionM * pos;
      vPosition = pos.xyz / pos.w;
    }
    

    precision mediump float;
    可变vec3位置;
    void main(){
    if(位置z<0.0){
    丢弃;
    }否则{
    //选择渲染的实际颜色。。
    }
    }
    
  • 使用Alessandro Bocalatte的四深度缓冲区:

    • 禁用颜色写入(即设置
      GLCOLORSMASK(假、假、假、假);
    • 渲染一个与标记形状匹配的四边形(即,只有一个与标记大小和位置/方向相同的四边形);这将只渲染到深度缓冲区(因为我们在上一步中禁用了颜色缓冲区写入)
    • 启用回颜色掩码(
      GLCOLORSMASK(真、真、真、真);
    • 渲染3D模型
  • 由于该扩展在OpenGL ES 2.0中不可用(因为该扩展需要OpenGL ES 3.0),因此必须模拟剪辑。通过丢弃片段,可以在片段着色器中模拟它。看

    另见:

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

    if (intensity < 0.0)
        discard;
    
    片段着色器:

    varying vec3  vertPos;
    varying vec3  vertCol;
    varying float clip_distance;
    
    void main()
    {
        if ( clip_distance < 0.0 )
            discard;
        gl_FragColor = vec4( vertCol.rgb, 1.0 );
    } 
    
    
    高精度浮点;
    属性vec3inpos;
    属性vec3-inNV;
    属性向量3 inCol;
    可变vec3垂直位置;
    可变vec3-vertNV;
    可变vec3-vertCol;
    不同的浮动距离;
    均匀mat4 u_投影mat44;
    统一mat4 u_视图MAT44;
    统一mat4 u_型MAT44;
    均匀vec4 u_clipPlane;
    void main()
    {   
    mat4 mv=u_视图MAT44*u_模型MAT44;
    vertCol=inCol;
    vertNV=正常化(mat3(mv)*inNV);
    vec4 viewPos=mv*vec4(inPos,1.0);
    vertPos=viewPos.xyz;
    gl_位置=u_投影地图44*viewPos;
    vec4 modelPos=u_modelMat44*vec4(inPos,1.0);
    vec4 clipPlane=vec4(规格化(u_clipPlane.xyz),u_clipPlane.w);
    剪辑距离=点(modelPos,clipPlane);
    }
    精密中泵浮子;
    可变vec3垂直位置;
    可变vec3-vertNV;
    可变vec3-vertCol;
    不同的浮动距离;
    void main()
    {
    如果(夹持距离<0.0)
    丢弃;
    vec3颜色=vertCol;
    gl_FragColor=vec4(color.rgb,1.0);
    } 
    剪辑
    
    实际上有一个甚至支持GLES2的软件,但恐怕只有在苹果设备上才能找到。这个问题有标签。OpenGL 2.0 ES没有
    gl\u ClipDistance
    。请参见(GLSL ES 1.00对应于OpenGL ES 2.00)。实际上,这就是问题所在:“在OpenGL ES 2.0中剪裁平面”
    attribute vec3 inPos;
    attribute vec3 inCol;
    
    varying vec3  vertCol;
    varying float clip_distance;
    
    uniform mat4 u_projectionMat44;
    uniform mat4 u_viewMat44;
    uniform mat4 u_modelMat44;
    uniform vec4 u_clipPlane;
    
    void main()
    {   
        vertCol        = inCol;
        vec4 modelPos  = u_modelMat44 * vec4( inPos, 1.0 );
        gl_Position    = u_projectionMat44 * u_viewMat44 * viewPos;
        clip_distance  = dot(modelPos, u_clipPlane);
    }
    
    varying vec3  vertPos;
    varying vec3  vertCol;
    varying float clip_distance;
    
    void main()
    {
        if ( clip_distance < 0.0 )
            discard;
        gl_FragColor = vec4( vertCol.rgb, 1.0 );
    }