-1

In the picture below you will see my current setup. I am rendering a sphere with heightmap information. The mesh is a square that is wrapped around a sphere. The source of light is located directly at the camera position. The problem that I have at the moment is the calculation of normals.

From what I found, one way of getting the normal vector on a continous surface, is for every vertex, find all vertices that are adjacent to it i nthe mesh (in my case I have 6 neighboring vertices) finding the normals to all six planes that they are forming, then adding them up and normalizing.

You can see the code below. Unfortunately, for some parts of the planet it seems to work, but not for everything. Also notice the strange shadow line that seems to go diagonnaly across the texture.

Any ideas what could be causing this behaviour?

EDIT: the issue is not related to the weight of the adjecent planes in the final normal calculation.

private Vector3f calcNormal(int x, int z)
{
    if ( x<1 || x> RESOLUTION-2 || z<1 || z > RESOLUTION -2) {
        Vector3f newNormal = new Vector3f();
        newNormal = globe[x][z].sub(this.getTransform().GetPos()).normalize();
        return newNormal;
    }
    Vector3f center = globe[x][z];
    Vector3f up = globe[x][z-1];
    Vector3f down = globe[x][z+1];
    Vector3f left = globe[x-1][z];
    Vector3f right = globe[x+1][z];
    Vector3f rightUp = globe[x+1][z-1];
    Vector3f leftDown = globe[x-1][z];


    Vector3f dUp = new Vector3f(center).sub(up);
    Vector3f dRightUp = new Vector3f(center).sub(rightUp);
    Vector3f dRight = new Vector3f(center).sub(right);
    Vector3f dDown = new Vector3f(center).sub(down);
    Vector3f dLeft = new Vector3f(center).sub(left);
    Vector3f dLeftDown = new Vector3f(center).sub(leftDown);


    Vector3f normal = new Vector3f(dUp.cross(dRightUp)).
                    add(new Vector3f(dRightUp.cross(dRight))).
                    add(new Vector3f(dRight.cross(dDown))).
                    add(new Vector3f(dDown.cross(dLeftDown))).
                    add(new Vector3f(dLeftDown.cross(dLeft))).
                    add(new Vector3f(dLeft.cross(dUp)));

    return normal.normalize();  

}

Screen

1 Answers1

0

This is maybe not the actual problem of your code, but it might still be good to know:

This simple algorithm wouldn't give you good results. You'll need to use some weighting factor on each adjacent normal that takes into account "how adjacent" a triangle is to your current vertex. For example, a normalized incident angle of the triangle could be used. The problem is quite good described in this presentation from Crytek.

Note, that since you are not normalizing the normals of the adjacent triangles you kind of do this already, since they are scaled by the size of parallelogram spanned by the two side vectors.

BDL
  • 21,052
  • 22
  • 49
  • 55
  • When I was researching the calculation of normals, I came across this issue. This is also why I did not normalize the adjecent triangle normals. – Tomasz Naglik Nov 06 '17 at 16:08
  • I'm just not sure that the weighting you use gives you the results you want. You weight by two times the size of the triangle and all of your triangles have the same size. But two of your triangles cover the 90° around you vertex while the other for cover 45° each. But as I said, I'm not sure this is the actual problem. – BDL Nov 06 '17 at 16:25
  • Ok, I got your point. I scaled down the two normals that cover 90 deg by 2, but there is no noticable effect on the rendering (even though I agree that it should be better now). From what I noticed, the dark shadow is at a diagonal where x=z. – Tomasz Naglik Nov 06 '17 at 16:32
  • Sorry then. I hope someone else can help you :) – BDL Nov 06 '17 at 20:07