Good evening everyone,
I have recently started using openGl for my thesis work but my knowledge is very basic and I am having a bit of trouble. In particular, I drew a cube and I wanted to use glClipPlane to cut it with respect to a nonstandard plane ( on the diagonal ) but despite tutorials and examples I can not. Does anyone have any advice or examples on how to do this?
Thanks to all.
Depends on which version are you woking on, but glClipPlane is an outdated function and it doesn’t work with VBOs.
glClipPlane
controls clipping planes in the fixedfunction pipeline and is deprecated.
That being said, you should use gl_ClipDistance instead, which lets you perform custom clipping operations on your vertex shader.
So, assuming that is the main reason why you cannot clip the object, try the following:
vert shader
void main(void){
...
vPos = vec3(modelViewM * in_Vertex);
vec4 u_plane0 = vec4(1,0,0,0);
gl_ClipDistance[0] = dot(u_plane0, vPos); //If you want to clip using the camera coordinate system
gl_ClipDistance[0] = dot(u_plane0, in_Vertex); //If you want to clip using the local coordinate system
gl_ClipDistance[0] = dot(u_plane0, camMat * modelViewM * in_Vertex); //If you want it in global system
}
and enable this plane in your program:
glEnable(GL_CLIP_DISTANCE0);
This statement aswritten is false. glCipPlane and VBOs are apples and oranges. They can work together just fine and have nothing to do with each other.
If we’re going to be pedantic, let’s be properly pedantic. You can put vertex data into buffer objects that are used by the fixed function pipeline (which includes clip planes). However, if you use generic vertex attributes (ie: glVertexAttribPointer
), you must also be using shaders, which override clip plane math in favor of letting you do whatever you want to compute clip distances.
We don’t want to give the impression that any use of VBOs is orthogonal to clip planes.
Thank you all very much for your answers!
My vertex shader is this:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoords;
out vec3 ourColor;
out vec2 TexCoords;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 view;
void main(void)
{
TexCoords = aTexCoords;
ourColor = aColor;
gl_Position = projection * view * model * vec4(aPos , 1.0f);
}
I’m having a little difficulty understanding what corresponds to what.
vPos
what is it? The modelViewM
should correspond to my view
(mat4
) which should then be multiplied by a vec4
(so in_Vertex
is a vec4
but who is it?) and multiplying these two vPos
will then be a vec4
.
Following this reasoning, shouldn’t it be
void main(void) {
...
vec4 vPos = vec4(view * in_Vertex);
vec4 plane0 = vec4(0,1,0);
...
}
that way the
gl_ClipDistance[0] = dot(plane0, vPos);
m fits because it is the product of two vec4
s
but the other two gl_ClipDistance
s don’t fit (because I don’t understand what in_Vertex
is).
Thanks again to everyone!
UPDATE:
Perhaps I have understood, in_Vertex corresponds to my already defined gl_Position, right?
this is the result of your modelviewmatrix times your vertex that is currently being processed. (same as gl_ModelViewMatrix * gl_Vertex)
in_Vertex is the vertex data received by your vertex attribute while processed by the shader. (same as gl_Vertex)
gl_Position should be = gl_ModelViewProjectionMatrix* gl_Vertex;
but, like I said, use the system that suits you best for this case:
About those other 2 gl_ClipDistance[0], they are not meant to be all used at the same time, those are options depending on which coordinate system you want to use, so for what you need, you would only need to use on of them as the commonent next to each line says.
gl_ClipDistance[0] = dot(plane0, gl_Vertex); // Gives you the clipping on the object refrence coordintates
gl_ClipDistance[0] = dot(plane0, gl_ModelViewMatrix * gl_Vertex); // Gives you the clipping on the view coordintates
Depending on what you want, you could perfomr the transformations as needed.
With the fixedfunction pipeline, the plane passed to glClipPlane
is specified in object coordinates but stored in eye coordinates.
When using shaders, you can use whatever coordinate system you want, but the plane and the points tested against it need to be in the same coordinate system.
If you have separate model and view matrices, then aPos
is in object coordinates, model * aPos
is in world coordinates, and view * model * aPos
is in eye coordinates. Use whichever one matches the coordinate system of the clip plane(s).
Thats why it was followed by
Meaning that using attributes sent on to the shader wont be working with the glClipPlane
Thanks again to all for your answers.
This is what I got by using this Vertex Shader:
============================================================
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoords;
out vec3 ourColor;
out vec2 TexCoords;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 view;
void main(void)
{
vec4 vPos = vec4(view * model);
vec4 plane0 = vec4(0, 1, 1 ,0);
TexCoords = aTexCoords;
ourColor = aColor;
gl_Position = projection * view * model * vec4(aPos , 1.0f);
gl_ClipDistance[0] = dot(model*vec4(aPos,1.0f), plane0);
}
=====================================================
and setting a cutting plane of the type vec4(0,1,1,0).
I define this vec4
in the Vertex Shader though, what if I wanted to update it directly from the main instead?
My goal is to give it 9 floats (the coordinates of three points in space) to calculate the plane passing through those three points and cut with respect to that. That’s why I created this function:
====================================================
std::vector<float> get_plane(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3)
{
std::vector<float> cutplane;
float a1 = x2  x1;
float b1 = y2  y1;
float c1 = z2  z1;
float a2 = x3  x1;
float b2 = y3  y1;
float c2 = z3  z1;
float a = (b1 * c2)  (b2 * c1);
float b = (a2 * c1)  (a1 * c2);
float c = (a1 * b2)  (b1 * a2);
float d = ((a * x1)  (b * y1)  (c * z1));
cutplane.push_back(a);
cutplane.push_back(b);
cutplane.push_back(c);
cutplane.push_back(d);
return cutplane;
};
=====================================================
But I guess that’s not good enough… Should I output a vec4
instead of an std::vector
? So I can call it back in the vertex, right?
=============================================================================
UPDATE
22:57
monday, 20 dicember 2021 (CET)
I managed to create the custom cutting planes by modifying the function: now it returns a vec4 which when fed to the vertex shader allows me to bypass the vec(0,1,1,0) in the void.
I also added two more cutting planes and got three cuts on my cube.
Thank you all!
Another curiosity: I got this cube cut by using 3 cutting planes together but, as the cube is empty, of course you can see the inside… Is there a way to “close” the hole? Or a way to make a solid “full” from the start?
Thank you all!
The main options are to either modify the mesh, adding a vertex for each edge which intersects the clip plane and replacing each connected set of vertices which are excluded with a polygon, or to use stencilling (see e.g. here).
Eventually on my cube I was able to create three cutting planes and cut simultaneously using
gl_ClipDistance[0] = dot(gl_Position, plane_equation0).
Now I have another question:
I went from a manually defined cube by writing the vertices to a loaded obj model and now I can’t cut the object with gl_ClipDistance anymore.
For simplicity to create the cutting plane I take the point (0.0, 0.0, 0.0) that belongs to the object but is also the center of the global reference system.
This is my vertex shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 2) in vec2 vertexUV;
layout(location = 1) in vec3 vertexNormal_modelspace;
out vec2 UV;
out vec3 Position_worldspace;
out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 view;
uniform vec3 LightPosition_worldspace;
mat4 MVP=projectionviewmodel;
uniform vec4 plane_equation0;
uniform vec4 plane_equation1;
uniform vec4 plane_equation2;
void main(){
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
Position_worldspace = (model * vec4(vertexPosition_modelspace,1)).xyz;
vec3 vertexPosition_cameraspace = ( view * model * vec4(vertexPosition_modelspace,1)).xyz;
EyeDirection_cameraspace = vec3(0,0,0)  vertexPosition_cameraspace;
vec3 LightPosition_cameraspace = ( view * vec4(LightPosition_worldspace,1)).xyz;
LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
Normal_cameraspace = ( view* model * vec4(vertexNormal_modelspace,0)).xyz;
UV = vertexUV;
gl_ClipDistance[0] = dot(plane_equation0, gl_Position);
};
actually to cut in the global reference system I should use
gl_ClipDistance[0] = dot(plane_equation0, MVP);
but still the object is not clipped.
Where am I going wrong?
Thank you all!
This should have no impact on the process assuming the structure is exactly the same (ie, no transformations or vertex differences)
The gl_ClipDistance is essencially telling the the gpu where to place a clip plane, and if the geometry is placed at the same position, then the effect should be the same regardless of the creation process.
This is not in model space but in localspace, the model space is after applying the Model Matrix, but as it is only a name, there is no problem here.
Have you enabled the GL_CLIP_DISTANCE0
using glEnable(GL30.GL_CLIP_DISTANCE0);
?
And no, you should use:
gl_ClipDistance[0] = dot(plane_equation0, model*vertexPosition_modelspace);
Actually the objects are very different because from a cube of 1cm side I switched to a full size bone so I had to, compared to the cube, move the camera. Also, before the camera was fixed and I rotated only the object while now the camera rotates and the object is still.
GL_CLIP_DISTANCE0 is enabled.
I tried to use
gl_ClipDistance[0] = dot(plane_equation0, model*vec4(vertexPosition_modelspace,1));
but it still doesn’t work.
I guess it’s a reference system issue at this point?
what is your equation vector? this should be in global coordinates system.
try the following:
gl_ClipDistance[0] = dot(vec4(1, 0, 0, 0), model*vec4(vertexPosition_modelspace,1));
and you should see a cut right down the middle.
This is the function with which I calculate the cutting plane
vec4 get_plane(array<vec3,3> vertices_plane)
{
float x1, y1, z1, x2, y2, z2, x3, y3, z3;
vec4 cutplane;
x1 = vertices_plane[0][0];
y1 = vertices_plane[0][1];
z1 = vertices_plane[0][2];
x2 = vertices_plane[1][0];
y2 = vertices_plane[1][1];
z2 = vertices_plane[1][2];
x3 = vertices_plane[2][0];
y3 = vertices_plane[2][1];
z3 = vertices_plane[2][2];
float a1 = x2  x1;
float b1 = y2  y1;
float c1 = z2  z1;
float a2 = x3  x1;
float b2 = y3  y1;
float c2 = z3  z1;
float a = (b1 * c2)  (b2 * c1);
float b = (a2 * c1)  (a1 * c2);
float c = (a1 * b2)  (b1 * a2);
float d = ((a * x1)  (b * y1)  (c * z1));
cutplane[0] = a;
cutplane[1] = b;
cutplane[2] = c;
cutplane[3] = d;
return cutplane;
};
my workflow is this:

I pass to a get_points_for_plane function a vec3 (which is a point that belongs to the object) and I calculate two more points on the plane I want to define;

I take these 3 points and pass them to the get_plane function with which I calculate the equation of the plane;
I assign the equation of the plane that comes out to plane_equation[i] and send it to the vertex shader.
gl_ClipDistance[0] = dot(vec4(1, 0, 0, 0), model*vec4(vertexPosition_modelspace,1));
even with this I see no cut
do you have any transformation at all? is out object translated?
If so, try the following:
gl_ClipDistance[0] = dot(vec4(1, 0, 0, 0), vec4(vertexPosition_modelspace,1));
because you should see at least a cut, if your objects is:
 Having a clear transformation model (ie, your model matrix is entity)
 your mesh vertex data is centered (ie, iits center of mass is in its local origin)
If you still can’t see the cut, try to change to a simples cube mesh (obj) and check if the same line works
I’m not really sure about this condition… how would i check it?
I can’t see any cuts with this one either…
It shouldn’t be a camera problem because even with the cube, when I was using
gl_ClipDistance[0] = dot(plane_equation0, gl_Position);
I could rotate and see the cube from different angles and it still showed me the various cuts.
Here instead it doesn’t seem to find the mesh points to cut
@Manel_Goucha
I have found the problem: they don’t like these two lines of code. commenting them I can make the cut even if I lose all the part of light and therefore you can’t see them anymore.
Without knowing the rest of your code (Fragment shader, etc) from a quick look around it shouldn’t have to impact your clipping.
Clipping happens on the geometry positioning part of the pipeline (in the Vertex Shader), so, unless you are using those variables to perform some extra positioning/transforming operations, that shouldn’t have to imapct on the clipping itself.