# Help with Phong Tessellation

## Recommended Posts

Prune    224
I extracted the shader text from the executable in the demo at http://perso.telecom-paristech.fr/~boubek/papers/PhongTessellation/ but I don't see how p0-p3 are computed... and wouldn't they be different per triangle? Why send them as uniforms... Also, not sure what quadID is, though quadMode specifies triangle or quad and alpha is the depth value mentioned in the paper. The other thing not clear is how to actually subdivide; this shader only outputs the position, and looks like the demo executable uses OpenMesh for subdivision.
uniform vec3 n0, n1, n2, n3, p0, p1, p2, p3;
uniform float alpha;

varying vec4 P;
varying vec3 N;

vec3 project(vec3 p, vec3 c, vec3 n)
{
return p - dot(p - c, n) * n;
}

vec3 PhongGeometry(float u, float v, float w)
{
vec3 p = w * p0 + u * p1 + v * p2;
vec3 c0 = project(p, p0, n0);
vec3 c1 = project(p, p1, n1);
vec3 c2 = project(p, p2, n2);
vec3 q = w * c0 + u * c1 + v * c2;
vec3 r = mix(p, q, alpha);
return r;
}

vec3 bilinearInterpolation(float w, float u, vec3 p0, vec3 p1, vec3 p2, vec3 p3)
{
return u * (w * p0 + (1.0 - w) * p1) + (1.0 - u) * (w * p3 + (1.0 - w) * p2);
}

vec3 quadPhongGeometry(float u, float v, float w)
{
vec3 p;
if (quadID == 0) p = bilinearInterpolation(u, v, p0, p1, p2, p3);
else p = bilinearInterpolation(u, v, p2, p3, p0, p1);
vec3 c0 = project(p, p0, n0);
vec3 c1 = project(p, p1, n1);
vec3 c2 = project(p, p2, n2);
vec3 c3 = project(p, p3, n3);
vec3 q;
if (quadID == 0) q = bilinearInterpolation(u, v, c0, c1, c2, c3);
else q = bilinearInterpolation(u, v, c2, c3, c0, c1);
vec3 r = mix(p, q, alpha);
return r;
}

vec3 evalPos(float u, float v, float w)
{
else return PhongGeometry(u, v, w);
}

vec3 PhongNormal(float u, float v, float w)
{
return normalize(w * n0 + u * n1 + v * n2);
}

vec3 quadPhongNormal(float u, float v, float w)
{
if (quadID == 0) return normalize(bilinearInterpolation(u, v, n0, n1, n2, n3));
return normalize(bilinearInterpolation(u, v, n2, n3, n0, n1));
}

vec3 evalNormal(float u, float v, float w)
{
return PhongNormal(u, v, w);
}

void main(void)
{
float u = gl_Vertex.y;
float v = gl_Vertex.z;
float w = gl_Vertex.x;
gl_Vertex = vec4(evalPos(u, v, w), gl_Vertex.w);
gl_Normal = evalNormal(u, v, w);
P = gl_Vertex;
N = gl_Normal;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}

##### Share on other sites
Prune    224
Looks like the subdivision is done by replacing the original triangles with tessellated ones from a database, from a previous publication: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch05.html
The gl_Vertex holds the barycentric coordinates, and the uniforms are the original triangle positions (and normals). But this means that each original triangle to be refined would incur a separate uniform update and draw call...
Is there a way to avoid this if a geometry shader is used to subdivide? Or maybe something with instancing and uniform buffers?