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?


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"])
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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