Sign in to follow this  
Prune

Help with Phong Tessellation

Recommended Posts

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;
uniform int quadMode;
uniform int quadID;

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)
{
	if (quadMode == 1) return quadPhongGeometry(u, v, 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)
{
	if (quadMode == 1) return quadPhongNormal(u, v, 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 this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this