使用几何着色器实现裁剪平面?

时间:2018-07-18 15:59:45

标签: c++ qt opengl geometry-shader

我正在使用什么:Qt 5.11.1,MinGW 5.3,Windows 10,C ++ 11,GPU:NVidia 820M(支持OpenGL 4.5)

我的任务:我有非实体(仅表面)对象,通过glDrawArrays渲染,并且需要按平面获取该对象的横截面。我已经找到了古老的openGL函数glClipPlane,但它与VAO和VBO的兼容性不强。我也发现可以通过几何着色器重写glClipPlane。

我的问题/问题:

  1. 您知道实现此任务的其他方法吗?

  2. 我真的不明白,如何在QtCreator中添加几何着色器,没有几何着色器的“图标”,我试图添加顶点着色器并将其重命名为.gsh或只是.glsl,尝试使用{ {1}}并在程序中编写着色器代码,但是每次添加几何着色器时,在字符串上出现“ QOpenGLShader:无法创建着色器”。

看起来要在程序中添加着色器

screenshot

顶点着色器:

QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source)

几何着色器:

layout (triangles) in;
layout (triangles) out;
layout (max_vertices = 3) out;

void main()
{
    int i;

    for (i = 0; i < gl_in.length(); i++)
    {
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

片段着色器:

layout (triangles) in;
layout (triangles) out;
layout (max_vertices = 3) out;

void main()
{
    int i;

    for (i = 0; i < gl_in.length(); i++)
    {
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

2 个答案:

答案 0 :(得分:3)

让我们先解决一些误解:

  

已经发现了古老的openGL函数glClipPlane,但它与VAO和VBO的兼容性不强。

那是不正确的。通过glClipPlane定义的用户剪切平面在现代GL中确实已弃用,并已从核心轮廓中删除。但是,如果使用它们仍然存在的上下文,则可以将它们与VAO和VBO结合使用而没有任何问题。

  

我也发现可以通过几何着色器重写glClipPlane

自定义裁剪平面不需要几何着色器。

用户定义的裁剪平面的现代方式是为每个顶点计算gl_ClipDistance。您可以在几何着色器中修改此值,也可以在顶点着色器中直接生成该值。如果您不需要几何着色器,则完全没有理由仅将其添加到剪切平面。

  

我真的不明白,如何在QtCreator中添加几何着色器,没有几何着色器的“图标”,我试图添加顶点着色器并将其重命名为.gsh或只是.glsl,尝试使用{{1} }并在程序中编写着色器代码,但是每次添加几何着色器时,在字符串上出现“ QOpenGLShader:无法创建着色器”。

您首先需要确定您实际使用的OpenGL版本。使用Qt,您可以轻松获得OpenGL ES 2.0上下文(取决于创建上下文的方式以及Qt的编译方式)。您的着色器代码是桌面GL 2.x(GLSL 1.10 / 1.20)或GLES 2.0(GLSL 1.00ES),但在现代OpenGL核心配置文件中无效。

GLES2完全不支持几何着色器。它还不支持OpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source),因此,如果您确实需要使用GLES2,则可以尝试使用emulate the clipping in the fragment shader。但是更好的选择是切换到现代的核心配置文件GL环境。

答案 1 :(得分:1)

glClipPlane在现代OpenGL中已被弃用,但裁剪平面的概念却没有。

在您的CPU代码中,开始绘制要修剪的几何图形之前,必须启用一个修剪平面。

glEnable(GL_CLIP_DISTANCE0);

完成绘制后,您将以类似的方式禁用它。

glDisable(GL_CLIP_DISTANCE0);

保证您至少可以启用8个剪切平面。

然后在顶点或几何着色器中,您必须告诉OpenGL顶点与平面的距离,以使其知道要裁剪的内容。需要明确的是,您不需要 用于剪切的几何着色器,但是可以根据需要在此处完成。着色器代码如下所示:

// vertex in world space
vec4 vert_pos_world = world_matrix * vec4(vert_pos_model, 1.0);

// a horizontal plane at a specified height with normal pointing up
// could be a uniform or hardcoded
vec4 plane = vec4(0, 1, 0, clip_height_world);

// 0 index since that's the clipping plane we enabled
gl_ClipDistance[0] = dot(vert_pos_world, plane);