【问题标题】:Implementing clip planes with geometry shaders?使用几何着色器实现剪切平面?
【发布时间】:2018-12-26 15:13:26
【问题描述】:

我在用什么: 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,尝试使用@ 987654323@ 并在程序中编写着色器代码,但每次我在添加几何着色器的字符串上得到“QOpenGLShader:无法创建着色器”时。

在程序中添加着色器的样子


顶点着色器:

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;

}    

【问题讨论】:

    标签: c++ qt opengl geometry-shader


    【解决方案1】:

    我们先理清几个误区:

    找到了古老的openGL函数glClipPlane,但它不兼容VAOs和VBOs。

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

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

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

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

    我真的不明白,如何在 QtCreator 中添加几何着色器,没有几何着色器的“图标”,我尝试添加顶点着色器并将其重命名为 .gsh 或只是 .glsl,尝试使用 OpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::Geometry, QString &amp;source) 和在程序中编写着色器代码,但每次我在添加几何着色器的字符串上得到“QOpenGLShader:无法创建着色器”时。

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

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

    【讨论】:

    • 感谢您的建议。我明白需要解决更复杂的任务:保存某处点,这些点是通过我的 3d 对象和平面交叉的结果。开始谷歌,发现这个article。但它们都至少需要 GL 3.X。之后,我尝试切换到现代核心配置文件 GL 上下文:运行标准 Qt 示例“computegles31”并通过函数 OGLSupports 返回我没有 GL >=2.0 和计算着色器支持,仅支持 GLES 2.0、3.0。我该如何解决?
    • @AntonPonikarovskii:“我明白需要解决更复杂的任务:保存某处点,这些点是通过我的 3d 对象和平面交叉的结果。”嗯,没有。你需要把它存起来做什么?您可以在顶点着色器中即时计算该值,并将其分配给适当的gl_ClipDistance 输出。您所需要的只是您的飞机的系数(例如制服)和一个简单的dot 产品。
    • @AntonPonikarovskii:就 GL 上下文创建而言:可能的情况取决于您运行它的设备、使用的驱动程序、Qt 版本以及编译时使用的一些选项,甚至可能是沿着 Qt 应用程序部署的一些 GL 库。我已经看到一些 Qt 项目带有自己版本的台面软件渲染器和/或 ANGLE。我不知道他们为什么这样做,但我真的不知道 qt。
    • 是的,我已经了解 gl_ClipDistance 方法并实现了它。但是当我实现这个方法时,我决定添加一些附加功能。我剪裁了具有复杂几何形状的房间的 3D 模型,通过剪裁我得到了这个平面上的墙壁边界。我想在边界内的这个 2D 平面中计算一些轨迹。所以,我需要通过模型和平面得到的这些点。感谢 Qt 和 GL。继续谷歌搜索和阅读。
    • “所以,我需要通过模型和平面交叉获得的这些点。”好吧,您可能应该只手动计算交叉点。 GL 不会帮你的。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多