I've created a certain number of book cover textures (with their respective roughness maps) but I really don't want to create a material for every book and then assign their respective textures manually. I'm talking of hundreds of books. There's a way to do this automatically?
-
There is a commercial Cycles Node Setup that allows setup random textures on the same material, if that is what you are looking for. If plugged in by the same order diffuse/ should be kept in sync. (Disclaimer: Shameless publicity, I made that product) – Duarte Farrajota Ramos Mar 25 '17 at 23:53
-
Not ideal solution but it should do the trick. Thank you! – J. Sena Mar 26 '17 at 00:06
-
1Same free node group is included here for years, also there is an answer over here explaining the principle, so honestly I think 10 bucks isn't really worth it... Can you list some advantages against the other ones? @DuarteFarrajotaRamos – brockmann Mar 27 '17 at 09:00
-
No advantage, it is basically the same thing pre-packaged if you wish to save the trouble. – Duarte Farrajota Ramos Mar 27 '17 at 12:55
2 Answers
Working with you having some structure setup with your naming, let's say you have an object called "book1" and you have images "book1_diffuse.png" and "book1_roughness.png" you can create a material called "book1" that uses both images and then assign the material to the object.
import bpy
from glob import glob
import os
# adjust this to point to your texture directory
# can start with // to refer to the current blend file dir
texture_dir = '//textures'
os.chdir(bpy.path.abspath(texture_dir))
diffuse_imgs = glob('*_diffuse.png')
for img in diffuse_imgs:
mat_name = img.split('_')[0]
mat = bpy.data.materials.new(mat_name)
mat.use_nodes = True
m_nodes = mat.node_tree.nodes
m_links = mat.node_tree.links
diff_node = m_nodes['Diffuse BSDF']
imgnode = m_nodes.new('ShaderNodeTexImage')
imgnode.location.x = diff_node.location.x - 200
imgnode.location.y = diff_node.location.y
bpy.ops.image.open(filepath=img)
imgnode.image = bpy.data.images[img]
m_links.new( diff_node.inputs['Color'], imgnode.outputs['Color'] )
roughnode = m_nodes.new('ShaderNodeTexImage')
roughnode.location.x = imgnode.location.x - 200
roughnode.location.y = imgnode.location.y - 50
roughimg = mat_name+'_roughness.png'
bpy.ops.image.open(filepath=roughimg)
roughnode.image = bpy.data.images[roughimg]
m_links.new( diff_node.inputs['Roughness'], roughnode.outputs['Color'] )
uvnode = m_nodes.new('ShaderNodeUVMap')
uvnode.location.x = roughnode.location.x - 200
uvnode.location.y = roughnode.location.y - 100
uvnode.uv_map = 'UVMap'
m_links.new(imgnode.inputs['Vector'], uvnode.outputs['UV'])
m_links.new(roughnode.inputs['Vector'], uvnode.outputs['UV'])
bpy.data.objects[mat_name].active_material = mat
You can easily expand that to include any number of image textures for each material and add in a mix and glossy node if you wanted. You can find the node types you can use listed here.
If you have a random number of book objects, you could create the materials and add them to a list as you go, then go through the list of objects and pick a random material to assign to each.
- 55,387
- 3
- 59
- 192
-
I'm new to Blender and don't know much about Python but I searched how to run a python script and it didn't worked for me. Tried to load in the text editor and run but nothing happens. – J. Sena Mar 27 '17 at 00:10
-
Most likely the
diffuse_imgs =line will need to be adjusted, as it is it will find the images in the current directory. I just added an adjustment to the first few lines to make that easier. – sambler Mar 27 '17 at 07:20 -
Still not working. Tried a few times and got this error everytime:
Error: Cannot read 'Cube_diffuse.png': no such file or directory Traceback (most recent call last): File "D:\TEMP\untitled.blend\test.py.001", line 22, in <module> File "C:\Program Files\Blender Foundation\Blender\2.78\scripts\modules\bpy\ops.py", line 189, in _call_ ret = op_call(self.idname_py(), None, kw) RuntimeError: Error: Cannot read 'Cube_diffuse.png': No such file or directory.Don't know why it's trying to read Cube_diffuse.png since I don't have a "Cube" in my scene.
– J. Sena Mar 29 '17 at 17:10
One way is to (within one material) have a shader for each book variation, with the textures plugged into them accordingly, and mix the shaders together using the "Random" output from the "Object Info" node (found in the "input" node category) as the factor. This "random" output simply selects all the objects with the material in question and randomly assigns some of them as white and some of them as black.
Of course, this will require one Mix Shader node for pretty much every variation of the book, so it's still not neat, clean, and simple, but it will be more effective than assigning a separate material to each book :P
- 225
- 2
- 9