6

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?

J. Sena
  • 81
  • 4

2 Answers2

1

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.

sambler
  • 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
0

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

christsdude
  • 225
  • 2
  • 9