T junctions in simple distanced based tesselation

87 Views Asked by At

I implemented a simple distance based LOD for future terrain rendring using tesselation control/evaluation shader in openGL. Surptisingly, I still get cracks (T junctions) in my output... The shader code is

uniform mat4 pvmM;
uniform vec4 u_camerapos;

#ifdef TESSELATION_CONTROL_SHADER
layout(vertices = 4) out;

unsigned int dist(vec3 p1,vec3 p2,vec3 p3)
{

    float d=distance((p1+p2)/2.0,p3); // precise float d=(...)
    if (d<1.5) return 64;
    if (d<2.5) return 32;
    if (d<3) return 16;
    if (d<4) return 8;
    if (d<5) return 4;
    if (d<6) return 2;
    return 1;
}

void main() {
    if (gl_InvocationID == 0){
        gl_TessLevelOuter[0] = dist( gl_in[3].gl_Position.xyz,gl_in[0].gl_Position.xyz,u_camerapos.xyz);
        gl_TessLevelOuter[1] = dist( gl_in[0].gl_Position.xyz,gl_in[1].gl_Position.xyz,u_camerapos.xyz);
        gl_TessLevelOuter[2] = dist( gl_in[1].gl_Position.xyz,gl_in[2].gl_Position.xyz,u_camerapos.xyz);
        gl_TessLevelOuter[3] = dist( gl_in[2].gl_Position.xyz,gl_in[3].gl_Position.xyz,u_camerapos.xyz);
        float mean=floor((gl_TessLevelOuter[0]+gl_TessLevelOuter[1]+gl_TessLevelOuter[2]+gl_TessLevelOuter[3])/4.0);
        gl_TessLevelInner[0] = int(mean);
        gl_TessLevelInner[1] = int(mean);
        }
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;  
    }
#endif
#ifdef TESSELATION_EVALUATION_SHADER
void main() {
    vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
    vec4 p2 = mix(gl_in[2].gl_Position, gl_in[3].gl_Position, gl_TessCoord.x);
    gl_Position = pvmM*mix(p1, p2, gl_TessCoord.y);
    }
#endif

Using python: vertices and indices are generated using

blocksz=8
vertices=np.array([(x,0,z) for z in range(blocksz) for x in range(blocksz)],dtype='f4')
vertices=vertices-np.array([blocksz/2,0,blocksz/2])
faces= np.array([(x+z*blocksz,x+1+z*blocksz,x+(z+1)*blocksz,x+1+(z+1)*blocksz ) for z in range(blocksz-1) for x in range(blocksz-1)  ],dtype='i4')

and drawn using

glDrawElements(GL_PATCHES,count,GL_UNSIGNED_SHORT,None)

On the image below,

you can see the results. some T-Junctions are present on the x axis (left-right, for example first and last columns) but never on the z axis (top bootom). virtual camera is represented by red dot and its position is passed as uniform.

All the rest is working as expected. Any idea of what I'm mis-understanding?

1

There are 1 best solutions below

0
On

OK, found the bug. When generating the index array (faces), I used a wrong winding (same winding as for GL_QUAD_STRIP). The correct faces array should be:

faces= np.array([(x+z*blocksz,x+1+z*blocksz,x+1+(z+1)*blocksz,x+(z+1)*blocksz ) for z in range(blocksz-1) for x in range(blocksz-1)  ],dtype='i4')

Then, in tess evaluation shader (notice fliiping points 2 and 3

vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
vec4 p2 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);