3

I'm using cycles and have a texture that I want to animate by changing the hue so that it cycles through the rainbow. I know how to make keyframes of nodes, however I'm not sure how to make it seamless when the hue slider operates on a 0-1 scale. Would it just be a matter of changing the animation curves??

Toadhands
  • 63
  • 6

1 Answers1

5

You can use a Maths node set to 'Modulo' to convert an input value into a repeating range; the output will vary between 0 and the value set on the second input. For example, with the following nodes :

hue continuous

Varying the 'Value' will produce Hue that varies between 0 and 1, then restarts back at 0. This will produce a continuous repeating range of hues as Value increases from 0 upwards (simply keyframe Value from 0 to, say, 5 to result in 5 repetitions of the range of hues : 0.0->1.0, 0.0->1.0, 0.0->1.0, 0.0->1.0, 0.0->1.0).


As @RobinBetts pointed out, using the Modulo function can cause strange effects then using negative values as the Blender 'Modulo' function (as is the same for many programming languages) flips the output for negative input values. To correct this we can add a couple of additional Maths nodes :

For example, here's the usual output from the Modulo function :

modulo

Notice how the output flips in the centre as it crosses zero.

Adding Maths nodes to Add the Value, followed by a second Modulo corrects for this - by effectively shifting all values that are less than zero back to being positive :

modulo - fixed

Rich Sedman
  • 44,721
  • 2
  • 105
  • 222
  • 1
    I was trying this earlier this evening, and it seems to raise an anomaly, crossing zero. In Python, -0.3 mod 1 == 0.7 mod 1, so you get a sawtooth, continuous down the number line. I doesn't seem to be so with the modulo math node? The results of -.3 and .7 are different? I think in the node, the sawtooth reflects about / rounds towards 0, where Python rounds toward -infinity. .. see here – Robin Betts Nov 12 '18 at 00:14
  • @RobinBetts It seems that this is implementation dependent - so different programming languages can potentially produce different results. The Python result that you mention follows the strict mathematical definition of negative module - ie, it's always positive and follows the same 'pattern' as for the positive side of zero. Some languages (eg, JavaScript, C) produce negative results for negative values - effectively (-x) mod y is equivalent to -(x mod y). – Rich Sedman Nov 12 '18 at 07:07
  • So in order to avoid ..(1,0),(1,0).(1,0),(0,1),(0,1).. @Toadhands has to stay one side of 0, I think... – Robin Betts Nov 12 '18 at 10:20
  • 1
    @RobinBetts Yes - staying to positives would certainly avoid the problem. I presume from the question that won't be a problem since it's just some arbitrary value that's being animated. However, by adding a couple of additional maths nodes you can avoid the problem of negatives - see edit. – Rich Sedman Nov 12 '18 at 17:41
  • 1
    Cunning. I spent quite a time trying to figure out how to fix this in a snappy way...... I thought it probably wouldn't take you long.... Glad I didn't put my clumsy solution up :D... also quite important for procedural textures, etc. – Robin Betts Nov 12 '18 at 18:09
  • Thanks. Yes - very useful when using Object coordinates that can go negative. It’s something that’s caught me out in the past. Until you pointed it out I didn’t realise so many programming languages did it differently. – Rich Sedman Nov 12 '18 at 20:32
  • Rich, I reconstructed your nodes and played with settings. I got 15 different (very interesting) results as posted in Facebook group. I did over 10 more patterns before that. https://www.facebook.com/groups/Blender.Nodes/?multi_permalinks=2714073138633740¬if_id=1559358625505001¬if_t=feedback_reaction_generic – Rita Geraghty Jun 01 '19 at 03:51
  • @Rich, All this time later, I ran into a hitch with your node implementation of positive saw-tooth modulo. Because of the way the native modulo node handles division by zero, 0 mod x is evaluated as -x, outside the [0.0 , x) range. Now floor is available, probably better to use x - (y * floor(x/y)) – Robin Betts Sep 16 '19 at 22:22
  • Hi @RobinBetts - well spotted... that's a really interesting case.... and it actually explains some behaviour I've seen (but not understood) with some of my shaders when using Generated coordinates for some sides of the default cube (since they start at zero). I think your suggestion could work... but I'd be a bit concerned about the divide by 'y' - what happens as it approaches zero...? Could be rounding or precision errors. I think the original Modulo behaviour is definitely a bug since it's inconsistent at x=0 and think it's probably worth reporting. Shall I submit a bug or do you want to? – Rich Sedman Sep 17 '19 at 06:27
  • 1
    @RobinBetts I’ll raise it - it looks quite convincing to me. As an example, consider 0.00001 mod 10, -0.00001 mod 10, 0 mod 10 - all values very close to each other. Using the Node implementation you’ll get results of 0.00001 for the first, -0.00001 for the second and -10 for the third - wildly different but they should actually all be very close. – Rich Sedman Sep 17 '19 at 08:19
  • 1
    I’ve put together an example that visualises it quite convincingly (I’ll update the answer when I get chance). – Rich Sedman Sep 17 '19 at 08:19
  • 1
    My demo, stripped down. Blend file here. – Robin Betts Sep 17 '19 at 10:37
  • 1
    Thanks @RobinBetts. I've raised this as a bug at https://developer.blender.org/T69978, including an image that shows the discrepancy at x=0 quite clearly. – Rich Sedman Sep 17 '19 at 12:05
  • 1
    Excellent description. Yup, following that, it's a bug. – Robin Betts Sep 17 '19 at 14:05
  • @RobinBetts Looks like the issue has already been resolved in Blender 2.81 - so it appears it was a long outstanding bug that's now fixed. – Rich Sedman Sep 18 '19 at 10:59
  • Okydoky, case closed. Apologies for taking us up a dead-end.. but we weren't to know.... – Robin Betts Sep 18 '19 at 12:57
  • @RobinBetts Thanks for pointing it out - and at least it prompted me to install the latest 2.81 :-) Looks like it’s a bug that’s been there for a long time so it’s good it’s resolved now. – Rich Sedman Sep 18 '19 at 13:00