I am trying to apply a texture to a model programmatically via script. Via GUI, it's easy enough to do (Blender 2.8):

  • Import model (obj file)
  • In model properties go to texture properties
  • Change "Base color option" to "Image texture"
  • "Open", then load dds file for the image texture

For writing the script, this is as far as I went:

import bpy

obj_path = '/my_path_to_files/mytest.obj'
tex_path = '/my_path_to_files/mytest.dds'

# import model and texture
bpy.ops.import_scene.obj(filepath=obj_path)#, axis_forward='-Y', axis_up='Z')
# get reference to model and texture
myobj = bpy.data.objects['mytest']
mytex = bpy.data.images['mytest.dds']

# try to set the texture (doesn't work)
myobj_material_nodes = myobj.active_material.node_tree.nodes
node_texture = myobj_material_nodes.new(type='ShaderNodeTexImage')
node_texture.image = mytex

I don't know which properties I have to set to get this working. Or if I am in the right path at all. The properties set when doing via GUI are:

bl_height_default: 100.0
bl_height_max: 30.0
bl_height_min: 30.0
bl_icon: NONE
bl_idname: ShaderNodeTexImage
bl_label: Image Texture
bl_rna: <bpy_struct, Struct("ShaderNodeTexImage")>
bl_static_type: TEX_IMAGE
bl_width_default: 240.0
bl_width_max: 700.0
bl_width_min: 140.0
color: <Color (r=0.6080, g=0.6080, b=0.6080)>
color_mapping: <bpy_struct, ColorMapping at 0x7f752ae3e298>
dimensions: <Vector (0.0000, 0.0000)>
draw_buttons: <bpy_func ShaderNodeTexImage.draw_buttons()>
draw_buttons_ext: <bpy_func ShaderNodeTexImage.draw_buttons_ext()>
extension: REPEAT
height: 100.0
hide: False
image: <bpy_struct, Image("mytest.dds")>
image_user: <bpy_struct, ImageUser at 0x7f752ae3e5c8>
input_template: <bpy_func ShaderNodeTexImage.input_template()>
inputs: <bpy_collection[1], NodeInputs>
internal_links: <bpy_collection[0], ShaderNodeTexImage.internal_links>
interpolation: Linear
is_registered_node_type: <bpy_func ShaderNodeTexImage.is_registered_node_type()>
location: <Vector (-280.0000, 280.0000)>
mute: False
name: Image Texture
output_template: <bpy_func ShaderNodeTexImage.output_template()>
outputs: <bpy_collection[2], NodeOutputs>
parent: None
poll: <bpy_func ShaderNodeTexImage.poll()>
poll_instance: <bpy_func ShaderNodeTexImage.poll_instance()>
projection: FLAT
projection_blend: 0.0
rna_type: <bpy_struct, Struct("ShaderNodeTexImage")>
select: True
show_options: True
show_preview: False
show_texture: True
socket_value_update: <bpy_func ShaderNodeTexImage.socket_value_update()>
texture_mapping: <bpy_struct, TexMapping at 0x7f752ae3e208>
update: <bpy_func ShaderNodeTexImage.update()>
use_custom_color: False
width: 240.0
width_hidden: 42.0

My question is, what would be a good, clean way of doing this?


1 Answer 1


What it was missing is a link between the shader and the texture. We can do it as follows:

myobj_material_links = myobj.active_material.node_tree.links
my_obj_shader = myobj_material_nodes.get('Principled BSDF')
myobj_material_links.new(my_obj_shader.inputs["Base Color"], node_texture.outputs["Color"])

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .