Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: PN-AEN Triangles GLSL

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    5

    PN-AEN Triangles GLSL

    Hi.
    I've been doing some work regarding tessellation techniques for smoothing meshes. Plain PN Triangle was pretty easy to implement but I have quite a problem with PN-AEN Triangles. I've searched over the net looking for implementation in GLSL but I've found nothing. I hope you will help me understand if this can or cannot be done in GLSL.

    I wont describe all PN-AEN T. but explain what doesn't seems to work...

    First...is it possible for TCS to pass further into pipeline only 3 vertices insteed of 9 defined in patch? I'm aware of "layout(vertices = 3) out" but from what I can tell, when I set TES to triangles it consumes all 9 vertices from patch and makes 3 triangles instead of wanting 1. I can check this by using gl_PrimitiveID in TES. I have indices like this for eg.:
    1,2,3, - those I want to see as triangle
    4,5,6,7,8,9, - those are control points only for calculations (end of first patch)
    10,11,12, - triangle
    13,14,15,16,17,18 - calculations (end of second patch)
    I can see triangle (10,11,12,) only when (gl_PrimitiveID <= 3) - so 4,5,6 and 7,8,9 also make triangles (I can sometimes see them as artifacts - flying on screen)

    Second... does gl_InvocationID have the same order in patches as they were send to memory? From above where second patch had verts 10,11,12,13,14,15,16,17,18 is it right to assume that the first vert in this patch: 10 will have gl_Invocation: 1, next 11 - 2, 12 - 3, and so on? If not is there other way around to make them like this? I really need this so I've tested it and it seems that sometimes it is not consistent - for 108 indices (12 triangles, rest are control points) it fails for 2 triangles. Like in the image.
    Click image for larger version. 

