1

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;

}    

2 Answers2

3

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.

derhass
  • 43,833
  • 2
  • 57
  • 78
  • thank you for your advices. I understood that need to solve more complex task: save somewhere points, which are result from crossing my 3d object and plane. Started to google, found this [article](https://stackoverflow.com/questions/13662005/run-on-buffer-object-and-change-its-data-by-shader). But all of them need at least GL 3.X. After that i tried to swith to a modern core profile GL context: run standart Qt example "computegles31" and through function OGLSupports it returns me that there is no GL >=2.0 and compute shaders support, supporting just GLES 2.0, 3.0. How can i fix it? – Anton Ponikarovskii Jul 23 '18 at 12:21
  • @AntonPonikarovskii: "I understood that need to solve more complex task: save somewhere points, which are result from crossing my 3d object and plane." uhm, no. What would you need to save that for? You calculate that value on the fly in the vertex shader, and just assign it to the appropriate `gl_ClipDistance` output. All you need are the coffecients for your plane(s) (e.g as uniform), and a simple `dot` product. – derhass Jul 23 '18 at 19:02
  • @AntonPonikarovskii: as far as the GL context creation goes: what's possible will depend on the device you're running this, the drivers in use, the Qt version and some with which options it was compiled, and maybe even some of the GL libraries which are deployed along your Qt application. I've seen some Qt projects coming with own versions of the mesa software renderer and/or ANGLE. I've no idea why they do that, but I really don't know about qt. – derhass Jul 23 '18 at 19:05
  • yes, I've understood gl_ClipDistance method and implemented it. But while I was implementing this method I decided to add some addition featch. I clip 3D model of room with complicated geometry, and by clipping I get walls border in this plane. I want to compute some trajectories in this 2D plane inside borders. So, I need this points which I get from crossing the model and plane. Thanks about Qt and GL. Continue googling and reading. – Anton Ponikarovskii Jul 24 '18 at 10:47
  • "So, I need this points which I get from crossing the model and plane." Well, you should proably just calculate the intersections manually. The GL isn't going to help you with that. – derhass Jul 24 '18 at 19:13
  • maybe you know some other methods which could help? I download my object from .obj file, so i know all vertices and how they connet between each other. – Anton Ponikarovskii Jul 25 '18 at 06:09
1

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);
Fibbs
  • 1,350
  • 1
  • 13
  • 23