11

It looks like it would be easy to add a texture to a material using Python, but no matter what i do i cant figure it out!

I can create a texture using:

bpy.data.textures.new("NewTexture", type='IMAGE')

and I can create a new material texture slot:

bpy.context.object.active_material.texture_slots.add()

However i can't link the texture to the Material Slot Texture. I have tried looking through the python API but nothing is working. I would be eternal grateful if someone could point me in the right direction.

p2or
  • 15,860
  • 10
  • 83
  • 143
Ryan Grzesiak
  • 243
  • 1
  • 2
  • 10
  • What render engine are you using? Internal? – p2or Mar 10 '16 at 13:04
  • I was using the blender internal to automatically find the basecolor, roughness, and normal channels to quickly create a game ready material so i could see how the models look before i bring them into the game engine. – Ryan Grzesiak Mar 12 '16 at 01:04

2 Answers2

12

Similar to material_slot.material, there is a texture_slot.texture

(I'm assuming Blender internal from the texture_slots.add in q)

mat = bpy.data.materials['Material']
tex = bpy.data.textures.new("SomeName", 'IMAGE')
slot = mat.texture_slots.add()
slot.texture = tex

A simple example using Cycles can be found here https://blender.stackexchange.com/a/14115/15543

batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • 1
    You are awesome! That was exactly what i was looking for and it worked. Thanks for the link to the Cycles as well – Ryan Grzesiak Mar 11 '16 at 04:31
  • 2
    That doesn't work in 2.8. There is not material.texture_slots anymore. There is now both material.texture_paint_images and material.texture_paint_slots, but both don't have an add() method. No idea so far how the 2.8 equivalent should look like. – bluenote10 Oct 10 '19 at 08:56
  • 5
    I have found this question which covers that. – bluenote10 Oct 10 '19 at 10:40
  • @bluenote10 Thank you so much! I was stuck here. PS THE ABOVE ANSWER IS WRONG FOR BLENDER 2.8. – Bob Denny May 01 '20 at 00:07
  • ... surprising that an answer from 2016 aimed at blender internal render engine doesn't work in 2.8. Thanks for the heads up. – batFINGER May 01 '20 at 04:13
1

The following solution works for Blender 3.0

import bpy
import bmesh

mat = bpy.context.active_object.material_slots[0].material

imgpath = '/image path' img = bpy.data.images.load(imgpath)

mat.use_nodes=True

#setup the node_tree and links as you would manually on shader Editor #to define an image texture for a material

material_output = mat.node_tree.nodes.get('Material Output') principled_BSDF = mat.node_tree.nodes.get('Principled BSDF')

tex_node = mat.node_tree.nodes.new('ShaderNodeTexImage') tex_node.image = img

mat.node_tree.links.new(tex_node.outputs[0], principled_BSDF.inputs[0])

#grab mesh data for the active mesh. bpy.ops.object.mode_set(mode="EDIT") mesh = bpy.context.active_object.data bm = bmesh.from_edit_mesh(bpy.context.object.data) bm.faces.ensure_lookup_table() bpy.ops.uv.unwrap() uv_layer = bm.loops.layers.uv.active

#assign the uv values for the vertices of each face. This example #assumes the default cube for i in range(6):

loop_data = bm.faces[i].loops
uv_data = loop_data[0][uv_layer].uv
uv_data.x = 1.0
uv_data.y = 0.0

uv_data = loop_data[1][uv_layer].uv
uv_data.x = 1.0
uv_data.y = 1.0

uv_data = loop_data[2][uv_layer].uv
uv_data.x = 0.0
uv_data.y = 1.0

uv_data = loop_data[3][uv_layer].uv
uv_data.x = 0.0
uv_data.y = 0.0

bpy.ops.object.mode_set(mode="OBJECT")

Kirbinator
  • 2,661
  • 1
  • 16
  • 24
user89301
  • 41
  • 1
  • 4