Archived

This topic is now archived and is closed to further replies.

carb

Help with Normals - Almost there ...

Recommended Posts

Allright, after much painstaking trouble, I came up with an algorithm to calculate normals in linear time for my heightmap renderer. The effect is ... decent ... but altogether, incorrect, it seems: Notice the checker-board artifacts. Even though the triangles themselves seem to be pointing in the correct direction / have the right shaded color, an outline appears in some situations ... particularly on steep hills, like this one. The algorithm is as follows: I have triangles ordered in an array (this is rendered with triangle lists) ... For each vertex in each triangle, I access all the triangles in the list which touch it using some fancy array manipulation, take the average, normalize, etc. Sounds right to me ... Any opinions? Appreciate it, - Ben

Share this post


Link to post
Share on other sites
Try either this:

for (int y = 0; y < HEIGHT; y++){
for (int x = 0; x < WIDTH; x++){
normalmap[x][y].x = heightmap[x][y]-heightmap[x+1][y];
normalmap[x][y].y = 1;
normalmap[x][y].z = heightmap[x][y]-heightmap[x][y+1];
//Don't forget to normalize the vector
Normalize(cp[x][y]);
}
}

-or- this:

for (int y = 0; y < HEIGHT; y++){
for (int x = 0; x < WIDTH; x++){
normalmap[x][y].x = heightmap[x-1][y]-heightmap[x+1][y];
normalmap[x][y].y = 2;
normalmap[x][y].z = heightmap[x][y-1]-heightmap[x][y+1];
//Don't forget to normalize the vector
Normalize(cp[x][y]);
}
}


and tell me/show me how it works.
If you want the thing to tile the stuff, you'll want a modulus in there. Check this page for a terse explanation of dot3 + normals related material.

If you still get the checkerboard pattern going on, you could either area sample the vectors (to smooth them) or chalk it (the problem) up to gourad shading .

-Michael


[edited by - thr33d on November 14, 2003 1:10:09 PM]

Share this post


Link to post
Share on other sites
When I was working on my bezier patch program, I had the same problem. I never really understood the fix that I did, but it worked. What I was doing was rendering all my tris like this:


I then, using the exact same normal calculator, changed the triangle layout to this:


... and it worked.

Anyway, may not be the same situation but if it is, you should try this.

[edited by - ISOPimp on November 14, 2003 1:55:30 PM]

[edited by - ISOPimp on November 14, 2003 1:57:23 PM]

Share this post


Link to post
Share on other sites
Reply 1: Err, yeah, I''ve been doing that from the start. That''s only one step.

Reply 2: I''m currently using the second method. For some reason it''s just appearing like it''s the 1st ...

Like, I''ve been debugging this for hours, and hours ... I was just wondering if, for some reason, there was some silly option I needed turned on that would make everything magically work correctly.

But I guess not ;(

I''m still open to suggestions. The actual code I use is like, 100 lines for it all, so, I''m not going to post it ...

- Ben

Share this post


Link to post
Share on other sites
Er Post 1, sorry, misread it. That''s an interesting alternative, but calculating the normals isn''t the problem. As you can see - this is shaded properly. Just ... the lines ...

- Ben

Share this post


Link to post
Share on other sites
I think it's the normals, and I think the lines are caused by your vertex normal calculation algorithm, because it treats all 9 neighbouring triangles having an equal weighting on each vertex's normal, when in reality they don't. Thr33d's method should work anyway.

[edited by - benjamin bunny on November 14, 2003 6:49:23 PM]

Share this post


Link to post
Share on other sites
I''m not so sure ...

For example, this is taken using Thr33d''s method #2 (method #1 yields similar results).



Same type of lines. Furthermore, both algorithms produced less realistic lighting effects (this was the best example I could find) ...

- Ben

Share this post


Link to post
Share on other sites
That's because threed's method is wrong. I should have read it properly before recommending it.

What you should be doing is just taking calcuating 4 vectors from each point to each of it's 4-connected neighbours. Then get the sum of the 4 cross products of each vector with the next (moving round clockwise), and normalise the result.

BTW, you will always get lines to some extent; this is a side-effect of Gouraud shading. If you want to eliminate that then you'll have to write a fragment program to do per-pixel lighting.

[edited by - benjamin bunny on November 14, 2003 7:54:11 PM]

Share this post


Link to post
Share on other sites
So given the following vertex ...

.......a....w
.......|.../
.......|../
d----v----b
.......|
.......|
.......c

(dots used just to space everything out correctly )

I should calculate (a - v), (b - v), (c - v) and (d - v), ignore (w - v)?

Also, the algorithm I wanted to emulate was this one, which I've seen on countless webpages / source and seems to work allright.

(in pseudo code)
for each vertex {
sum = (0, 0, 0)
for each triangle {
if vertex is in triangle, add normal of triangle to sum
}
normalize sum
add sum to some normal list
}

- Ben

[edited by - carb on November 15, 2003 12:40:46 PM]

[edited by - carb on November 15, 2003 12:41:33 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
What also helps is giving a weight to each of the triangle normals for each vertex. Normals get weight should be the percentage of the full circle they contribute to the vertex in question''s normal.

Share this post


Link to post
Share on other sites
Okay, now using the method suggested by Ben, I get the _exact_ same result as my original algorithm in the first post. Interesting ... so I wasn''t crazy afterall. But, admittedly, this method is way, way faster.

So yeah, the lines are back - that same image I showed at the very top is the very same.

Maybe I''ve just been blinded by perfection I just wanted to make sure I had the lighting down perfect before I moved on to texturing. Although, I suppose, once that''s there, it''ll look more proper.

Thanks all.

- Ben

Share this post


Link to post
Share on other sites
Benjamin bunny''s solution was the best, and fastest. For best results, consider as many vertices as possible for each vertex.

I mean, you can''t avoid these artifacts, I''ve learned. They''ll be far less noticable once you map a texture over top, believe me.

If you want more accurate lighting, consider using lightmap shading.

- Ben

Share this post


Link to post
Share on other sites