2

So I'm trying to generate terrain using marching cubes algorithm. At this point I'm implementing the diffuse lighting (fragment shader). I calculated normals for each vertex and got this: result

The left side of the picture displays the normals (for each vertex and triangle) and wireframe, to the right is the lighted landscape from the same camera angle.

so, i'm curious, what am I doing wrong?

I calculate normals this way:

for (int t = 0; t < all_triangles.size(); t++) {

        Vertex v0 = all_vertices[triangle.get_vertex(0)];
        Vertex v1 = all_vertices[triangle.get_vertex(1)];
        Vertex v2 = all_vertices[triangle.get_vertex(2)];

        QVector3D edge1 = v1 - v0;
        QVector3D edge2 = v2 - v0;

        QVector3D normal = QVector3D::crossProduct(edge1, edge2);
//        triangle.set_normal(normal.normalized());

        for (int v = 0; v < 3; v++) {
            all_vertices[triangle.get_vertex(v)].add_normal(normal.normalized());
        }
    }

    for (int v = 0; v < all_vertices.size(); v++) {
        auto normal = all_vertices[v].get_normal();
        normal.normalize();
        all_vertices[v].set_normal(normal);

    }

upd: vcs

bitbucket source

viache
  • 51
  • 5

3 Answers3

2

That's normal for marching cubes. It's a know problem of the algorythm with some technical name like redundant triangles. There is a very simple adjustment for that if you need less triangles and dont mind adding a compare equals line for every vertex, the fix is to snap iso values onto the corners of the cubes if they are more than 95% closer to them. MC optimizations are very cool the best would be octree sensing of used cubes and resizing the cubes relative to the complexity or flatness of the surface at that zone. there are awesome papers on the topic.

Here is a demonstration of a fast fix just by snapping values to corners if edge intersection proximity to corner is under 5% or over 95%, tunable, can try 90% if you want.

Generic MC: enter image description here

Simplest possible optimization: enter image description here

SnapMC is similar:

enter image description here

bandybabboon
  • 2,210
  • 1
  • 23
  • 33
1

Your math is correct. You normals are looks like fine, but it's very hard to 100% understand your picture.

common approach for debuging such problems is: - flat shading (no normal smoothing) - use triangle/vertex normal as color to visualize normals

Also please share your shading code.

Bagobor
  • 51
  • 3
  • so I got [that](http://i.imgur.com/op7mcbZ.png), looks pretty random. what could be my next step? why rendering normals using geometry shader gives plausible result, and this looks like mess? – viache Jan 31 '16 at 10:20
  • can you share you code please? github/bitbucket/whatever? – Bagobor Jan 31 '16 at 12:05
  • majority of normals must be blue, but yours are green. try to inverse vectors. (mult. it on -1 or change order of edges in cross product) – Bagobor Jan 31 '16 at 12:08
  • I have not Qt so cant run/debug your code directly. I found that you are not doing math. avg on your cumulative normals. For example: void Vertex::calc_avg_normal() { this->normal = (this->normal / triangles.size()).normalized(); } – Bagobor Jan 31 '16 at 12:58
  • is that necessary? I do `normal.normalize();` to cumulative normals. Dividing then by some value before normalize() won't do anything, cause dividing/multiplying normals mean scaling of vector, and .normalize() will scale it back to unit vector. – viache Jan 31 '16 at 13:21
0

Some things to try:

(1) Weight your normals. add_normal(normal.normalized()*weight), where weight can be a lot of things, like the area of the triangle, or the inner angle

(2) Compute a normal from your field. You are getting a surface where f(x,y,z)=0. Evaluate to f(x-eps,y,z)-f(x+eps,y,z) to get your normal x, same for y,z.

(3) Just blur it. For every vertex add in all adjacent normals by edge, and average.

I think you want (2). Especially for terrain.

starmole
  • 4,974
  • 1
  • 28
  • 48