Spaces:
Sleeping
Sleeping
File size: 5,125 Bytes
2eba94f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import bpy
import sys
import os
def create_tex_node(nodes, img_path, label, color_space, location):
img = bpy.data.images.load(img_path)
tex = nodes.new(type='ShaderNodeTexImage')
tex.image = img
tex.label = label
tex.location = location
tex.image.colorspace_settings.name = color_space
return tex
def setup_environment_lighting(hdri_path):
if not bpy.data.worlds:
bpy.data.worlds.new(name="World")
if bpy.context.scene.world is None:
bpy.context.scene.world = bpy.data.worlds[0]
world = bpy.context.scene.world
world.use_nodes = True
nodes = world.node_tree.nodes
links = world.node_tree.links
nodes.clear()
env_tex = nodes.new(type="ShaderNodeTexEnvironment")
env_tex.image = bpy.data.images.load(hdri_path)
env_tex.location = (-300, 0)
bg = nodes.new(type="ShaderNodeBackground")
bg.location = (0, 0)
output = nodes.new(type="ShaderNodeOutputWorld")
output.location = (300, 0)
links.new(env_tex.outputs["Color"], bg.inputs["Color"])
links.new(bg.outputs["Background"], output.inputs["Surface"])
def setup_gpu_rendering():
bpy.context.scene.render.engine = 'CYCLES'
prefs = bpy.context.preferences
cprefs = prefs.addons['cycles'].preferences
# Choose backend depending on GPU type: 'CUDA', 'OPTIX', 'HIP', 'METAL'
cprefs.compute_device_type = 'CUDA'
bpy.context.scene.cycles.device = 'GPU'
def generate_blend(obj_path, base_color_path, normal_map_path, roughness_path, metallic_path, output_blend):
# Reset scene
bpy.ops.wm.read_factory_settings(use_empty=True)
# Import OBJ
bpy.ops.import_scene.obj(filepath=obj_path)
obj = bpy.context.selected_objects[0]
# Create material
mat = bpy.data.materials.new(name="BRDF_Material")
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
nodes.clear()
output = nodes.new(type='ShaderNodeOutputMaterial')
output.location = (400, 0)
principled = nodes.new(type='ShaderNodeBsdfPrincipled')
principled.location = (100, 0)
links.new(principled.outputs['BSDF'], output.inputs['Surface'])
# Base Color
base_color = create_tex_node(nodes, base_color_path, "Base Color", 'sRGB', (-600, 200))
links.new(base_color.outputs['Color'], principled.inputs['Base Color'])
# Roughness
rough = create_tex_node(nodes, roughness_path, "Roughness", 'Non-Color', (-600, 0))
links.new(rough.outputs['Color'], principled.inputs['Roughness'])
# Metallic
metal = create_tex_node(nodes, metallic_path, "Metallic", 'Non-Color', (-600, -200))
links.new(metal.outputs['Color'], principled.inputs['Metallic'])
# Normal Map
normal_tex = create_tex_node(nodes, normal_map_path, "Normal Map", 'Non-Color', (-800, -400))
normal_map = nodes.new(type='ShaderNodeNormalMap')
normal_map.location = (-400, -400)
links.new(normal_tex.outputs['Color'], normal_map.inputs['Color'])
links.new(normal_map.outputs['Normal'], principled.inputs['Normal'])
# Assign material
if obj.data.materials:
obj.data.materials[0] = mat
else:
obj.data.materials.append(mat)
# Global Illumination using Blender's default forest HDRI
blender_data_path = bpy.utils.resource_path('LOCAL')
forest_hdri_path = os.path.join(blender_data_path, "datafiles", "studiolights", "world", "forest.exr")
print(f"Using HDRI: {forest_hdri_path}")
setup_environment_lighting(forest_hdri_path)
# GPU rendering setup
setup_gpu_rendering()
# Pack textures into .blend
bpy.ops.file.pack_all()
# Set the 3D View to Rendered mode and focus on object
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
space.shading.type = 'RENDERED' # Set viewport shading to Rendered
for region in area.regions:
if region.type == 'WINDOW':
override = {'area': area, 'region': region, 'scene': bpy.context.scene}
bpy.ops.view3d.view_all(override, center=True)
elif area.type == 'NODE_EDITOR':
for space in area.spaces:
if space.type == 'NODE_EDITOR':
space.tree_type = 'ShaderNodeTree' # Switch to Shader Editor
space.shader_type = 'OBJECT'
# Optional: Switch active workspace to Shading (if it exists)
for workspace in bpy.data.workspaces:
if workspace.name == 'Shading':
bpy.context.window.workspace = workspace
break
# Save the .blend file
bpy.ops.wm.save_as_mainfile(filepath=output_blend)
print(f"✅ Saved .blend file with BRDF, HDRI, GPU: {output_blend}")
if __name__ == "__main__":
argv = sys.argv
argv = argv[argv.index("--") + 1:] # Only use args after "--"
if len(argv) != 6:
print("Usage:\n blender --background --python generate_blend.py -- obj base_color normal roughness metallic output.blend")
sys.exit(1)
generate_blend(*argv)
|