Smooth Normal Artifacts

I have been working on a renderer for some time now that will draw some quadratics on the screen. However I am having problem with smoothing the normals. I think I am calculating them okay, but they are not turning out right. For each point I am taking the normals for each of the faces (there are four of them) that use that point, and adding them together. Then I let OpenGL normalize the vectors (I think it’s glEnable(RESCALE_NORMALS) or somthing like that) Here is the result:

tbc++

Any Ideas?

BTW, forgot to mention the two of them have flat shading, and the others are suposed to be smooth, but as you can see on the Hyperboloid, somthing went wrong. It’s like there is a pattern on the edges or somthing.

I think it is probably working at least where you have obvious smooth shading, clearly the last two objects are flat shaded with no normal averaging. The problems with your smooth objects are related to classic Mach banding in conjunction with triangulated shading. (Real original definition of Mach banding as opposed to the abuse of the term.)

Basically your visual system is good at detecting changes in the derivative of brightness exaggerating it perceptually and extracting that as a visual feature. In addition OpenGL implementations tend to take quads drawn and decompose them into two triangles split along a diagonal axis, when you split a quad to a pair of triangles with smooth shading you can often see the diagonal due to simple color interpolation. These two issues are conspiring to produce visible shading artifacts on your primitives. The solution is additional subdivision.

Dorbie’s right, but I would like to point out that if you’re ever unsure of your normals, just draw them (although you’ll probably want to normalize them first). To draw them, just draw a line from each point to the point + the point’s normal. It’s a whole lot easier to see if they’re wrong that way.

Why not plugging in a pair of programs and passing the normal to the fragment, renormalizing it and dotting it with light at each pixel ?

SeskaPeel.

By the way, it is glEnable(GL_NORMALIZE) and not rescale normals. The latter can only be used when scaling a model with already normalized normals.

Well spotted.

Changed the glEnable(GL_RESCALE_NORMALS) to glEnable(GL_NORMALIZE). No avail. Drew the lines representing the normals, nothing wrong. Still having the same problems. Nothing I have done changed it at all. I even tried feeding OpenGL straight triangles instead of quads, no difference.

I’m at the end of my rope!

Any ideas?

tbc++

Didn’t you read my post? Those comments still stand, at most the normalize might have caught some non unit normals affecting brightness. This is just a limit of smooth shading, subdivide more.

I would love to think that you are right, however, how is it that the glutSolidSphere routines are perfectly smooth at a 10x10 subdivision, while my sphere looks like the above picture at the same resolution? I would love to just stick with the glut routines, but I need more flexability.

tbc++

Very strange then. Have you taken an individual quad and examined it’s screen space shading pixel by pixel? Just confirm it is linear (or perspective linear) on the triangles, that’s about all you can do there.

Try drawing the normals also, you may want to make sure they’re sane.

You could also flip the subdivision of the quad based on shape & shading, I have done this for constrained cases to eliminate the diagonal artifacts.

Maybe try drawing quads instead of triangles if you don’t already (although hardware decomposes to tris I heard some plans to improve on this and hardware has the ability to do that now)

Other than these I’m out of ideas. Glut may happen to subdivide differently (triangulation on the quads) but that should be of no consequence on the average.

P.S. I don’t necessarily believe you about the glut sphere, I think you should draw them side by side (and nothing else) to compare.

perhaps you’re duplicating vertices with flat normals in your vertex stream?

Why don’t you just look at the glut source code ?

Okay, this is for a comercial project, so I don’t think I can “just look at the glut code”.

Let’s say I have point [u,v]

and this function that returns a [x,y,z] point for a given [u,v] point

float *get_point(float u,float v);

Can someone please write out for me some type of (psudo)code that would calculate the smooth normal for each point in a quad, if each point is defined as

[u,v]------------------[u+1, v]
| |
| |
| |
| |
| |
| |
| |
| |
| |
[u,v+1]---------------[u+1,v+1]

Thanks alot,

tbc++

1. loop through all points
2. looph through all polys, to see in which one the point actually is
3. take the normal and add it to the “average normal”
4. take the average normal vector and average it
5. this average normal is your smoothed normal for your desired point

That’s what I thought. I’ll have to dive into the code again and see if I can find what is wrong…

Just as a side note I noticed a other day that the bump mapping example in the nVidia SDK (aka “Simple Bump Mapping” - an Opengl demo where it shows a globe of the world) appears to be suffering from a similar problem. And I’m reasonably sure that it didn’t always have this problem. It’s not as noticeable but it is there. That’s probably because their tesselation is much higher.

tbc++ it’s probably worth looking at the Glut code just to see what it is doing that is different to your code (eg. maybe immediate mode versus Vertex buffers is the difference - or something similar).

I have a suggestion of something to try to be absolutely sure you have a problem. Construct a sphere centered on the origin, and then set the normal at each point equal to the coordinate of that point. If this looks the same as your existing sphere, then there’s nothing you can do without increasing your tesselation. On the other hand, if it looks different, then your calculated normals probably aren’t right.

Based on looking at a sphere tesselation that I did myself (with triangles), I do tend to agree that yours doesn’t look quite right. But I wouldn’t swear for sure that it’s wrong.