Page MenuHome

Cycles Noise, Voronoi Edge Along Surface Normal
Needs RevisionPublic

Authored by Charlie Jolly (charlie) on Sep 3 2018, 5:53 PM.

Details

Reviewers
Brecht Van Lommel (brecht)
Group Reviewers
Cycles
Summary

Patch to implement edge along surface normal.

Based entirely on the following post on devtalk:

https://devtalk.blender.org/t/voronoi-distance-to-edge-along-surface-normal/2018

Implemented as additional node output.

Note: GLSL code is not complete for any of the new features in Voronoi texture and this hasn't been touched.

Diff Detail

Repository
rB Blender

Event Timeline

Brecht Van Lommel (brecht) requested changes to this revision.Sep 3 2018, 8:34 PM

The GLSL function should at least be updated to get the edge parameter, otherwise there will be an error.

I get some banding in OSL, I think that would be fixed by using N instead of calculatenormal(P).


Even with SVM there are quite odd discontinuities. I guess render in the devtalk thread use some thresholding to bring out a clear edge.

I wonder if there's a way to make it look a bit nicer..

intern/cycles/kernel/shaders/node_voronoi_texture.osl
182

Trailing space.

intern/cycles/kernel/svm/svm_voronoi.h
23

Is division by zero really impossible, or should we check?

28

Use * 0.5f for maybe slightly better performance.

33

Can't use & in kernel, only C pointers.

Also should only be computed if there is something connected to the Edge output, so might be easiest to move this code out of voronoi_neighbors to svm_node_tex_voronoi.

This revision now requires changes to proceed.Sep 3 2018, 8:34 PM

The example code on devtalk provides the same banding issues so to achieve the same look as the original example on devtalk does require running it through a colorramp or similar.

Maybe it would be better to implement the edge output as an additional feature instead e.g. Crackle Edge?

Also, seems that calculatenormal(p) is quite different to using sd->N in SVM. Is there anything equivalent in Cycles SVM?

Good find, that algorithm seems better.

Maybe it would be better to implement the edge output as an additional feature instead e.g. Crackle Edge?

Yes, I think that would be better.

Also, seems that calculatenormal(p) is quite different to using sd->N in SVM. Is there anything equivalent in Cycles SVM?

You could take the cross product of dPdx and dPdy, I think that's what it ends up doing in OSL. But then the normal is no smooth and you get facetting. The algorithm you linked may not even require a normal so maybe it doesn't matter.

The new algorithm is 2D so it will have the same issues that the original algorithm was trying to solve. I'll spend some more time experimenting!

Tests using OSL.

It seems the original algorithm from devtalk is better for 3D coordinates.

Hornwitser algorithm (devtalk) [white] > Hornwitser (with minor adjustments) [yellow] > Quilez algorithm [orange]

The Hornwitser algorithm using calculatenormal(p) [yellow] and when using N [red].

This is not quite what I remembered it to be, so I guess I should say a few things about the algorithm.

The discontinuities near the center of the voxels, shown below, is caused by an aggressive optimization I did. Rather than calculating the plane distance to all 26 neighbors (which was too slow) I made it take the shortest distance to the 3 closest neighbors according to the normal distance metric. This doesn't work near the center, but for what I wanted it worked fine. This optimization should probably be taken out. Unfortunately this probably means having to repeat the nested for loop, as the cell the point is inside needs to be known in order to calculate the distance to a given edge, and any one of the 26 other cells may have the edge closest to it.

The thing about calculatenormal(P) is that in order to calculate the distance along the surface, the normal provided has to be with respect to the coordinate system P is in. P defaults to the generated texture coordinates which doesn't change with rotations but N does, which means the calculations get all wacky as soon as the object is rotated if N is used instead of calculatenormal(P). If you know a way to get the normals of the surface before any transforms/deforms were applied that would be a possible way to solve the banding issue. Either way a socket needs to be provided to override the calculated normal, otherwise it may not be possible to get the right result when overriding the position input.

Finally I've been thinking that getting the distance along the normal to the points (F1,F2,etc) might be useful as well. And likewise with getting the distance to the edge with the other distance metrics. Which makes me think calculating the distance along normal should be a distance metric and distance to edge should be a feature output.

PS: is it possible to change my username to hornwitser?

In this case, perhaps @Brecht Van Lommel (brecht) can provide more detail about the normal calculations and if an equivalent is available from Cycles.

@Julian Siversen (sivert3), is it worth living with the discontinuities if the most important outcome is the edge?