5
$\begingroup$

I'd like to randomise any value. Here's an example: I'd like to randomise emission strength of a material every frame change between 0-15.

$\endgroup$
1
  • $\begingroup$ How about creating/editing a Driver for that animated field. While hovering over the field with your mouse: RMB: Create Driver. The expression would look something like noise.random()*NNN if( (Scene.frame_current > 0) and (Scene.frame_current <=15)) else 0 replacing NNN with some multiplier. $\endgroup$
    – james_t
    Nov 13 '21 at 18:23
6
$\begingroup$

Since comments are temporary, I decided to steal James_t idea as my answer:

You can click on the emission strength in Principled BSDF node, and type/paste there:

#noise.random()*4 if((frame > 0) and (frame <= 15)) else 0

The # tells Blender to not evaluate it once, but rather to create a driver and evaluate the expression on every frame. Once the field becomes purple, it means it's driven, and subsequent edits of the formula should omit the hash character, or the formula will become invalid.

The 4 is arbitrary and changes the output range from $[0;1)$ [source] to $[0;4)$.

I decided to leave the original formula by James, as some might find it more readable, but there are more concise ways of writing it in Python:

#noise.random()*4 if 0 < frame <= 15 else 0

and even

#noise.random()*4 *(0 < frame <= 15)

In order to get the same amount of control as with Map Range node, replace noise.random()*x with minimum + noise.random()*(maximum-minimum), for example, if you would put 3 as To Min and 10 as To Max, the formula would be 3+noise.random()*(10-3), which can be shortened to 3+noise.random()*7

Once you type/paste the formula and press Enter, you will get a warning message:

Clicking on Allow Execution will not make it work. Opening the console through menu Window > Toggle System Console will reveal an error:

        BPY_driver_eval() - restricted access disallows name 'random', enable auto-execution to support

Error in Driver: The following Python expression failed:
        'noise.random()*4 *(0 < frame <= 15)'

You need to go to menu Edit > Preferences... Save & Load, and enable Auto Run Python Scripts.

⚠ WARNING! Enabling this option introduces a severe security vulnerability. Every time you download some .blend file from the Internet, there's a risk it contains a virus in Python form. From now on this virus will be able to run. This is why it's strongly recommended to exclude the folders, from which you run .blend files from unverified sources, from automatic execution!

Finally, you can click on the purple field, just to press Enter again and now it will work.

This solution is not deterministic; Rendering the animation twice will end up with two different animations, because by default the random value is based on current system time (which changes between renders). In order to deal with this, you have to change the formula to something like this:

[noise.seed_set(floor(frame)), noise.random()*4 *(0 < frame <= 15)][1]

This ensures the value changes between frames, but the same frame rendered multiple times will output the same value each time. However, using this formula for multiple objects will end up with the same value for each object! If you want to combat that, you need:

[noise.seed_set(floor(frame+519752137)), noise.random()*4 *(0 < frame <= 15)][1]

where 519752137 is just some random number you change for each formula.

The length of this answer proves Nathan's point:

Certainly, drivers are a way to do this, but I tend to think of drivers as less accessible than solutions that rely more on nodes

$\endgroup$
2
  • 1
    $\begingroup$ Wow: so thorough! And I never thought about the security implications of enabling Python scripts before. $\endgroup$
    – james_t
    Nov 14 '21 at 17:21
  • $\begingroup$ Pretty smart setting the seed to prevent random-randomization :) Although as you mentioned this may be taking the driver system a bit too far for its own sake >< $\endgroup$
    – Gorgious
    Nov 15 '21 at 7:26
6
$\begingroup$

To randomize a material value, you can use a noise node (white noise or noise depending on your needs; scale of the noise node, again, depending on your needs. Your choices affect the distribution of the random value.)

To get the current frame count, you can use a value node with a value driven from the current frame. Blender provides a simple interface for this: you just type "#frame" in the value field.

To remap the value that a noise texture outputs (which exists between 0 and 1 by default) you can use a map range node. Below, I'm remapping from 0,1 to 0,15.

enter image description here

Randomizing non-material values is sometimes possible, sometimes not, and uses different methods; if curious about randomizing some specific non-material value, it'd be best to ask about that specifically. Since you gave the example of emission here, I demonstrated randomization of material values only.

$\endgroup$
6
  • $\begingroup$ To fully satisfy the question, place a Map Range node between the White Noise and Emission nodes. Set From Min and Max to 0 and 1, and To Min and Max to the range min and max. 0 to 15 in the example in the question. $\endgroup$ Nov 13 '21 at 17:20
  • $\begingroup$ @MartyFouts Ahh, I thought they were asking about randomizing for frame 0 to frame 15. Your interpretation makes more sense. $\endgroup$
    – Nathan
    Nov 13 '21 at 17:31
  • $\begingroup$ rereading the question just now i think it could have been either. oh well, you've got both covered in your answer. $\endgroup$ Nov 13 '21 at 18:15
  • 1
    $\begingroup$ @MartyFouts and @Nathan -- how about simply adding a Driver to the Emission Strength field like noise.random()*NNN if( (Scene.frame_current > 0) and (Scene.frame_current <=15)) else 0, replacing NNN with some multiplier. ? $\endgroup$
    – james_t
    Nov 13 '21 at 18:24
  • 1
    $\begingroup$ @james_t personally, I didn't explicitly limit to 15 frames, because OP didn't say what they wanted otherwise (and it's ambiguous anyways.) You can limit by frames with nodes, just mixRGB or math or whatever on the basis of (frame>-1)*(frame<16). Certainly, drivers are a way to do this, but I tend to think of drivers as less accessible than solutions that rely more on nodes (more intuitive for people, I believe.) $\endgroup$
    – Nathan
    Nov 13 '21 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.