Skip to content

Instantly share code, notes, and snippets.

@eviltrout
Last active August 1, 2023 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eviltrout/09cd1a450ead954aca8b389d94960ab6 to your computer and use it in GitHub Desktop.
Save eviltrout/09cd1a450ead954aca8b389d94960ab6 to your computer and use it in GitHub Desktop.
Godot Import Script to automatically find and create materials
# A Godot Post Import script to automatically build or find materials for things.
# From this video: https://www.youtube.com/watch?v=v23xZHJdtLE
# Not meant as a drop in for your project - you will likely have to modify it to get it to work.
# MIT License.
@tool
extends EditorScenePostImport
func _post_import(scene):
var root = scene
_process_meshes(root, scene)
return scene
func _process_meshes(root, node):
if node == null:
return
if node is MeshInstance3D:
_process_mesh_materials(node)
for child in node.get_children():
_process_meshes(root, child)
func _process_mesh_materials(mesh: MeshInstance3D):
var mat = mesh.get_active_material(0)
if mat is StandardMaterial3D:
# If there's an existing material, keep it
if mat.resource_path:
return
if mat.resource_name:
var res := _find_material_by_name("res://materials", mat.resource_name)
if res:
mesh.set_surface_override_material(0, res)
return
_process_standard_material(mesh.name, mat)
func _find_tex(texture_base: String, mesh_name: String, id: String, suffix: String) -> Resource:
var mesh_asset_name = texture_base + mesh_name + suffix
if FileAccess.file_exists(mesh_asset_name):
return load(mesh_asset_name)
var model_asset_name = texture_base + id + suffix
if FileAccess.file_exists(model_asset_name):
return load(model_asset_name)
return null
func _find_material_by_name(path: String, resource_name: String) -> Resource:
var dir = DirAccess.open(path)
if dir:
dir.list_dir_begin()
var file_name := dir.get_next()
while file_name != "":
var full_path := str(path, '/', file_name)
if file_name.get_basename() == resource_name:
return load(full_path)
elif dir.current_is_dir():
var res := _find_material_by_name(full_path, resource_name)
if res:
return res
file_name = dir.get_next()
return null
func _process_standard_material(mesh_name: String, material: StandardMaterial3D):
if mesh_name.ends_with("-novertcol"):
material.vertex_color_use_as_albedo = false
# We always backface cull
material.cull_mode = BaseMaterial3D.CullMode.CULL_BACK
var src_file := get_source_file()
var path := src_file.get_base_dir().replace("res://meshes/", "")
var basepath = src_file.get_basename().replace("res://meshes/", "")
var id = src_file.get_file().get_basename()
var ext = src_file.get_extension()
if ext == "glb":
var texture_base: String = "res://textures/" + path + "/"
var albedo_tex = _find_tex(texture_base, mesh_name, id, "-albedo.png")
if albedo_tex:
material.albedo_texture = albedo_tex
var normal_tex = _find_tex(texture_base, mesh_name, id, "-normal.png")
if normal_tex:
material.normal_enabled = true
material.normal_texture = normal_tex
#
var orm_texture = _find_tex(texture_base, mesh_name, id, "-orm.png")
if orm_texture:
material.ao_enabled = true
# material.ao_light_affect = 1.0
material.ao_texture = orm_texture
material.ao_texture_channel = BaseMaterial3D.TEXTURE_CHANNEL_RED
material.roughness_texture = orm_texture
material.roughness_texture_channel = BaseMaterial3D.TEXTURE_CHANNEL_GREEN
material.metallic = 1
material.metallic_texture = orm_texture
material.metallic_texture_channel = BaseMaterial3D.TEXTURE_CHANNEL_BLUE
var emit_texture = _find_tex(texture_base, mesh_name, id, "-emit.png")
if emit_texture:
material.emission_enabled = true
material.emission_texture = emit_texture
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment