As described in OpenGL Vertex Post-Processing https://www.khronos.org/opengl/wiki/Vertex_Post-Processing Under User-defined Clipping, I am trying to clip each vertex send to a plane in the vertex shader. Providing only an index per vertex, so that I can access the UBO's data, which contains the clipping plane information, determined and send before the actual BIG data push.
"...It is possible to mitigate this by using a UBO to store an array of clipping regions, with each vertex simply specifying an integer index into that array...."
The problem is that somehow I cannot access the UBO with a simple indexing, because the clip index buffer sent along just refuses to work, although the data is full and correct. (Inspected in NSight).
The GPU simply thinks that I want to access only the first clipping rect. (ClipIndex is always equal to ZERO); So it only works for the first window in my simple imgui.
So I have heard of OpenGL not accepting indexing since version 1.2 or something. Is this the reason??? They have even set a hard restriction on the size of the UBO (I think 6kb). What then is the specific reason why I cannot access my data? I can fetch a texel from wherever I want in a texture, but I cannot get some simple data with a constant size buffer.
It compiles clean, I have checked for errors and validated the program. Also links fine. If I hard set it into the vertex shader it works fine. Meaning that if I want to clip only for window one (Clip.Rects[1]) no problem. When I introduce a single contiguous array of indices, we are out of the game. The array is always treated as if it is full with ZEROs.
I know the code may not be optimal. For now we are trying to reach the working phase.
I am new to asking questions here, so please don't hate me for the wrong indentation of the code.
The alternatives, in my opinion, are to draw 6 or less verts per rectangle and each time I have to clip to a different plane do it manually changing the glScissor() or glClipPlane(). And the second one, which comes to mind, is to use a texture to store the data, which I don't like, because it is not a texture :D.
Why my approach is busted? And are there better ways to clip one contiguous array of vertex data to multiple planes?
#version 400 core
struct rect
{
float X;
float Y;
float Width;
float Height;
};
layout (shared) uniform clip_rects
{
rect Rects[50];
} Clip;
out float gl_ClipDistance[6]; // Clipping each vert to a rectangle plane
// Skippied some unrelated info colors depth...
in vec2 RectVBO;
in int ClipIndex;
uniform mat4 PCMatrix;
void main()
{
gl_Position = PCMatrix * vec4(RectVBO.xy, Depth, 1.0f);
//FIRST ATTEMPT (already in -1,1 space)
vec2 v0 = vec2(Clip.Rects[ClipIndex].X, Clip.Rects[ClipIndex].Y);
vec2 v1 = vec2(Clip.Rects[ClipIndex].X + Clip.Rects[ClipIndex].Width, Clip.Rects[ClipIndex].Y);
vec2 v2 = vec2(Clip.Rects[ClipIndex].X + Clip.Rects[ClipIndex].Width, Clip.Rects[ClipIndex].Y + Clip.Rects[ClipIndex].Height);
vec2 v3 = vec2(Clip.Rects[ClipIndex].X, Clip.Rects[ClipIndex].Y + Clip.Rects[ClipIndex].Height);
//END OF FIRST ATTEMPT
//Even this doesn't work!
//SECOND ATTEMPT
vec2 v0 = vec2(0.0f,0.0f);
vec2 v1 = vec2(0.0f,0.0f);
vec2 v2 = vec2(0.0f,0.0f);
vec2 v3 = vec2(0.0f,0.0f);
//NOTE: It only takes the first if block if we set it to 1, 2, 3
//for example its all set to the above zeroed out vec2s.
if(ClipIndex == 0)
{
v0 = vec2(Clip.Rects[0].X, Clip.Rects[0].Y);
v1 = vec2(Clip.Rects[0].X + Clip.Rects[0].Width, Clip.Rects[0].Y);
v2 = vec2(Clip.Rects[0].X + Clip.Rects[0].Width, Clip.Rects[0].Y + Clip.Rects[0].Height);
v3 = vec2(Clip.Rects[0].X, Clip.Rects[0].Y + Clip.Rects[0].Height);
}
else if(ClipIndex == 1)
{
v0 = vec2(Clip.Rects[1].X, Clip.Rects[1].Y);
v1 = vec2(Clip.Rects[1].X + Clip.Rects[1].Width, Clip.Rects[1].Y);
v2 = vec2(Clip.Rects[1].X + Clip.Rects[1].Width, Clip.Rects[1].Y + Clip.Rects[1].Height);
v3 = vec2(Clip.Rects[1].X, Clip.Rects[1].Y + Clip.Rects[1].Height);
} else if(ClipIndex == 2)
{
v0 = vec2(Clip.Rects[2].X, Clip.Rects[2].Y);
v1 = vec2(Clip.Rects[2].X + Clip.Rects[2].Width, Clip.Rects[2].Y);
v2 = vec2(Clip.Rects[2].X + Clip.Rects[2].Width, Clip.Rects[2].Y + Clip.Rects[2].Height);
v3 = vec2(Clip.Rects[2].X, Clip.Rects[2].Y + Clip.Rects[2].Height);
}
// END OF SECOND ATTEMPT
//Tried "local" variable indexing still no progress.
//THIRD ATTEMPT
vec2 v0 = vec2(0.0f,0.0f);
vec2 v1 = vec2(0.0f,0.0f);
vec2 v2 = vec2(0.0f,0.0f);
vec2 v3 = vec2(0.0f,0.0f);
for(int k = 0; k < 3; k++)
{
if(k == ClipIndex)
{
v0 = vec2(Clip.Rects[k].X, Clip.Rects[k].Y);
v1 = vec2(Clip.Rects[k].X + Clip.Rects[k].Width, Clip.Rects[k].Y);
v2 = vec2(Clip.Rects[k].X + Clip.Rects[k].Width, Clip.Rects[k].Y + Clip.Rects[k].Height);
v3 = vec2(Clip.Rects[k].X, Clip.Rects[k].Y + Clip.Rects[k].Height);
}
}
//END OF THIRD ATTEMPT
vec2 VecToVertex0 = gl_Position.xy - v0;
vec2 VecToVertex1 = gl_Position.xy - v1;
vec2 VecToVertex2 = gl_Position.xy - v2;
vec2 VecToVertex3 = gl_Position.xy - v3;
vec2 v0v1 = v1 - v0;
vec2 v1v2 = v2 - v1;
vec2 v2v0 = v0 - v2;
vec2 v0v2 = v2 - v0;
vec2 v2v3 = v3 - v2;
vec2 v3v0 = v0 - v3;
gl_ClipDistance[0] = dot(v0v1, VecToVertex0);
gl_ClipDistance[1] = dot(v1v2, VecToVertex1);
gl_ClipDistance[2] = dot(v2v0, VecToVertex2);
gl_ClipDistance[3] = dot(v0v2, VecToVertex0);
gl_ClipDistance[4] = dot(v2v3, VecToVertex2);
gl_ClipDistance[5] = dot(v3v0, VecToVertex3);
}
ClipIndexwhich is an integer in the GLSL code. If you pass it at C++ code by usingglUniform1fthen that is wrong. You must useglUniform1i(note the 'i' at the end)in int ClipIndex;. I'd make the same guess as here.