[CG Pipeline] Refactor
This commit is contained in:
parent
6538f70d54
commit
b3612d8655
23 changed files with 634 additions and 645 deletions
|
@ -18,43 +18,94 @@ __version__ = '0.2'
|
|||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
import bpy
|
||||
import addon_utils
|
||||
import BakeWrangler
|
||||
from BakeWrangler.nodes.node_tree import BW_TREE_VERSION
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# COLLECTIONS NAMIG CONVENTION
|
||||
parts_col_name = 'Parts'
|
||||
lcs_col_name = 'LCS'
|
||||
hierarchy_col_name = 'Hierarchy'
|
||||
lowpoly_col_name = 'Lowpoly'
|
||||
# LCS POINT'S SUFFIXES CONVENTION
|
||||
inlet = '_in'
|
||||
outlet = '_out'
|
||||
root = '_root'
|
||||
# CG ASSETS SUFFIXES CONVENTION
|
||||
hightpoly = '_hp'
|
||||
midpoly = 'mp'
|
||||
lowpoly = '_lp'
|
||||
render = '_render'
|
||||
bw_config_1 = {
|
||||
'passes': {
|
||||
'diffuse': {
|
||||
'bake_cat': 'PBR',
|
||||
'bake_subcat': 'ALBEDO',
|
||||
'suffix': 'D',
|
||||
},
|
||||
'nornal': {
|
||||
'bake_cat': 'CORE',
|
||||
'bake_subcat': 'NORMAL',
|
||||
'suffix': 'N',
|
||||
},
|
||||
'ao': {
|
||||
'bake_cat': 'CORE',
|
||||
'bake_subcat': 'AO',
|
||||
'bake_samples': 16,
|
||||
'suffix': 'AO',
|
||||
},
|
||||
'roughness': {
|
||||
'bake_cat': 'CORE',
|
||||
'bake_subcat': 'ROUGHNESS',
|
||||
'suffix': 'R',
|
||||
},
|
||||
'metallic': {
|
||||
'bake_cat': 'PBR',
|
||||
'bake_subcat': 'METALLIC',
|
||||
'suffix': 'M',
|
||||
},
|
||||
'uv': {
|
||||
'bake_cat': 'WRANG',
|
||||
'bake_subcat': 'ISLANDID',
|
||||
'suffix': 'UV',
|
||||
},
|
||||
},
|
||||
'margin': 8,
|
||||
'ray_dist': 0.001,
|
||||
'bake_samples': 4,
|
||||
}
|
||||
|
||||
bw_config_10 = {
|
||||
'passes': {
|
||||
'nornal': {
|
||||
'bake_cat': 'CORE',
|
||||
'bake_subcat': 'NORMAL',
|
||||
'suffix': 'N',
|
||||
},
|
||||
'ao': {
|
||||
'bake_cat': 'CORE',
|
||||
'bake_subcat': 'AO',
|
||||
'bake_samples': 16,
|
||||
'suffix': 'AO',
|
||||
},
|
||||
},
|
||||
'margin': 8,
|
||||
'ray_dist': 0.01,
|
||||
'bake_samples': 4,
|
||||
}
|
||||
|
||||
configs = {'bake_1': bw_config_1, 'bake_10': bw_config_10}
|
||||
|
||||
|
||||
def bw_submit(lowpoly_obj_names, resolution=4096, tree_name='robossembler', area=None):
|
||||
def bw_submit(lowpoly_obj_names,
|
||||
bw_config,
|
||||
resolution,
|
||||
bake_path=None,
|
||||
area=None,
|
||||
**cg_config):
|
||||
''' Submit session and bake textures with BakeWrangler addon. '''
|
||||
BakeWrangler.register()
|
||||
|
||||
asm_name = os.path.basename(bpy.context.blend_data.filepath).split('.')[0]
|
||||
asm_path = os.path.dirname(bpy.context.blend_data.filepath)
|
||||
textures_path = os.path.join(asm_path,'textures').replace('\\', '/')
|
||||
bake_path = os.path.join(textures_path,'bake')
|
||||
bake_path_double = os.path.join(textures_path,'bake_double')
|
||||
os.makedirs(bake_path, exist_ok=True)
|
||||
if not bake_path:
|
||||
asm_path = os.path.dirname(bpy.context.blend_data.filepath)
|
||||
textures_path = os.path.join(asm_path, 'textures').replace('\\', '/')
|
||||
bake_path = os.path.join(textures_path, 'bake').replace('\\', '/')
|
||||
if os.path.exists(bake_path):
|
||||
shutil.rmtree(bake_path)
|
||||
os.makedirs(bake_path, exist_ok=True)
|
||||
|
||||
# create node tree
|
||||
tree = bpy.data.node_groups.new(name=tree_name, type='BakeWrangler_Tree')
|
||||
baking_tree_name = ''.join([item[0] for item in bw_config['passes'].keys()])
|
||||
tree = bpy.data.node_groups.new(name=baking_tree_name, type='BakeWrangler_Tree')
|
||||
|
||||
# for default used Compositing Node Editor area
|
||||
if not area:
|
||||
|
@ -88,10 +139,10 @@ def bw_submit(lowpoly_obj_names, resolution=4096, tree_name='robossembler', area
|
|||
tree.nodes.new('BakeWrangler_OutputSettings').location = (600, 0)
|
||||
|
||||
tree.nodes['Mesh Settings'].pinned = True
|
||||
tree.nodes['Mesh Settings']['margin'] = 8
|
||||
tree.nodes['Mesh Settings']['ray_dist'] = 0.001
|
||||
tree.nodes['Mesh Settings']['margin'] = bw_config['margin']
|
||||
tree.nodes['Mesh Settings']['ray_dist'] = bw_config['ray_dist']
|
||||
tree.nodes['Sample Settings'].pinned = True
|
||||
tree.nodes['Sample Settings']['bake_samples'] = 4
|
||||
tree.nodes['Sample Settings']['bake_samples'] = bw_config['bake_samples']
|
||||
tree.nodes['Pass Settings'].pinned = True
|
||||
tree.nodes['Pass Settings']['res_bake_x'] = resolution
|
||||
tree.nodes['Pass Settings']['res_bake_y'] = resolution
|
||||
|
@ -105,187 +156,100 @@ def bw_submit(lowpoly_obj_names, resolution=4096, tree_name='robossembler', area
|
|||
# batch bake node
|
||||
node_batch = tree.nodes.new('BakeWrangler_Output_Batch_Bake')
|
||||
node_batch.location = (1000, -500)
|
||||
|
||||
node_batch_double = tree.nodes.new('BakeWrangler_Output_Batch_Bake')
|
||||
node_batch_double.location = (2000, -1500)
|
||||
node_batch.name = 'Batch'
|
||||
|
||||
node_y_pos = 0
|
||||
node_pos = 500
|
||||
pass_socket = 0
|
||||
pass_socket_double = 0
|
||||
for lp_name in lowpoly_obj_names:
|
||||
# run for eatch lowpoly object
|
||||
lp = bpy.data.objects[lp_name]
|
||||
mp = bpy.data.objects['_'.join(lp.name.split('_')[:-1] + [midpoly])]
|
||||
mp = bpy.data.objects[
|
||||
'_'.join(lp.name.split('_')[:-1] + [cg_config['midpoly']])
|
||||
]
|
||||
img_name = '_'.join(lp.name.split('_')[:-1]) + '_'
|
||||
|
||||
node_inputs = tree.nodes.new('BakeWrangler_Bake_Mesh')
|
||||
node_inputs.location = (-700, node_y_pos - 500)
|
||||
node_inputs.location = (-700, node_y_pos - node_pos)
|
||||
|
||||
node_inputs.inputs['Target'].value = lp
|
||||
node_inputs.inputs['Source'].value = mp
|
||||
|
||||
def bw_pass(node_pos, bake_pass, pass_socket):
|
||||
node_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_pass.location = (-200, node_y_pos - node_pos)
|
||||
node_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_img.location = (200, node_y_pos - node_pos)
|
||||
|
||||
tree.links.new(node_pass.outputs['Color'], node_img.inputs['Color'])
|
||||
|
||||
node_pass.bake_cat = bake_pass['bake_cat']
|
||||
if bake_pass.get('bake_cat') == 'CORE':
|
||||
node_pass.bake_core = bake_pass['bake_subcat']
|
||||
elif bake_pass.get('bake_cat') == 'PBR':
|
||||
node_pass.bake_pbr = bake_pass['bake_subcat']
|
||||
elif bake_pass.get('bake_cat') == 'WRANG':
|
||||
node_pass.bake_wrang = bake_pass['bake_subcat']
|
||||
if bake_pass.get('bake_samples'):
|
||||
node_pass.bake_samples = bake_pass['bake_samples']
|
||||
node_img.inputs['Color'].suffix = bake_pass['suffix']
|
||||
node_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_img.inputs['Split Output'].img_name = img_name
|
||||
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_pass.inputs[1])
|
||||
tree.links.new(node_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
|
||||
# bake passes
|
||||
# Diffuse
|
||||
node_d_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_d_pass.location = (-200, node_y_pos - 500)
|
||||
node_d_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_d_img.location = (200, node_y_pos - 500)
|
||||
|
||||
tree.links.new(node_d_pass.outputs['Color'], node_d_img.inputs['Color'])
|
||||
|
||||
node_d_pass.bake_cat = 'PBR'
|
||||
node_d_pass.bake_pbr = 'ALBEDO'
|
||||
node_d_img.inputs['Color'].suffix = 'D'
|
||||
node_d_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_d_img.inputs['Split Output'].img_name = img_name
|
||||
'''
|
||||
## Curvature
|
||||
node_c_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_c_pass.location = (-200, node_y_pos -1000)
|
||||
node_c_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_c_img.location = (200, node_y_pos -1000)
|
||||
|
||||
tree.links.new(node_c_pass.outputs['Color'], node_c_img.inputs['Color'])
|
||||
|
||||
node_c_pass.bake_cat = 'WRANG'
|
||||
node_c_pass.bake_wrang = 'CURVATURE'
|
||||
node_c_img.inputs['Color'].suffix = 'C'
|
||||
node_c_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_c_img.inputs['Split Output'].img_name = img_name
|
||||
'''
|
||||
# Normal
|
||||
node_n_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_n_pass.location = (-200, node_y_pos - 1500)
|
||||
node_n_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_n_img.location = (200, node_y_pos - 1500)
|
||||
|
||||
node_n_img_double = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_n_img_double.location = (200, node_y_pos - 1750)
|
||||
|
||||
tree.links.new(node_n_pass.outputs['Color'], node_n_img.inputs['Color'])
|
||||
tree.links.new(node_n_pass.outputs['Color'], node_n_img_double.inputs['Color'])
|
||||
|
||||
node_n_pass.bake_cat = 'CORE'
|
||||
node_n_pass.bake_core = 'NORMAL'
|
||||
node_n_img.inputs['Color'].suffix = 'N'
|
||||
node_n_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_n_img.inputs['Split Output'].img_name = img_name
|
||||
|
||||
node_n_img_double.inputs['Color'].suffix = 'N'
|
||||
node_n_img_double.inputs['Split Output'].disp_path = bake_path_double
|
||||
node_n_img_double.inputs['Split Output'].img_name = img_name
|
||||
|
||||
# AO
|
||||
node_ao_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_ao_pass.location = (-200, node_y_pos - 2000)
|
||||
node_ao_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_ao_img.location = (200, node_y_pos - 2000)
|
||||
|
||||
node_ao_img_double = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_ao_img_double.location = (200, node_y_pos - 2250)
|
||||
|
||||
tree.links.new(node_ao_pass.outputs['Color'], node_ao_img.inputs['Color'])
|
||||
tree.links.new(node_ao_pass.outputs['Color'], node_ao_img_double.inputs['Color'])
|
||||
|
||||
node_ao_pass.bake_cat = 'CORE'
|
||||
node_ao_pass.bake_core = 'AO'
|
||||
node_ao_pass.bake_samples = 32
|
||||
node_ao_img.inputs['Color'].suffix = 'AO'
|
||||
node_ao_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_ao_img.inputs['Split Output'].img_name = img_name
|
||||
|
||||
node_ao_img_double.inputs['Color'].suffix = 'AO'
|
||||
node_ao_img_double.inputs['Split Output'].disp_path = bake_path_double
|
||||
node_ao_img_double.inputs['Split Output'].img_name = img_name
|
||||
|
||||
# Roughness
|
||||
node_r_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_r_pass.location = (-200, node_y_pos - 2500)
|
||||
node_r_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_r_img.location = (200, node_y_pos - 2500)
|
||||
|
||||
tree.links.new(node_r_pass.outputs['Color'], node_r_img.inputs['Color'])
|
||||
|
||||
node_r_pass.bake_cat = 'CORE'
|
||||
node_r_pass.bake_core = 'ROUGHNESS'
|
||||
node_r_img.inputs['Color'].suffix = 'R'
|
||||
node_r_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_r_img.inputs['Split Output'].img_name = img_name
|
||||
|
||||
# Metallic
|
||||
node_m_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_m_pass.location = (-200, node_y_pos - 3000)
|
||||
node_m_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_m_img.location = (200, node_y_pos - 3000)
|
||||
|
||||
tree.links.new(node_m_pass.outputs['Color'], node_m_img.inputs['Color'])
|
||||
|
||||
node_m_pass.bake_cat = 'PBR'
|
||||
node_m_pass.bake_pbr = 'METALLIC'
|
||||
node_m_img.inputs['Color'].suffix = 'M'
|
||||
node_m_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_m_img.inputs['Split Output'].img_name = img_name
|
||||
|
||||
# UV
|
||||
node_uv_pass = tree.nodes.new('BakeWrangler_Bake_Pass')
|
||||
node_uv_pass.location = (-200, node_y_pos - 3500)
|
||||
node_uv_img = tree.nodes.new('BakeWrangler_Output_Image_Path')
|
||||
node_uv_img.location = (200, node_y_pos - 3500)
|
||||
|
||||
tree.links.new(node_uv_pass.outputs['Color'], node_uv_img.inputs['Color'])
|
||||
|
||||
node_uv_pass.bake_cat = 'WRANG'
|
||||
node_uv_pass.bake_wrang = 'ISLANDID'
|
||||
node_uv_img.inputs['Color'].suffix = 'UV'
|
||||
node_uv_img.inputs['Split Output'].disp_path = bake_path
|
||||
node_uv_img.inputs['Split Output'].img_name = img_name
|
||||
|
||||
# connect meshes to passes
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_d_pass.inputs[1])
|
||||
'''
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_c_pass.inputs[1])
|
||||
'''
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_n_pass.inputs[1])
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_ao_pass.inputs[1])
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_r_pass.inputs[1])
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_m_pass.inputs[1])
|
||||
tree.links.new(node_inputs.outputs['Mesh'], node_uv_pass.inputs[1])
|
||||
|
||||
# batch bake node
|
||||
tree.links.new(node_d_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
'''
|
||||
pass_socket += 1
|
||||
tree.links.new(node_c_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
'''
|
||||
pass_socket += 1
|
||||
tree.links.new(node_n_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
pass_socket += 1
|
||||
tree.links.new(node_ao_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
pass_socket += 1
|
||||
tree.links.new(node_r_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
pass_socket += 1
|
||||
tree.links.new(node_m_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
pass_socket += 1
|
||||
tree.links.new(node_uv_img.outputs['Bake'], node_batch.inputs[pass_socket])
|
||||
pass_socket += 1
|
||||
|
||||
# batch bake node double
|
||||
tree.links.new(node_n_img_double.outputs['Bake'],
|
||||
node_batch_double.inputs[pass_socket_double])
|
||||
pass_socket_double += 1
|
||||
tree.links.new(node_ao_img_double.outputs['Bake'],
|
||||
node_batch_double.inputs[pass_socket_double])
|
||||
pass_socket_double += 1
|
||||
for bake_pass in bw_config['passes'].keys():
|
||||
bw_pass(node_pos, bw_config['passes'][bake_pass], pass_socket)
|
||||
pass_socket += 1
|
||||
node_pos += 500
|
||||
|
||||
reroute1 = tree.nodes.new('NodeReroute')
|
||||
reroute1.location = (-1000, 0)
|
||||
reroute2 = tree.nodes.new('NodeReroute')
|
||||
reroute2.location = (2000, 0)
|
||||
tree.links.new(reroute1.outputs[0], reroute2.inputs[0])
|
||||
node_pos = 500
|
||||
node_y_pos -= 4000
|
||||
|
||||
bpy.ops.bake_wrangler.bake_pass(tree=tree_name, node=node_batch.name, sock=-1)
|
||||
logger.info('Baking first pass is finished!')
|
||||
return tree, pass_socket
|
||||
|
||||
# double pass
|
||||
tree.nodes['Mesh Settings']['ray_dist'] = 0.01
|
||||
|
||||
bpy.ops.bake_wrangler.bake_pass(tree=tree_name, node=node_batch_double.name, sock=-1)
|
||||
logger.info('Baking double pass is finished!')
|
||||
def bw_bake(lowpoly_obj_names, textures_path, resolution, **cg_config):
|
||||
BakeWrangler.register()
|
||||
output_paths = []
|
||||
for config in configs:
|
||||
# 1 pass
|
||||
bake_path = os.path.join(textures_path, config).replace('\\', '/')
|
||||
if os.path.exists(bake_path):
|
||||
shutil.rmtree(bake_path)
|
||||
os.makedirs(bake_path, exist_ok=True)
|
||||
tree_obj, count = bw_submit(
|
||||
lowpoly_obj_names, configs[config], resolution, bake_path, **cg_config)
|
||||
|
||||
return textures_path
|
||||
node_batch = tree_obj.nodes['Batch']
|
||||
|
||||
bpy.ops.bake_wrangler.bake_pass(tree=tree_obj.name, node=node_batch.name, sock=-1)
|
||||
|
||||
logger.info('Baking pipeline is started!')
|
||||
# delay until render will be complete
|
||||
# ______________________________
|
||||
exit_delay = 180
|
||||
start_time = time.time()
|
||||
while bpy.context.window_manager.bw_status == 1:
|
||||
time.sleep(2)
|
||||
if not os.listdir(bake_path):
|
||||
if time.time() > start_time + exit_delay:
|
||||
break
|
||||
if not len(os.listdir(bake_path)) < count:
|
||||
break
|
||||
# ______________________________
|
||||
assert len(os.listdir(bake_path)) == count, (
|
||||
'Warning! Baked only {} of {} textures!'.format(
|
||||
len(os.listdir(bake_path)), count))
|
||||
logger.info('Baking %s textures is finished!', len(os.listdir(bake_path)))
|
||||
|
||||
output_paths.append(bake_path)
|
||||
|
||||
return output_paths
|
||||
|
|
|
@ -21,16 +21,19 @@ import os
|
|||
import bpy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def compose_baked_textures(textures_path, resolution=4096):
|
||||
def compose_baked_textures(textures_path, bake_paths, resolution):
|
||||
''' Mix, edit, and inpaint baked textures to production condition. '''
|
||||
logger.info('Composing textures started!')
|
||||
# cleanup
|
||||
for img in os.listdir(textures_path):
|
||||
if img.startswith('T_'):
|
||||
os.remove(os.path.join(textures_path, img).replace('\\', '/'))
|
||||
|
||||
bake_path = os.path.join(textures_path, 'bake')
|
||||
bake_path_double = os.path.join(textures_path, 'bake_double')
|
||||
bake_path_1, bake_path_10, = bake_paths
|
||||
|
||||
baked_images = sorted(os.listdir(bake_path))
|
||||
baked_images = sorted(os.listdir(bake_path_1))
|
||||
|
||||
bpy.context.scene.render.resolution_x = resolution
|
||||
bpy.context.scene.render.resolution_y = resolution
|
||||
|
@ -40,7 +43,7 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
bpy.context.scene.render.filepath = textures_path
|
||||
bpy.context.scene.render.image_settings.file_format = 'PNG'
|
||||
bpy.context.scene.render.image_settings.color_mode = 'RGB'
|
||||
bpy.context.scene.render.image_settings.compression = 100
|
||||
bpy.context.scene.render.image_settings.compression = 50
|
||||
|
||||
bpy.context.scene.display_settings.display_device = 'sRGB'
|
||||
bpy.context.scene.view_settings.view_transform = 'Standard'
|
||||
|
@ -49,6 +52,8 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
bpy.context.scene.view_settings.gamma = 1
|
||||
bpy.context.scene.view_settings.use_curve_mapping = False
|
||||
|
||||
bpy.context.scene.cycles.use_auto_tile = False
|
||||
|
||||
bpy.context.scene.render.use_compositing = True
|
||||
bpy.context.scene.render.dither_intensity = 2
|
||||
bpy.context.scene.use_nodes = True
|
||||
|
@ -63,7 +68,7 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
# render for eatch uv packs
|
||||
uv_images = [image for image in baked_images if 'UV' in image]
|
||||
for uv_image in uv_images:
|
||||
uv_obj = bpy.data.images.load(os.path.join(bake_path, uv_image))
|
||||
uv_obj = bpy.data.images.load(os.path.join(bake_path_1, uv_image))
|
||||
uv_node = tree.nodes.new(type='CompositorNodeImage')
|
||||
uv_node.image = bpy.data.images[uv_obj.name]
|
||||
uv_node.location = 0, (node_y_pos + 500)
|
||||
|
@ -77,16 +82,19 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
tree.links.new(key_node.outputs['Matte'], de_node.inputs['Mask'])
|
||||
|
||||
slot_name = uv_image.split('_UV')[0]
|
||||
logger.info('Prepare %s image slot!', slot_name)
|
||||
for image in baked_images:
|
||||
if '_UV' in image and image.startswith(slot_name):
|
||||
if '_UV' in image:
|
||||
continue
|
||||
if not image.startswith(slot_name):
|
||||
continue
|
||||
if '_AO' in image:
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path, image))
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path_1, image))
|
||||
image_node = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node.location = -500, (node_y_pos + 200)
|
||||
image_node.image = bpy.data.images[image_obj.name]
|
||||
|
||||
image_obj_double = bpy.data.images.load(os.path.join(bake_path_double, image))
|
||||
image_obj_double = bpy.data.images.load(os.path.join(bake_path_10, image))
|
||||
image_node_double = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node_double.location = -500, (node_y_pos - 200)
|
||||
image_node_double.image = bpy.data.images[image_obj_double.name]
|
||||
|
@ -104,12 +112,12 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
tree.links.new(lighten_node.outputs['Image'], aa_node.inputs['Image'])
|
||||
|
||||
elif '_N' in image:
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path, image))
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path_1, image))
|
||||
image_node = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node.location = -1000, (node_y_pos + 200)
|
||||
image_node.image = bpy.data.images[image_obj.name]
|
||||
|
||||
image_obj_double = bpy.data.images.load(os.path.join(bake_path_double, image))
|
||||
image_obj_double = bpy.data.images.load(os.path.join(bake_path_10, image))
|
||||
image_node_double = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node_double.location = -1000, (node_y_pos - 200)
|
||||
image_node_double.image = bpy.data.images[image_obj_double.name]
|
||||
|
@ -133,7 +141,7 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
tree.links.new(mix_node.outputs['Image'], aa_node.inputs['Image'])
|
||||
|
||||
elif '_R' in image:
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path, image))
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path_1, image))
|
||||
image_node = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node.location = -600, (node_y_pos + 100)
|
||||
image_node.image = bpy.data.images[image_obj.name]
|
||||
|
@ -159,7 +167,7 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
tree.links.new(mix_node.outputs['Image'], aa_node.inputs['Image'])
|
||||
|
||||
else:
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path, image))
|
||||
image_obj = bpy.data.images.load(os.path.join(bake_path_1, image))
|
||||
image_node = tree.nodes.new(type='CompositorNodeImage')
|
||||
image_node.location = 0, node_y_pos
|
||||
image_node.image = bpy.data.images[image_obj.name]
|
||||
|
@ -216,7 +224,7 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
node_y_pos -= 500
|
||||
|
||||
# render
|
||||
bpy.ops.render.render(use_viewport=True)
|
||||
bpy.ops.render.render(animation=False)
|
||||
# remove all nodes after rendering
|
||||
for node in tree.nodes:
|
||||
tree.nodes.remove(node)
|
||||
|
@ -229,8 +237,8 @@ def compose_baked_textures(textures_path, resolution=4096):
|
|||
]
|
||||
for texture in composed_textures:
|
||||
os.rename(
|
||||
os.path.join(textures_path, texture),
|
||||
os.path.join(textures_path, texture.split('000')[0] + '.png')
|
||||
os.path.join(textures_path, texture).replace('\\', '/'),
|
||||
os.path.join(textures_path, texture.rpartition('0001')[0] + '.png').replace('\\', '/')
|
||||
)
|
||||
|
||||
logger.info('Composing %s textures is finished!', len(composed_textures))
|
||||
|
|
|
@ -18,10 +18,10 @@ __version__ = '0.1'
|
|||
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import bpy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def assign_pbr_material(obj_names, textures_path):
|
||||
|
@ -44,41 +44,48 @@ def assign_pbr_material(obj_names, textures_path):
|
|||
continue
|
||||
|
||||
# create Principled BSDF based material
|
||||
bmat = bpy.data.materials.new(name=part_name)
|
||||
bmat = bpy.data.materials.new(name=f'M_{part_name}')
|
||||
bmat.use_nodes = True
|
||||
principled_node = bmat.node_tree.nodes["Principled BSDF"]
|
||||
random_color = (
|
||||
round(random.uniform(0.1, 0.9), 3),
|
||||
round(random.uniform(0.1, 0.9), 3),
|
||||
round(random.uniform(0.1, 0.9), 3),
|
||||
1.0)
|
||||
bmat.diffuse_color = random_color
|
||||
principled_node.inputs['Base Color'].default_value = random_color
|
||||
|
||||
for texture in textures:
|
||||
print(1, 'texture', texture)
|
||||
if not texture.startswith('T_' + part_name):
|
||||
continue
|
||||
print(2, 'texture', texture)
|
||||
if '_ao.' in texture:
|
||||
image_obj = bpy.data.images.load(os.path.join(textures_path, texture))
|
||||
image_obj.colorspace_settings.name = 'Linear'
|
||||
texture_ao = bmat.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
texture_ao.name = texture_ao.label = 'ambient_occlusion'
|
||||
texture_ao.location = -1000, 500
|
||||
texture_ao.image = bpy.data.images[image_obj.name]
|
||||
|
||||
mix_node = bmat.node_tree.nodes.new(type="ShaderNodeMix")
|
||||
mix_node.location = -500, 500
|
||||
#mix_node.data_type = 'RGBA'
|
||||
mix_node.data_type = 'RGBA'
|
||||
mix_node.blend_type = 'MULTIPLY'
|
||||
mix_node.inputs['Factor'].default_value = 0.5
|
||||
|
||||
bmat.node_tree.links.new(texture_ao.outputs['Color'], mix_node.inputs['B'])
|
||||
bmat.node_tree.links.new(mix_node.outputs[0], principled_node.inputs['Base Color'])
|
||||
bmat.node_tree.links.new(texture_ao.outputs['Color'], mix_node.inputs[7])
|
||||
bmat.node_tree.links.new(mix_node.outputs[2], principled_node.inputs['Base Color'])
|
||||
|
||||
|
||||
if '_d.' in texture:
|
||||
image_obj = bpy.data.images.load(os.path.join(textures_path, texture))
|
||||
image_obj.colorspace_settings.name = 'sRGB'
|
||||
texture_d = bmat.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
texture_d.name = texture_d.label = 'diffuse'
|
||||
texture_d.location = -1000, 0
|
||||
texture_d.image = bpy.data.images[image_obj.name]
|
||||
|
||||
if texture_ao:
|
||||
bmat.node_tree.links.new(texture_d.outputs['Color'], mix_node.inputs['A'])
|
||||
bmat.node_tree.links.new(texture_d.outputs['Color'], mix_node.inputs[6])
|
||||
else:
|
||||
bmat.node_tree.links.new(texture_d.outputs['Color'], principled_node.inputs['Base Color'])
|
||||
|
||||
|
@ -86,6 +93,7 @@ def assign_pbr_material(obj_names, textures_path):
|
|||
image_obj = bpy.data.images.load(os.path.join(textures_path, texture))
|
||||
image_obj.colorspace_settings.name = 'Linear'
|
||||
texture_m = bmat.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
texture_m.name = texture_m.label = 'metallic'
|
||||
texture_m.location = -1000, -500
|
||||
texture_m.image = bpy.data.images[image_obj.name]
|
||||
|
||||
|
@ -95,6 +103,7 @@ def assign_pbr_material(obj_names, textures_path):
|
|||
image_obj = bpy.data.images.load(os.path.join(textures_path, texture))
|
||||
image_obj.colorspace_settings.name = 'Linear'
|
||||
texture_r = bmat.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
texture_r.name = texture_r.label = 'roughness'
|
||||
texture_r.location = -1000, -1000
|
||||
texture_r.image = bpy.data.images[image_obj.name]
|
||||
|
||||
|
@ -104,6 +113,7 @@ def assign_pbr_material(obj_names, textures_path):
|
|||
image_obj = bpy.data.images.load(os.path.join(textures_path, texture))
|
||||
image_obj.colorspace_settings.name = 'Non-Color'
|
||||
texture_n = bmat.node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
texture_n.name = texture_n.label = 'normal'
|
||||
texture_n.location = -1000, -1500
|
||||
texture_n.image = bpy.data.images[image_obj.name]
|
||||
|
||||
|
@ -113,7 +123,6 @@ def assign_pbr_material(obj_names, textures_path):
|
|||
bmat.node_tree.links.new(texture_n.outputs['Color'], normal_node.inputs['Color'])
|
||||
bmat.node_tree.links.new(normal_node.outputs['Normal'], principled_node.inputs['Normal'])
|
||||
|
||||
|
||||
obj.data.materials.append(bmat)
|
||||
|
||||
logger.info('Shading of %s objects is finished!', len(obj_names))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue