Is there any alternative ddx ddy for calculating normals when use DistanceToNearSurface?

Sure thing. It’s definitely the most flexible, and probably the cheapest since it avoids all trig functions, although I didn’t profile to compare so that’s just speculation.

The normals will be slightly less accurate since with a trig function you have infinite resolution and mathematically accurate normals can be solved exactly.
This texture method is technically a very close approximation due to having finite resolution. You’ll notice the normal changes depending on the offset amount. Just like before, you can sanity check it by comparing to DDX cross DDY to find the closest physically accurate value.
In practice that doesn’t really matter much, especially considering how convenient and powerful it is.

2 Likes

Just to confirm, for my own validation, the path you first posted, with the ArcTans and whatnot, is ‘perfect’ and valid, just expensive; there isn’t technically ‘wasted effort’ in the maths?

The 2nd path is just-faster, but subject to the finite-resolution you mentioned?

The first technique with ArcTan generates a map of rotational values, and then uses those rotational values to alter a known normal. It should be accurate, but unnecessary, as the results are the same as optimized version that doesn’t use a rotation map but still uses math. The optimized version leverages the fact that we know that all the normals must point either towards the surface (that the DF detects) or away from the surface, thus we really only need to figure out the B component, and can make assumptions about the R&G.

The math formulas solve for the normal at the specific, instantaneous point on the wave, which is ran per pixel and therefor the normal is always accurate at infinite resolution. It achieves this by taking advantage of the fact that the derivative of a curve equals its tangent, and the derivative of Sine is Cosine. When you can solve the exact tangent, you can solve the exact normal. This method should work for any mathematically defined curve too, such as Bezier curves. Although the formula is different, because the derivative is different. This is how normals were generated for the Bezier curve driven grass in Ghost of Tsushima.

The texture curve method gets an approximate rate of change over an offset range, and therefore is not an instantaneous point, but rather compares two points of the two samplers. Because the rate of change across two nearby points of the curve will be approximately the same as the instantaneous rate of change at the center of those two points, the tangent can be estimated this way. And again, the normal can be determined as result. Since the samples have a predefined resolution, so do the points that you can calculate. This is how the “normal from heightmap” function works, but we can simplify it, because we only need to solve the normal in 1D again, as we can use the same directionality assumption as in the mathematical case whereas the built in function operates in 2D and needs more samples as a result.

Since trig functions are expensive, I believe the texture curve method would likely be faster - although it does need to sample the curves which is not free. Even if it’s not cheaper, the ability to draw any waveform you want is very appealing to me.

2 Likes

Agreed. And thanks for the clarification.

1 Like