Page MenuHome

Shading: Extend Noise node to other dimensions.

Authored by Omar Emara (OmarSquircleArt) on Aug 22 2019, 8:42 PM.



This patch extends perlin noise to operate in 1D, 2D, 3D, and 4D
space. An AVX implementation of the noise will follow.

Previously, a constant offset of 13.5 was added to the noise to act as a seed for generating distortion textures. Additionally, swizzling was performed to act as a seed for the Color outputs. This cased some issues, in particular, swizzling meant zero components may result in identical noise outputs and a constant value of 13.5 meant that distortion may happen only at close to zero areas.
To solve this, we use random offset functions that generates offsets at compile time, you can see this in details in the code. This change meant that the pattern of distortion will change and won't be identical to the previous version of the node.

Diff Detail

rB Blender

Event Timeline

  • Bump subversion and add versioning code.
Omar Emara (OmarSquircleArt) retitled this revision from Shading: Extend Noise node to other dimenstions. to Shading: Extend Noise node to other dimensions..Aug 22 2019, 9:24 PM
Omar Emara (OmarSquircleArt) edited the summary of this revision. (Show Details)
  • Revert socket renamming.
  • Use more consistent names.

Are you able to test how this affects Cycles CUDA or OpenCL rendering performance?

Increasing the kernel size like this often affects performance in all scenes, even without those using the specific node. And then we need to do some tweaking to avoid it. I can run some benchmarks, but it would help if you could do it, even if only the simple bmw27 benchmark for example.

@Brecht Van Lommel (brecht) I can't test CUDA as I don't have an Nvidea GPU.

I do have an RX 590, however, OpenCl compilation hits the assert assert(kernel->second == NULL); in OpenCLDevice::OpenCLProgram::create_kernels after 25 seconds from starting compilation. So I haven't been able to test OpenCL so far. This also happens in master, so it is not caused by something I did. Is this a driver issue? Should I try to remove the assert and render?

The render times for the BMW benchmark are as follows:

BranchTiming 1Timing 2Timing 3Average

So this patch is, on average, 1.29s faster.

The benchmarks used cached kernels, so those results don't include the compilation times. The benchmarks were done by executing Blender in background mode in a tty with no xserver.


Are the three noise_turbulence implementations here exactly the same?
Either deduplicate or write a comment for why the code is duplicated three times.

Also why is turbulence in the name of these functions? Isn't this normal perlin noise?


Is this supposed to be in this patch?


standard (typo)


same comment as above


Can this have a better name? Or at least a description for what it is doing?

I also tested the patch. Did not find any issues, but obviously there are limits to how well I can test this manually.


The only difference between them is the input vector type. For SVM, the noise function call is also different as we don't have overloading. This is what I showed in this section. I can add a comment about this, pretty sure I had one, not sure why I removed it.

I don't know why it is called turbulence. I am guessing because the original developer wanted to differentiate "perlin noise" from "multi-octave perlin noise". I never liked the name turbulence anyway, I can change it to something else. Perhaps octave_noise or something.


This function was originally in node_texture.h, but it was only used by the voronoi function, so I moved it here and renamed node_texture.h to node_noise.h because the file only contains noise functions. This will be removed anyway in the voronoi patch.


What do you suggest? The function creates an ssef by streaming the "low" part of an ssef. So for instance:

low(ssef(0, 1, 2, 3)) -> ssef(0, 1, 0, 1)

Isn't this often called fractal_{noise-type}? Whereby fractal means that you add multiple layers of noise.
At least the FastNoise library we used in AN calls it that way afaik.


Is there a benefit of using this function over a shuffle?
If yes, then you could also implement this as an specialization of shuffle (maybe the compiler replaces that anyway).


fractal looks good to me. I can rename it to that. Should it be fractal_perlin?


Look at the shuffle<2, 3, 2, 3> and shuffle<0, 1, 0, 1> functions above. Those are already implemented as specialized shuffle functions. However, I found that the code is more readable when we have an explicit function like low and high. Look at my comments in ssef bi_mix function above.


Since perlin noise is apparently called just noise everywhere, it is probably best to just call it fractal_noise.


Based on it does not actually seem like these specialized instructions are actually faster then the generic shuffle. Not sure why they exist.

Personally, I don't like the names low and high because they could mean many different things. The shuffle template makes what you are doing more explicit.


Ok, will update the patch.

  • Correct typo.
  • Use "shuffle" function instead of "high" function.
  • Rename noise_turbulance to fractal_noise.
Omar Emara (OmarSquircleArt) marked 8 inline comments as done.Aug 26 2019, 7:21 PM

Would probably be good to have a comment indicating this before every duplicated function. Otherwise it is easy to not see this when working on one of the functions.

The comment could be /* The fractal_noise_Xd functions are all exactly the same except for the input type. */.

Otherwise "the following functions" could become a bit unspecific when more functions get added.

  • Merge master and update patch.
Omar Emara (OmarSquircleArt) marked an inline comment as done.Sep 2 2019, 2:39 PM

I didn't find measurable performance regressions with this for CUDA and CPU rendering with my benchmarks.

This does break backwards compatibility for color noise and distortion, but I can't see a good way to avoid that without making a mess, so I think that's acceptable.

This revision is now accepted and ready to land.Sep 4 2019, 4:39 PM