Anton Ponikarovskii
Anton Ponikarovskii

Reputation: 13

Implementing clip planes with geometry shaders?

What am I using: Qt 5.11.1, MinGW 5.3, Windows 10, C++11, GPU: NVidia 820M (supports OpenGL 4.5)

My task: I have non-solid (just surface) object, rendering by glDrawArrays, and i need to get cross-section of this object by plane. I have found ancient openGL function glClipPlane, but its not compability with VAOs and VBOs. Also Ive found out that its possible to rewrite glClipPlane via geometry shader.

My questions/problems:

  1. Do you know other ways to realize this task?

  2. 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 QOpenGLShaderProgram::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.

look of adding shader into program

screenshot

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

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

Fragment shader:

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;

}    

Upvotes: 1

Views: 2665

Answers (2)

Fibbs
Fibbs

Reputation: 1420

While glClipPlane is deprecated in modern OpenGL, the concept of clipping planes is not.

In your CPU code before you start drawing the geometry to be clipped you must enable one of the clipping planes.

glEnable(GL_CLIP_DISTANCE0);

Once you have finished drawing you would disable this in a similar way.

glDisable(GL_CLIP_DISTANCE0);

You are guaranteed to be able to enable minimum of 8 clipping planes.

In your vertex or geometry shader you must then tell OpenGL the signed distance of your vertex from the plane so that it knows what to clip. To be clear you don't need a geometry shader for clipping but it can be done there if you wish. The shader code would look something like the following:

// 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);

Upvotes: 1

derhass
derhass

Reputation: 45322

Let's sort out a few misconceptions first:

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

That is not correct. The user defined clip planes via glClipPlane are indeed deprecated in modern GL, and removed from core profiles. But if you use a context where they still exist, you can combine them with VAOs and VBOs without any issue.

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

You don't need a geometry shader for custom clip planes.

The modern way of user-defined clip planes is calculating gl_ClipDistance for each vertex. While you can modify this value in a geometry shader, you can also directly generate it in the vertex shader. If you don't otherwise need a geometry shader, there is absolutely no reason to add it just for the clip planes.

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.

You first need to find out which OpenGL version you're actually using. With Qt, you can easily end up with an OpenGLES 2.0 context (depending on how you create the context, and also how your Qt was compiled). Your shader code is either desktop GL 2.x (GLSL 1.10/1.20) or GLES 2.0 (GLSL 1.00ES), but not valid in modern core profiles of OpenGL.

GLES2 does not support geometry shaders at all. It also does not support gl_ClipDistance, so if you _really) have to use GLES2, you can try to emulate the clipping in the fragment shader. But the better option would be switching to a modern core profile GL context.

Upvotes: 3

Related Questions