1
$\begingroup$

enter image description here

Above is the material I've created. I exported my model to .obj from Blender. From a Python script (I have Blender compiled as a Python Module), I import my .obj file. I then attempt to set the Noise Texture 'W' property:

import bpy

bpy.ops.import_scene.obj( filepath = PATH_TO_MY_OBJ)
bpy.context.object.name = "obbb"
obj = bpy.data.objects["obbb"]

My material is called Material. How can I access the Noise Texture node and change the value of W?

As suggested, here is the Blend file:

$\endgroup$
12
  • $\begingroup$ @brockmann nope: AttributeError: 'NoneType' object has no attribute 'node_tree' $\endgroup$
    – pookie
    Oct 10 '21 at 14:48
  • $\begingroup$ @pookie make sure you selected an object and in Material Properties tab you selected a non-empty material slot. $\endgroup$ Oct 10 '21 at 14:52
  • $\begingroup$ @MarkusvonBroady There is no Materials Properties tab -- as I mentioned, I am doing this all from Python; Blender is not open/running. $\endgroup$
    – pookie
    Oct 10 '21 at 14:53
  • 2
    $\begingroup$ @pookie you're using bpy.context.object to access your object. So how about print(bpy.context.object.material_slots[:]) - does it display an empty list []? If not, how about print(bpy.context.object.material_slots[0].material.node_tree) - does it display something without an error? If so, how about print(bpy.context.object.material_slots[0].material.node_tree.get("Noise Texture"))? $\endgroup$ Oct 10 '21 at 14:59
  • 1
    $\begingroup$ Then there's something wrong with how you embedded blender into your application. What is the actual error you get when it fails? $\endgroup$ Oct 10 '21 at 16:33
5
$\begingroup$

Above is the material I've created. I exported my model to .obj from Blender. From a Python script (I have Blender compiled as a Python Module), I import my .obj file. I then attempt to set the Noise Texture 'W' property:

When you rountrip through OBJ you will not get the original node graph back. OBJ only supports a few simple material properties, not stuff like noise textures. Import your .obj into Blender and check the shader graph. You will see that all those nodes you added are lost. That's why there isn't a noise texture.

See Import & Export of Node Shaders in the manual for more info about what is supported when exporting to OBJ.


Here is how you can append (as in File > Append) the CloudCube from your proceedural_clouds.blend file into the current file and change its W.

import bpy

# First, append the CloudCube from your .blend into the current file.
blendpath = "//proceedural_clouds.blend"
with bpy.data.libraries.load(blendpath, link=False) as (data_src, data_dst):
    data_dst.objects = ["CloudCube"]
cloud_cube = data_dst.objects[0]

# Link cloud cube into scene so it shows up
bpy.context.scene.collection.objects.link(cloud_cube)

# Grab the material it uses
mat = cloud_cube.material_slots[0].material

# Change W
mat.node_tree.nodes["Noise Texture"].inputs["W"].default_value = 42.0
$\endgroup$
3
  • $\begingroup$ I have a few items in my scene already. Will opening the .blend file delete them? Also, could you give me an example of how I would load the blend file and set the Noise Texture W property? $\endgroup$
    – pookie
    Oct 10 '21 at 16:53
  • $\begingroup$ "Will opening the .blend file delete them?" Yes it would. You can append the data you need instead. See edit. $\endgroup$
    – scurest
    Oct 10 '21 at 17:19
  • $\begingroup$ Thank you! And nice touch with the reference to Hitch Hikers Guide to the Galaxy. $\endgroup$
    – pookie
    Oct 10 '21 at 18:21
1
$\begingroup$

EDIT The real reason is that the object file was being imported as OBJ, which doesn't support Blender materials, especially not noise.

The solution is to either read the Blender file or to reconstruct the material in Python before trying the solution below.

Your approach was close:

from random import randrange
import bpy
import time


for i in range(0,50):
    n = randrange(10)
    bpy.data.materials["Material"].node_tree.nodes["Noise Texture"].inputs[1].default_value = n

but you need to change the last line slightly:

bpy.data.materials["CloudMaterial"].node_tree.nodes["Noise Texture"].inputs['W'].default_value = n

The index for materials should be the actual name of the material and using ['W'] rather than [1] makes the code work even if the developers change the order of input sockets in the future.

$\endgroup$
7
  • $\begingroup$ This will error with KeyError: 'bpy_prop_collection[key]: key "Noise Texture" not found'. I'm not running my script from within Blender; I'm running Blender as a Python module. My Python app calls bpy, loads the obj file and now I am trying to edit the W property of the Noise Texture shader node. $\endgroup$
    – pookie
    Oct 10 '21 at 16:38
  • $\begingroup$ So the problem is probably that the shader being loaded from the obj file is not the shader in the blend file. $\endgroup$ Oct 10 '21 at 16:42
  • $\begingroup$ hmm, any idea how to fix that? $\endgroup$
    – pookie
    Oct 10 '21 at 16:45
  • $\begingroup$ Wavefront obj's mtl files don't support materials that translate to Noise textures. The best I can suggest is to reconstruct the material in Python so it ends up with the node tree you want. $\endgroup$ Oct 10 '21 at 16:51
  • $\begingroup$ Ha, OK, thanks -- No idea how I will do that :D $\endgroup$
    – pookie
    Oct 10 '21 at 16:52
1
$\begingroup$

You wrote "I have Blender compiled as a Python Module". Do you realize that you can run blender in background against a script (no UI).

For example I set up a python script.py as

import bpy
bpy.data.materials['CloudMaterial'].node_tree.nodes['Noise Texture'].inputs[1].default_value=2.33
bpy.ops.wm.save_mainfile()

and used the command line:

blender -b proceedural_clouds.blend -P script.py

And the V value was changed.

$\endgroup$
1
  • $\begingroup$ Yes, I am aware of that, thanks. $\endgroup$
    – pookie
    Oct 10 '21 at 22:16
0
$\begingroup$

Hover over the W property and right-click (RMB context) menu Copy Full Data Path:

enter image description here

Then you can paste it into your python script, e.g.,:

bpy.data.materials["Material.001"].node_tree.nodes["Noise Texture"].inputs[1].default_value

and just add = 0.2 or whatever

$\endgroup$
2
  • $\begingroup$ No, it will not work. It does not find any Noise Texture, for some reason. $\endgroup$
    – pookie
    Oct 10 '21 at 16:28
  • $\begingroup$ @pookie -- do you own "Copy Full Data Path" as I show above, as the name of your Noise Texture node might not be "Noise Texture"! It might be "Noise Texture.001", for example. $\endgroup$
    – james_t
    Oct 10 '21 at 16:54

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