0

I have a list of faces [index], that a list of vertices and normals are mapped to. I generate offsets at each vertex to produce terrain/variation, but by doing so the vertice normals stop working like they should. This is what I do to make the shading work again, namely try to redo the vertice normals (vn);

for (auto &x : normals)x = vec3(0);  //zero normals first
vec3 facenormal; //buffer

for (size_t i = 0; i<indices.size();)  //iterate 3 points per face
{
   //find the face normal (b-a x c-a)
    facenormal = cross(  
        (shape[indices[i + 1]] - shape[indices[i]]), 
        (shape[indices[i + 2]] - shape[indices[i]])
        );

    //add this face normal, to each of the 3 vn slots nearby
    normals[indices[i++]] += facenormal; //note +=
    normals[indices[i++]] += facenormal;
    normals[indices[i++]] += facenormal;
}

for (auto &x : normals)x = normalize(x); //then normalize them

According to this reply it should do the trick. But, something is wrong with the approach.

It causes artifacting like shown on in the lower half of the image, while the shading mostly seems to work.

notice the visible lines

The question is: how should I calculate the vn's, to avoid these lines?

Remaking the parser: The way I was parsing (loading) the model was taking out duplicate index-values, which can save reference faces that I have to pass to the GPU, but will cause some of the values to stack/be reused. Atleast I suspect this was the problem, since it seems alot cleaner now. The only problem however is I'm getting flat shading all of a sudden. The flat shading makes it hard to see if the problem is really gone too, but I suspect it is. Why the new parsing produces flat shading after recalculation is beyond me. But these are the results im looking at.

enter image description here

I still have to find out the correct formula to calculate vertex normals? I dont understand why the shading was round before, but now its flat, all because I stopped stacking 1/4th of the index values?

Finding the right solution, finally! As NicoSchertler pointed out, the vertex normals were not of the base mesh. The way I load the vertices/uv/normals to fit the index for the glDrawElementsBaseVertex render-call, means cycling through the vertices and normals as they are loaded, does not refer to the base, but copies designed to fit indexing for uv+normals.

Soo, what I end up getting is weird artifacting and flat shading, as the values I'm modifying are post-parsing. Making every face not-unique does not solve anything, but clarify part of the problem, namely that I needed to modify the base index-values, not the loaded index ones.

after calculating vertice normals on the base mesh

After I recalculate for the base mesh (pre indexing) I get this result; smooth shading and visible differences for the mountainsides. The model is higher poly (and serialized in binary) and the coloring is still in the its early stages. It is however, shadily correct.

Community
  • 1
  • 1
Charlie
  • 585
  • 9
  • 17
  • That happens when there are duplicate vertices. I.e. the faces do not reference the same vertex (for which the normal would be averaged) but two distinct vertices with the same position. One way to solve this is to merge duplicate vertices, potentially under consideration of the angle between faces to preserve sharp features. – Nico Schertler Mar 17 '17 at 07:28
  • Shouldnt normalizing balance that out? like im doing already. – Charlie Mar 17 '17 at 07:59
  • I'm curious what would you get if you would lose the i++ when adding face normal and put it in the `for`... – Adrian Roman Mar 17 '17 at 08:19
  • the exact same thing, i+=3 in the for, instead of 3 i++'s make the same thing. I just made it like that, since one single [i] with 2 [i++]s looked lonely ;) – Charlie Mar 17 '17 at 08:22
  • I meant not `i+=3` in `for`, but `i++` – Adrian Roman Mar 17 '17 at 08:42
  • like a wrinkly tomato, the line is still at the same place, which baffles me – Charlie Mar 17 '17 at 08:49
  • 2
    No, normalization has nothing to do with that. It is pretty obvious in the image that there are two vertices with different normals at the same position (where there is the discontinuity). And you need to match these vertices somehow. Other than that, your normal calculation is fine. – Nico Schertler Mar 17 '17 at 09:13
  • The torus vertices probably start (and end) where the line is, I'm not surprised that averaging normals for triangles give so different normals for start and end. You'll probably have to somehow average at the start with the triangles that are at the end (and vice versa) in order to get rid of that line. – Adrian Roman Mar 17 '17 at 12:08
  • I suggest asking on graphics programming too – realvictorprm Mar 18 '17 at 06:44
  • @NicoSchertler you were on to somthing I suspect. I was parsing the file in a way that was sharing index-references. But now my shading is flat so idk what – Charlie Mar 18 '17 at 08:13
  • 1
    If you are not reusing any vertices any more, then you end up with a lot of duplicates (same position, different normal). The problem before was that there was not enough re-usage. As I said - you have to find duplicates based on their position and when you visit a face during normal calculation, you have to add the face normals also to the duplicates for the vertices of that face. – Nico Schertler Mar 18 '17 at 08:20
  • you were right about everything :D @NicoSchertler If you could mention how base values need to be modified, and not the indexex copies, ill give you the answer for it :) – Charlie Mar 19 '17 at 00:20

0 Answers0