Backface Culling of procedural generated terrain

Started by
7 comments, last by fido9dido 2 years, 10 months ago

I am generating a terrain with Perlin noise, the terrain is generated procedurally. right now I cannot render all the outer faces of terrain, some triangles are displayed from inside the terrain. As you might have known, it's winding order problem. so How to render the outer face of triangles without disabling culling??

In another word, if I did clock wise order, some triangles will be rendered and others will disappear, for instance let's imagine a cube it has front and back faces, one of them need to be ordered in clock-wise winding order the other face will be counter clock-wise in order to render the outer or inner faces of the cube. How to determine whether I should use the clockwise or counter clock wise of the current triangle.

Note: the terrain may have caves or bridges

Advertisement

fido9dido said:
Note: the terrain may have caves or bridges

That implies this is some sort of voxel terrain? How are you actually generating the final mesh?

It's pretty common to end up with winding errors in marching cubes (or related voxel algorithm) implementations - but it also tends to be pretty easy to fix.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

fido9dido said:
How to determine whether I should use the clockwise or counter clock wise of the current triangle.

Adjacent triangles have inconsistent order as well in your case, so you can't rely on them. (Maybe if errors are really rare)
So the only option is to do it right already when generating iso surface by using information of solid / empty space, which is available at this point.

Personally i don't know marching cubes, but i use ‘Minecraft mesh’ made from density volume. Then i use density gradients to project the vertices to the iso surface. Was pretty easy to do and i had no winding order issues with that approach.

Are we talking manifold geometry here? In most cases game geometry is manifold (more or less). That's even more true for terrain. If it's manifold, just make everything clockwise as seen from the outside. Don't worry about the culling, the hardware will do the right thing if you have your winding right.

If your question is how to do that, you need to provide more information on how you generate terrain. for instance if you are going to have procedurally generated caves you might use something like marching cubes, native surface nets or dual contouring.

@swiftcoder it's voxel terrain yes, it's Dual Contouring (DC)

@joej

information of solid / empty space,

can you elaborate please what do you mean by that? I tried to google it and I didn't get any result

@gnollrunner as joej put it better than myself, the adjacent triangles have inconsistent order, so I am looking for a way to determine the correct winding order per triangle, and the order matter in DirectX

how the terrain is created is this,

1- Perlin noise to generate density

2- look for sign change and per sign change generate 4 adjacent vertices(vertex buffer) (DC always guarantee a face )

3- iterate over created vertices and create create index buffer (triangle list) to render the triangles

to calculate normal of generated vertex I normalize the result of this formula

N(x,y,z) =
F(x+dx,y,z)-F(x-dx,y,z)/2*dx
F(x,y+dy,z)-F(x,y-dy,z)/2*dy
F(x,y,z+dz)-F(x,y,z-dz)/2*dz


where F is improved perlin noise and dx=1/countofColumns , etc


In Nvidia's marching cube they negate the result but I don't know why anway

assuming terrain is solid and air. I am thinking of generating Normals that always point to in the direction of Air then check the direction of the normal then decide winding order. I generated the normals but I dont know where they are pointing

so I dont know how to make sure the generated normal will always be pointing to air (outside),

@gnollrunner as joej put it better than myself, the adjacent triangles have inconsistent order, so I am looking for a way to determine the correct winding order per triangle, and the order matter in DirectX

I'm doing marching prisms but the idea is still the same. What I did to help me visualize it, is make a binder with drawings of the possible combinations. You will notice the information you need is there contained in the voxels. When you are generating faces around an edge crossing, if you are looking at it from the “out” vertex side you just go in a clockwise direction. You shouldn't ignore the voxel information when building an index buffer and then try to fix it later. I'm not sure if it's even possible to fix it without the voxel data. Since you are not doing height mapped terrain you can't make assumptions about which way a face should be pointing.

fido9dido said:
can you elaborate please what do you mean by that? I tried to google it and I didn't get any result

For me that's easy: I have density volume, cells with density <0.5 are empty, others are solid.
Then i generate quads at each face between solid/empty cells, so it's clear where's in/outside for every face.

But IDK how this is with marching cubes. Likely you use LUTs from some common reference, lacking in depth understanding how the algorithm works, so it's hard to ensure winding order is right for each special case.

fido9dido said:
assuming terrain is solid and air. I am thinking of generating Normals that always point to in the direction of Air then check the direction of the normal then decide winding order. I generated the normals but I dont know where they are pointing so I dont know how to make sure the generated normal will always be pointing to air (outside),

What you could try: Calculate the gradient from the density field for each vertex as you already do; calculate triangle normal; invert winding order if dot(vertexGradient, triNorm) is less than zero for more than 1 vertices of the 3.

But likely some false positives remain. If you have edge adjacency information, you could then compare resulting winding order with the 3 adjacent triangles per triangle, and invert again if more than 1 neighbors disagree.

Might be good enough, but still not 100% robust i guess.

It's uncertainties like this (mainly about guaranteeing manifold) why i made my own iso extraction algorithm. Seemed easier to reinvent than to understand existing algorithms precisely.

@joej @gnollrunner

Thanks guys for help, both of you have given me the idea on how to do it,

first of all, sorry, The biggest issue is I am new to these kind of algorithms and I am not familiar with a lot of terminologies used, for instance if Hermite data as I understand it, is collection of data used to generate terrain, similar to data cache then I added one more data which is the Air direction, or information of solid / empty space.

I already know what is solid thus but I didn't use this information before

1- when creating the terrain vertices at edges with sign change, I stored the direction of air as boolean (AT this stage the terrain is cubic)

2- when creating the vertex gradient I forced it to be in air direction from step 1, because the way gradient is calculated in my previous post, results with many but not all adjacent Normals to have an opposite directions. This way I forced all normals to point to the air direction no matter where they are(before this stage the terrain was already smooth)

3- when I create index buffer I used the direction of gradient from step2(direction of normal is known by the sign value so no need to calc vector direction) to decide the winding order

This way I avoided any additional math computations and so far it works smoothly

This topic is closed to new replies.

Advertisement