Page MenuHome

Shading: Noise and Wave nodes. Uniform texture distortion instead of diagonal shift.

Authored by Bartosz Moniewski (monio) on Nov 3 2019, 3:02 AM.
"Love" token, awarded by Shimoon."Love" token, awarded by charlie."Love" token, awarded by gadas."Like" token, awarded by klutz."Love" token, awarded by pablovazquez."Love" token, awarded by alterdings."Love" token, awarded by Draise."Like" token, awarded by amonpaike."Love" token, awarded by bunny."Love" token, awarded by astrand130."Like" token, awarded by SINED."Love" token, awarded by symstract."Love" token, awarded by valera."Love" token, awarded by snewpo."Love" token, awarded by RC12."Love" token, awarded by aidyburrows3d."Love" token, awarded by mfink."Like" token, awarded by gottfried."Love" token, awarded by mistajuliax."Love" token, awarded by andreasus."Like" token, awarded by MetinSeven."Love" token, awarded by OmarSquircleArt."Like" token, awarded by EAW."Love" token, awarded by wuzzle."Love" token, awarded by Linkun."Love" token, awarded by dbystedt."Like" token, awarded by Schamph."Love" token, awarded by zanqdo."Love" token, awarded by fin.eskimo."Love" token, awarded by CGKrisu.



Currently Noise and Wave texture nodes use noise functions within [0,1] range for distortion effect. We either add or subtract noise from coordinates, never do both at same time. This leads to texture drastically shifting on diagonal axis of a plane / cube. This behavior makes Distortion input hard to control or animate. Capabilities of driving it with other texture are also limited, diagonal shifting is very apparent.

This can be easily fixed by offsetting noise function to signed range and make it zero-centered. This way noise is uniformly added and subtracted from coordinates. Texture pattern sticks to main coordinates which makes it way easier to control.

Diagonal shifting can be "artistic decision" but I believe that users would want uniform distortion in vast majority of cases. After my changes diagonal shifting could be easily achieved by adding another noise node to coordinates.
This patch will change appearance of textures in some corner cases when input was driven by another texture with high amplitude and/or frequency (last example in video).

Patch notes:
Before we used noise() for distortion effect. This patch change it to snoise() which is zero-centered but also has twice the range. To maintain same distortion amount I added versioning code that halve distortion value, directly in node or by adding multiply node for used sockets.

Diff Detail

rB Blender

Event Timeline

Bartosz Moniewski (monio) created this object with visibility "Bartosz Moniewski (monio)".

I think this is a great improvement. Just one comment.


You shouldn't handle backward compatibility in the code itself. The 0.5 is called a magic number in this case, because it doesn't make sense outside of the context of backward compatibility.

Alternatively, half the distortion input of the node in the versioning code, either by adding a divide node if the input is connected or by dividing the value directly if it isn't.

Increment BLENDER_SUBVERSION in BKE_blender_version.h, add a versioning function in versioning_cycles.c, and call it in the do_versions_after_linking_cycles function. See the existing code for reference.

Nice video presenation!

For Noise node I replaced noise() with snoise(). For compatibility reasons I halved distortion factor to compensate bigger range of noise function.

Wave texture use fractal noise function so it was easier to just offset it.

Don't think you can preserve 100% compatibility with just this, so is it really needed?

After my changes diagonal shifting could be easily achieved by adding another noise node to coordinates.

Do you think we can have some versioning code to minimize the difference?
Thing is, noise textures are used a lot for all sort of procedural textures, would be quite annoying to change look of all of them.

Bartosz Moniewski (monio) updated this revision to Diff 19800.EditedNov 23 2019, 9:04 PM
Bartosz Moniewski (monio) edited the summary of this revision. (Show Details)
  • Noise node: Removed magic number multiplier.
  • Wave Node: Changed ambiguous -0.5 offset to common unsigned-signed remapping.

Booth nodes use signed noise now. This means distortion amount is doubled but I think it's still way easier to use compared to old behavior.

  • Added versioning.

I added versioning code that recreates old distortion behavior with nodes. Node logic is based on code so results are identical. All those Nebula shaders will look the same.
I'm creating lots of nodes so I made utility functions for inserting math and noise nodes, also for placing nodes relatively to updated node.

Updated version of Wave texture doesn't actually need Wave texture node, but I'm leaving it there for users who might search for Wave nodes and update their materials to new behavior. Removing it entirely would be confusing imho.

Unfortunately those added nodes introduce a bit of overhead in Cycles. Rendering Noise with them it's ~4.5% slower (3D variant). Eevee performance is identical. We should mention this in release notes and provide instructions to people who want to update to new behavior.

Versioning test file:

Cycles side changes looks good to me now.

But didn't realize preserving compatibility will come with such code complexity and render time penalty.

Makes me wonder, what's the least of evil here. Wouldn't mind hearing from @Brecht Van Lommel (brecht) or @Dalai Felinto (dfelinto).

Bartosz Moniewski (monio) planned changes to this revision.EditedNov 26 2019, 11:59 AM
Bartosz Moniewski (monio) marked an inline comment as done.

During performance regression tests I've found that I need to support internal texture mapping in versioning code. Will update patch soon.

I'm not sure strictly preserving backwards compatibility here is required. While ideally everything renders exactly the same, I think this is a bit beyond what is needed. If there is somewhat we can do to get it significantly closer in a couple lines of code we can do it, otherwise I would not bother with the code complexity that will be extra work to maintain through refactorings and maybe introduce bugs.

Bartosz Moniewski (monio) edited the summary of this revision. (Show Details)
  • Removed versioning code for recreating old effect
  • Added versioning code for halving distortion amount

If there is somewhat we can do to get it significantly closer in a couple lines of code we can do it

With those algorithms we can either recreate them in 100% (with massive node setups) or accept change in noise pattern distribution.
Recreating them was fun but I'm glad you choose second solution.

Both old and new distortion effects appears very similar if distortion is a constant value set in node. Which is pretty much always because users almost never plug anything to distortion socket. I believe this is caused by very issue I've explained above and try to fix with this patch.

This revision is now accepted and ready to land.Dec 6 2019, 12:16 AM