5

I've succeeded in getting tesselation control and evaluation shaders to work correctly, but the lighting for my scene is still blocky because I've been calculating per (triangle) face normals, instead of per vertex. Now that I'm using tesselation, it seems necessary to calculate new normal vertors for the newly tesselated vertexes in either the tess eval or geometry shader.

In order to get smooth per vertex normals I need to calculate per face normals for every triangle sharing the vertex in question, then compute a weighted average of these face normals. But I'm not sure how to get all those triangle faces in the tess eval or geometry shader. The layout (triangles_adjacency) in option for the geometry shader looks promising, but theres not much information about how to use it.

Is it possible to compute smooth per vertex normals on the GPU without the use of a normal/bump map in this way? The end goal is to have smooth per vertex lighting that benefits from the increased level of tesselation detail.

Here are my tessellation control and evaluation shaders:

// control
#version 400

layout (vertices = 3) out;

in vec3 vPosition[];
out vec3 tcPosition[];

const float tessLevelInner = 1.0;
const float tessLevelOuter = 1.0;

void main()
{
    tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];
    if (gl_InvocationID == 0) {
        gl_TessLevelInner[0] = tessLevelInner;
        gl_TessLevelOuter[0] = tessLevelOuter;
        gl_TessLevelOuter[1] = tessLevelOuter;
        gl_TessLevelOuter[2] = tessLevelOuter;
    }
}

// eval
#version 400

layout (triangles, equal_spacing, cw) in;
uniform mat4 uProj;
uniform mat4 uModelView;

in vec3 tcPosition[];
out vec3 tePosition;

void main()
{
    vec3 p0 = gl_TessCoord.x * tcPosition[0];
    vec3 p1 = gl_TessCoord.y * tcPosition[1];
    vec3 p2 = gl_TessCoord.z * tcPosition[2];

    tePosition = p0 + p1 + p2;
    gl_Position = uProj * uModelView * vec4(tePosition, 1);
}
cdk
  • 6,698
  • 24
  • 51
  • "*In order to get smooth per vertex normals I need to calculate per face normals for every triangle sharing the vertex in question, then compute a weighted average of these face normals.*" No. If you're using tessellation, the tessellation algorithm generally will provide the ability to compute normals, just as it provides the ability to compute positions. – Nicol Bolas May 02 '13 at 00:48
  • i'm doing tesselation in the tess control and eval shaders in a pretty standard fashion. Could you please go into more detail on how the tessellation algorithm can compute normals? – cdk May 02 '13 at 01:03
  • What is a "standard fashion" for that? Tessellation is, generally speaking, *completely* arbitrary. How you compute the normals depends entirely on your tessellation algorithm. – Nicol Bolas May 02 '13 at 01:46
  • right now I'm not doing anything fancy with dynamic tesselation levels, I've posted my tess shader code and the vertex shader is trivial. – cdk May 02 '13 at 01:52
  • What you don't seem to get is this: I could give you an answer for *this particular* "tessellation" algorithm. But it wouldn't help you when you actually start doing real tessellation. When you move on to an actual tessellation algorithm, you would have to move on to a different normal computation algorithm too. The way you compute your positions affects the way you compute your normals. – Nicol Bolas May 02 '13 at 02:04
  • 2
    and no generalization is available? Does the method I proposed above using the geometry shader have any merit? If you could explain how to compute the normals in this specific case, and why it wouldnt work for a different tessellation algorithm, that would probably help me better understand this problem. – cdk May 02 '13 at 02:19
  • You said you are computing per-face normals, but OpenGL doesn't have a per-face vertex buffer, so you must be passing them per-vertex somehow. If that so, why don't you just interpolate vertex normals in the same way you interpolate vertex positions, but with normalization? – kvark Dec 05 '13 at 22:26

0 Answers0