Ralith / hypermine

A hyperbolic voxel game
Apache License 2.0
160 stars 20 forks source link

Surface extraction can produce extra surfaces with a risk of z-fighting #330

Closed patowen closed 5 months ago

patowen commented 10 months ago

If a voxel in the chunk's margin is solid but is next to a void voxel in the chunk's interior, the surface extraction logic will produce a surface on a face of the chunk that can be viewed from the inside. This is redundant with the adjacent chunk, causing the same voxel face to be rendered twice, which results in overdraw and could result in z-fighting (for instance, if the textures are oriented differently).

For potential surfaces that span a margin voxel and an interior voxel, the surface should only be rendered ~if the interior voxel is solid and the margin voxel is void~ if the margin voxel is solid and the interior voxel is void, not vice versa. (See comment thread below on why this edit was made)

Fixing this would also slightly reduce the worst-case number of surfaces when the dimension is even to 3*d^3 (but still 3*(d^3+d^2) when odd). For simplicity of reasoning, though, it may not be worth taking advantage of this.

This issue won't be apparent until #41 is resolved,

patowen commented 6 months ago

I'm actually somewhat curious about this issue. Just after filing #379, I'm wondering if I got it backwards. As in, perhaps the surface should only be rendered if the margin voxel is solid and the interior voxel is void, not vice versa.

My reasoning here is that, if everything goes well, it might take less work to get accurate ambient occlusion. With the original scheme, edge and corner margins both affect ambient occlusion, but since 20 chunks can meet at a single corner, corner margins can be very difficult to maintain, especially efficiently. However, with this reversal, I believe (but have not confirmed) that corner margins would no longer play any role at all, and we would only have to worry about the somewhat-tricky edge margins.

This would have an effect on texture orientation, which might be confusing to the player. For instance, filling an entire chunk with a single material and then carving into that chunk might seem like the texture orientation should be consistent throughout rather than different on the outer boundary, although I don't know whether that matters at all.

EDIT: If we do decide to do this backwards to make ambient occlusion easier, we'll need to remember that side-margins need to have the correct material (and not just be correctly void or non-void like edge margins can be) because these margins would actually be rendered.

EDIT2: I realize that this is a bit tricky to visualize, so I drew the 2D equivalent: image

As for the key of what the picture signifies:

Note that in the "current" approach, one of the ambient occlusion voxels is at a corner margin of the chunk, but in the "proposed" approach, none of them are.

I think the answer is going to be that we should stick with the "current" approach for now until we implement edge margins, in which case we can swap to the "proposed" approach to see how it looks. After all, it's really easy to swap between the two approaches.

Ralith commented 6 months ago

perhaps the surface should only be rendered if the margin voxel is solid and the interior voxel is void, not vice versa.

Makes sense to me! I wouldn't stress making AO perfect, since it's just an expedient hack, but this seems like a free improvement.

This would have an effect on texture orientation, which might be confusing to the player.

Meh, so long as there's a solid surface I don't really care. The whole surface extraction paradigm is subject to change, we shouldn't micro-optimize the aesthetics of the status quo too hard.

we'll need to remember that side-margins need to have the correct material (and not just be correctly void or non-void like edge margins can be)

Aren't we achieving that anyway?

patowen commented 6 months ago

Makes sense to me! I wouldn't stress making AO perfect, since it's just an expedient hack, but this seems like a free improvement.

Meh, so long as there's a solid surface I don't really care. The whole surface extraction paradigm is subject to change, we shouldn't micro-optimize the aesthetics of the status quo too hard.

Good to know that you're on board with this idea! I'll go ahead an apply it my current branch since it seems more likely than not to be our final state.

Aren't we achieving that anyway?

Oh yeah, we are. That was almost a note-to-self, because I has considered other designs before, such as always using dirt or void, just to make it easier to be consistent with edge margins, for example. This certainly isn't a downside to this approach.

patowen commented 6 months ago

It does look like this has immediate benefits as well, mainly because, although edge margins are still needed, they're needed in fewer places.

Before: image

After: image

EDIT: Something odd seems to have happened to these pictures, where the borders of the picture look funny. That isn't present in the actual game, and I likely just make a mistake somewhere when cropping the screenshot, or there was a bug in some software I was using.