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

Implementing clip planes with geometry shaders?

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

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

我的questions/problems:

  1. 你知道其他实现这个任务的方法吗?

  2. 我真的不明白,如何在QtCreator中添加几何着色器,没有"icon"几何着色器,我尝试添加顶点着色器并将其重命名为.gsh或只是。 glsl,尝试使用 QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source) 并在程序中编写着色器代码,但每次我在添加几何着色器的字符串上得到 "QOpenGLShader: could not create shader"。

将着色器添加到程序中的外观


顶点着色器:

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();
}

片段着色器:

precision mediump float;

uniform highp float u_lightPower;
uniform sampler2D u_texture;
uniform highp mat4 u_viewMatrix;
varying highp vec4 v_position;
varying highp vec2 v_texCoord;
varying highp vec3 v_normal;

void main(void)
{
    vec4 resultColor = vec4(0.25, 0.25, 0.25, 0.0);
    vec4 diffMatColor = texture2D(u_texture, v_texCoord);
    vec3 eyePosition = vec3(u_viewMatrix);
    vec3 eyeVect = normalize(v_position.xyz - eyePosition);
    float dist = length(v_position.xyz - eyePosition);
    vec3 reflectLight = normalize(reflect(eyeVect, v_normal));
    float specularFactor = 1.0;
    float ambientFactor = 0.05;

    vec4 diffColor = diffMatColor * u_lightPower * dot(v_normal, -eyeVect);//     * (1.0 + 0.25 * dist * dist);

    resultColor += diffColor;

    gl_FragColor = resultColor;

}    

先理清几个误区:

have found ancient openGL function glClipPlane, but its not compability with VAOs and VBOs.

这是不正确的。用户通过 glClipPlane 定义的裁剪平面在现代 GL 中确实已弃用,并已从核心配置文件中删除。但是,如果您使用它们仍然存在的上下文,则可以毫无问题地将它们与 VAO 和 VBO 结合使用。

Also Ive found out that its possible to rewrite glClipPlane via geometry shader.

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

用户定义裁剪平面的现代方法是为每个顶点计算 gl_ClipDistance。虽然您可以在几何着色器中修改此值,但您也可以直接在顶点着色器中生成它。如果您不需要几何着色器,绝对没有理由只为裁剪平面添加它。

I really dont understand, how to add geometry shader in QtCreator, there is no "icon" of geometry shader, I tried to add vertex shader and rename it to .gsh or just .glsl, tried to use OpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &source) and write shader code in program, but every time I get "QOpenGLShader: could not create shader" on string with adding geometry shader.

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

GLES2 完全不支持几何着色器。它也不支持gl_ClipDistance,所以如果你_really) 必须使用GLES2,你可以尝试emulate the clipping in the fragment shader。但更好的选择是切换到现代核心配置文件 GL 上下文。

虽然 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);