Name:	Untitled.jpg 
Views:	281 
Size:	45.8 KB 
ID:	794

    I think that code is unnecessary but if someone want to look at it here it is:
    TCS
    Code :
    #version 400
     
    struct CP
    {
    	vec3 Pos[3];
    	vec3 Nor[2];
    };
    //------------------------------
    layout(vertices = 3) out;
     
    in vec3 vPosition[];
    in vec3 vNormal[];
    out CP cp[];
    patch out vec3 center;
     
    uniform float TessLevelInner;
    uniform float TessLevelOuter;
     
    #define ID gl_InvocationID
     
    void main()
    {
                    // for vert ID=0 use control points 3,4 (1 ID - 5,6; 2 ID - 7,8)
    		int IDnext    = (ID + 1) % 3;
    		int IDadd     = (ID * 2) + 3;
    		int IDaddNext = IDadd + 1;
     
    		vec3 P1i = vPosition[ID];
    		vec3 P2i = vPosition[IDnext];
    		vec3 N1i = normalize(vNormal[ID]);
    		vec3 N2i = normalize(vNormal[IDnext]);
     
    		vec3 P1o = vPosition[IDadd];
    		vec3 P2o = vPosition[IDaddNext];
    		vec3 N1o = normalize(vNormal[IDadd]);
    		vec3 N2o = normalize(vNormal[IDaddNext]);
     
    		vec3 posIns;
    		vec3 posOut;
     
    		cp[ID].Pos[0] = P1i;
     
    		posIns = (2 * P1i + P2i - dot(P2i - P1i, N1i) * N1i) / 3;
    		posOut = (2 * P1o + P2o - dot(P2o - P1o, N1o) * N1o) / 3;
    		cp[ID].Pos[1] = (posIns + posOut) / 2;
     
    		posIns = (2 * P2i + P1i - dot(P1i - P2i, N2i) * N2i) / 3;
    		posOut = (2 * P2o + P1o - dot(P1o - P2o, N2o) * N2o) / 3;
    		cp[ID].Pos[2] = (posIns + posOut) / 2;
     
     
    		float r12 = 2 * dot(P2i - P1i, N1i + N2i) / dot(P2i - P1i, P2i - P1i);
    			  r12+= 2 * dot(P2o - P1o, N1o + N2o) / dot(P2o - P1o, P2o - P1o);
    			  r12/=2;
    		cp[ID].Nor[0] = N1i;
    		cp[ID].Nor[1] = N1i + N2i - r12 * (P2i - P1i);
     
    		gl_TessLevelOuter[ID] = TessLevelOuter;
     
    		barrier();
    		if (ID == 0)
    		{
    			vec3 E = (cp[0].Pos[1] + cp[0].Pos[2] + 
    					  cp[1].Pos[1] + cp[1].Pos[2] + 
    					  cp[2].Pos[1] + cp[2].Pos[2]) / 6;
    			vec3 V = (vPosition[0] + vPosition[1] + vPosition[2]) / 3;
    			center = E + (E - V) / 2;
     
    			gl_TessLevelInner[0] = TessLevelInner;
    		}
    }
    TES
    Code :
    #version 400
     
    struct CP
    {
    	vec3 Pos[3];
    	vec3 Nor[2];
    };
     
    layout(triangles, equal_spacing, ccw) in;
    in CP cp[];
    patch in vec3 center;
     
    out vec3 tePosition;
    out vec3 tePatchDistance;
     
    uniform mat4 Projection;
    uniform mat4 Modelview;
     
    void main()
    {
    	if(gl_PrimitiveID % 3 == 0)
    	{
    		float u = gl_TessCoord.x;
    		float v = gl_TessCoord.y;
    		float w = gl_TessCoord.z;
     
    		vec3 pos = cp[0].Pos[0]*w*w*w   + cp[1].Pos[0]*u*u*u   + cp[2].Pos[0]*v*v*v   +
    				   cp[0].Pos[1]*w*w*u*3 + cp[0].Pos[2]*w*u*u*3 + cp[1].Pos[1]*u*u*v*3 +
    				   cp[1].Pos[2]*u*v*v*3 + cp[2].Pos[1]*v*v*w*3 + cp[2].Pos[2]*v*w*w*3 +
    				   center * u*v*w*6;
     
    		tePatchDistance = gl_TessCoord;
    		tePosition = pos;
    		gl_Position = Projection * Modelview * vec4(tePosition, 1);
    	}
    	else
    		gl_Position = vec4(0);
    }

    by if(gl_PrimitiveID % 3 == 0) I can prevent (control points) triangles from showing.
    Last edited by blackbee; 06-27-2012 at 12:14 PM.

  2. #2
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    5
    OK i spend two whole days to find a tiny mistake. I even implemented it on DirectX to test it out. Basically I forgot to change patch size to 9 .

    If I could I would edit or delete previous post but this option disappeared so let me clear things out.

    Quote Originally Posted by blackbee View Post
    First...is it possible for TCS to pass further into pipeline only 3 vertices insteed of 9 defined in patch? I'm aware of "layout(vertices = 3) out"
    Yes it's possible and "layout(vetices=#)" works fine (which is great!)
    Quote Originally Posted by blackbee View Post
    Second... does gl_InvocationID have the same order in patches as they were send to memory?
    Yes seems like it (which was kind of obvious).

    So the answer to the main question...
    Quote Originally Posted by blackbee View Post
    if this can or cannot be done in GLSL
    ... is also YES, here is the proof:
    TCS
    Code :
    #version 400
     
    struct CP
    {
    	vec3 Pos[3];
    	vec3 Nor[2];
    };
     
    layout(vertices = 3) out;
    in vec3 vPosition[];
    in vec3 vNormal[];
    out CP cp[];
    patch out vec3 center;
     
    uniform float TessLevelInner;
    uniform float TessLevelOuter;
     
    #define ID gl_InvocationID
     
    void main()
    {
    		int IDnext    = (ID + 1) % 3;
    		int IDadd     = (ID * 2) + 3;
    		int IDaddNext = IDadd + 1;
     
    		vec3 P1i = vPosition[ID];
    		vec3 P2i = vPosition[IDnext];
    		vec3 N1i = normalize(vNormal[ID]);
    		vec3 N2i = normalize(vNormal[IDnext]);
     
    		vec3 P1o = vPosition[IDadd];
    		vec3 P2o = vPosition[IDaddNext];
    		vec3 N1o = normalize(vNormal[IDadd]);
    		vec3 N2o = normalize(vNormal[IDaddNext]);
     
    		vec3 posIns;
    		vec3 posOut;
     
    		cp[ID].Pos[0] = P1i;
     
    		posIns = (2 * P1i + P2i - dot(P2i - P1i, N1i) * N1i) / 3;
    		posOut = (2 * P1o + P2o - dot(P2o - P1o, N1o) * N1o) / 3;
    		cp[ID].Pos[1] = (posIns + posOut) / 2;
     
    		posIns = (2 * P2i + P1i - dot(P1i - P2i, N2i) * N2i) / 3;
    		posOut = (2 * P2o + P1o - dot(P1o - P2o, N2o) * N2o) / 3;
    		cp[ID].Pos[2] = (posIns + posOut) / 2;
     
    		float r12 = 2 * dot(P2i - P1i, N1i + N2i) / dot(P2i - P1i, P2i - P1i);
     
    		cp[ID].Nor[0] = N1i;
    		cp[ID].Nor[1] = N1i + N2i - r12 * (P2i - P1i);
     
    		gl_TessLevelOuter[ID] = TessLevelOuter;
     
    		barrier();
    		if (ID == 1)
    		{
    			vec3 E = (cp[0].Pos[1] + cp[0].Pos[2] + 
    					  cp[1].Pos[1] + cp[1].Pos[2] + 
    					  cp[2].Pos[1] + cp[2].Pos[2]) / 6;
    			vec3 V = (cp[0].Pos[0] + cp[1].Pos[0] + cp[2].Pos[0]) / 3;
    			center = E + (E - V) / 2;
     
    			gl_TessLevelInner[0] = TessLevelInner;
    		}
    }

    for some reasons "gl_TessLevelOuter[gl_InvocationID] = TessLevelOuter;" doesnt seem to work in my 6XXX mobile radeon (but works in 5XXX). Maybe it's something with 'gl_InvocationID'. If you have similar problem just put there real numbers 0,1,2 and move it to 'if' body.

    TES
    Code :
    #version 400
     
    struct CP
    {
    	vec3 Pos[3];
    	vec3 Nor[2];
    };
     
    layout(triangles, equal_spacing, ccw) in;
    in CP cp[];
    patch in vec3 center;
     
    precise out vec4 P;
    precise out vec3 N;
    precise out vec3 E;
     
    uniform mat4 MProjection;
    uniform mat4 MModelview;
    uniform mat3 MNormal;
     
    void main()
    {
    	float u = gl_TessCoord.x;
    	float v = gl_TessCoord.y;
    	float w = gl_TessCoord.z;
     
    	precise vec3 pos = cp[0].Pos[0]*w*w*w   + cp[1].Pos[0]*u*u*u   + cp[2].Pos[0]*v*v*v   +
    			   cp[0].Pos[1]*w*w*u*3 + cp[0].Pos[2]*w*u*u*3 + cp[1].Pos[1]*u*u*v*3 +
    			   cp[1].Pos[2]*u*v*v*3 + cp[2].Pos[1]*v*v*w*3 + cp[2].Pos[2]*v*w*w*3 +
    			   center * u*v*w*6;
     
    	precise vec3 nor = cp[0].Nor[0]*w*w + cp[1].Nor[0]*u*u + cp[2].Nor[0]*v*v + 
    			   cp[0].Nor[1]*w*u + cp[1].Nor[1]*u*v + cp[2].Nor[1]*v*w;
     
        P = MProjection * MModelview * vec4(pos, 1);
        E = -(MModelview * vec4(pos,1)).xyz;
        N = MNormal * nor;
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •