I think the only way is scripting. Here's a small script that will automate it. Put it in the text editor and hit run or install it as an addon. Then go to File > Import > Images as Diffuse
and pick the images you want to import (use Shift and Ctrl to pick multiple files). It will also (optionally) add material slots for the new materials to your selected objects.
If you import the same image multiple times, it will reuse the same material. It does this by reusing the material with the same file name, so make sure your images have unique names.
If you want to change the nodes it creates, you'll have to edit the script yourself.
# Tested with Blender 2.93
bl_info = {
"name": "Import Images as Diffuse",
"blender": (2, 93, 0),
"category": "Import-Export",
"location": "File > Import",
}
import bpy
import os
def do_import(op, context, filepaths):
mats = []
for path in filepaths:
mat = import_material(path)
if mat:
mats.append(mat)
else:
op.report({'WARNING'}, "Couldn't create material: %s" % path)
if op.add_material_slots:
for ob in context.selected_objects:
add_material_slots(ob, mats)
# Add fake users if needed so materials aren't deleted
for mat in mats:
if mat.users == 0:
mat.use_fake_user = True
return {'FINISHED'}
def import_material(path):
name = os.path.basename(path)
if not name: return None
# Use existing material with same name if it exists
mat = bpy.data.materials.get(name)
if mat: return mat
try:
img = bpy.data.images.load(path, check_existing=True)
except Exception as e:
print(e)
return None
mat = bpy.data.materials.new(name)
mat.use_nodes = True
out = mat.node_tree.nodes["Material Output"]
mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"])
dif = mat.node_tree.nodes.new("ShaderNodeBsdfDiffuse")
dif.location = (60, 300)
dif.inputs["Roughness"].default_value = 1.0
tex = mat.node_tree.nodes.new("ShaderNodeTexImage")
tex.location = (-260, 300)
tex.interpolation = 'Closest'
tex.image = img
mat.node_tree.links.new(out.inputs[0], dif.outputs[0])
mat.node_tree.links.new(dif.inputs["Color"], tex.outputs["Color"])
return mat
def add_material_slots(ob, mats):
if not hasattr(ob.data, "materials"): return
for mat in mats:
if mat.name not in ob.material_slots:
ob.data.materials.append(mat)
from bpy_extras.io_utils import ImportHelper
from bpy.props import BoolProperty, CollectionProperty
from bpy.types import Operator
class ImportImagesAsDiffuse(Operator, ImportHelper):
"""Create diffuse materials for images"""
bl_idname = "import_image.to_diffuse"
bl_label = "Import Images As Diffuse"
files: CollectionProperty(
name="File Path",
type=bpy.types.OperatorFileListElement,
)
add_material_slots: BoolProperty(
name="Add Material Slots",
description="Add material slots for imported images to selected objects",
default=True,
)
def execute(self, context):
if self.files:
dirname = os.path.dirname(self.filepath)
files = [os.path.join(dirname, file.name) for file in self.files]
else:
files = [self.filepath]
return do_import(self, context, files)
def menu_func_import(self, context):
self.layout.operator(
ImportImagesAsDiffuse.bl_idname, text="Images As Diffuse", icon='MATERIAL')
def register():
bpy.utils.register_class(ImportImagesAsDiffuse)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_class(ImportImagesAsDiffuse)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
if __name__ == "__main__":
register()