Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for smooth shading #27

Open
Eldemarkki opened this issue May 15, 2020 · 10 comments
Open

Allow for smooth shading #27

Eldemarkki opened this issue May 15, 2020 · 10 comments

Comments

@Eldemarkki
Copy link
Owner

No description provided.

@jpdoiron
Copy link

I guess it means welding vertices to allow continuous surface without gap and smooth normal ?

@jpdoiron
Copy link

marching

Maybe an image explain best what I had in mind, when I displace the mesh using the normal direction

@Eldemarkki
Copy link
Owner Author

Yep, exactly.

I haven't thought too much about this yet, but one problem I know there will be are the chunks' borders where the vertices can not be welded, but other than that I don't see any problems with it.

@jpdoiron
Copy link

We might have some cool stuff if I can figure this out, so I'll have a look .. even tho I haven't done burst.. good opportunity to learn.

@ghost
Copy link

ghost commented May 31, 2020

This is an awesome project, thanks for working on it!

Smooth shading could be accomplished by calculating normals for each vertex by taking a gradient of the density field, and that might actually be done in parallel. I think this would work without having to knit the triangles.

Also, this appears to calculate vertex positions regardless of whether or not that vertex has already been found in an adjacent voxel, and I've been struggling with the same problem, especially in a parallel context. There are papers that describe only calculating verts on edges 0, 3, and 8 (the edges with one point at corner 0 of a voxel) and assuming the other verts get found when doing adjacent cubes, but I can't figure out how to keep the triangles and vertices tables synced up, let alone calculate verts asynchronously.
(this solution requires a density field 1 voxel bigger in every direction than the mesh)

Below refs talk about using an auxiliary structure to keep track of already-found verts, but the only ideas I've come up with seem really unwieldy, like a LUT that translates a voxel edge ID to a chunk-unique edge ID, or a table that translates from the current voxel's edge to the equivalent edge 0, 3, or 8 on an adjacent cube.

https://developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-1-generating-complex-procedural-terrains-using-gpu
https://www.google.com/url?sa=t&source=web&rct=j&url=http://jcgt.org/published/0008/03/01/paper.pdf&ved=2ahUKEwjes7vB8t7pAhXjoFsKHTa9AewQFjAIegQIChAB&usg=AOvVaw1wF8QIXQ8M6lOW1cKNiU8J

@Eldemarkki
Copy link
Owner Author

That sounds like a perfect solution for smooth shading! It would even solve the problem on chunk edges, which I thought would be really difficult. Thanks for sharing those resources, I'll try it out tomorrow!

@ghost
Copy link

ghost commented Jun 2, 2020

Here's another source for the gradient-normal idea with a c++ example: http://www.angelfire.com/linux/myp/MCAdvanced/MCImproved.html

The way I'm imagining it is:

  1. Compute a normalized gradient at each end point of the vertex's edge by sampling each end point's neighbors and store the result.
  2. When calculating a vertex's normal vector, interpolate each component of the gradient vector between the vertex's edge's two end points in the same way as vertex position.

The DOTS implementation is still beyond me, but it might save time to pre-compute the gradient for each density point and store it in an array in the same manner as the density values (after the densities are updated but before the normals are calculated - can be in parallel with vertex position calculation). That way, finding a vertex normal would just require the three lerps and a normalize. Since vertices are duplicated in up to 5 triangles, this might give significant savings over doing the whole process for each vert.

You rock for working on this! I'm learning a ton from what you've done so far.

@Eldemarkki
Copy link
Owner Author

Eldemarkki commented Jun 5, 2020

Hey, I tried to calculate the gradients and it kind of worked. Integrating it with the Job system was however kind of a mess (a huge mess to be honest...) so I decided to scrap it. There were also some problems with modifying the terrain because the gradients weren't coming from the signed distance function, but that could maybe be solved by interpolating between the density points.

I will some time in the future for sure come back to this, as I think smooth shading is something that this should definitely support!

@msimbao
Copy link

msimbao commented Jul 31, 2020

Hi!

TL:DR I found something for smooth shading that might help:
The link is here
Screen Shot 2020-07-31 at 12 28 33 AM

I wanted to just say your work is awesome and open source projects like your's are so inspirational.

This might be a bit of a long post but just because i had been searching for a way to smooth the terrain for 2 months so am excited to share a bit of the journey. I'm a complete newbie at coding so these might not work for more advanced users but for my simple uses worked well.

the first method you could try that gave some results is re-writing the method for calculating meta ball normals. It gives a weird effect where each chunk will have different colors because the normal calculation is isolated unless you weld your chunk meshes in advance. My normal calculations weren't right BUT with some quick math I instead isolate one chunk and get it to behave for a decent meta ball effect but, the shadows might still not behave. Below is the general effect without isolating a single chunk
The link is here
Screen Shot 2020-07-31 at 12 24 16 AM

After that, i spent a month trying different algorithms and methods (none of them worked lol) but eventually found the good normal solving script found here. The image is at the start of this post:
The link is here

It does a lot of the heavy lifting of finding adjacent vertices and averaging your normals for vertices that are close together and gives a great result like the meta ball one but you can actually have good shadows without the chunks looking different. This is in line with the Paul Bourke paper. Looks better with spherical density.
Screen Shot 2020-07-31 at 12 50 44 AM

A last a quick note was about scaling. I remember you once answered a user on youtube who asked about scaling and you said there were some problems with scaling. One work around i found for my usage was the method used by AR foundation (that is copyable or editable with some code). For AR foundation, instead of scaling the object, their function MakeObjectAppearAt uses a combination of child and parent offsetting to keep the child the same size but dynamically move the camera and camera parent in a way as to create the illusion of scaling. This works extremely well because the marching cubes terrain resolution can be made higher (so appear a bit more smooth) without having to increase chunk size or world size (if you don't want to) and without sacrificing performance since this implementation happens on the CPU.
The link is here

Combining the last two methods allowed me to be able to get a smooth clay like modeling material for an XR sculpting app i'm making for android that lets you sculpt with hand tracking.
Thank you again so much for your kindness in letting the community see your code and i know your kindness will be repaid many times over in your near future.

Screenshot_20200730-045909

@Eldemarkki
Copy link
Owner Author

Hey, that looks quite good! I'm not sure if that's faster than welding the vertices, but that would have to be profiled. Still, I really appreciate your search efforts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature
Development

No branches or pull requests

3 participants