Skip to content

Setup Blender Environment

Alex Petsiuk edited this page Mar 17, 2024 · 9 revisions

This section contains methods to set up a Blender scene using Python scripts. Considering continuous Blender evolution, please refer to Blender Python API. Provided scripts have been developed for Blender 3.4.

Light sources

Automatically generate light sources.

import bpy

# create light datablock, set attributes
light_data_1 = bpy.data.lights.new(name="scene_light_1", type='POINT')
light_data_1.energy = 50
# create new object with our light datablock
light_object_1 = bpy.data.objects.new(name="scene_light_1", object_data=light_data_1)
# link light object
bpy.context.collection.objects.link(light_object_1)
# make it active 
bpy.context.view_layer.objects.active = light_object_1
#change location
light_object_1.location = (25, 15, 5)


# create light datablock, set attributes
light_data_2 = bpy.data.lights.new(name="scene_light_2", type='SUN')
light_data_2.energy = 5
# create new object with our light datablock
light_object_2 = bpy.data.objects.new(name="scene_light_2", object_data=light_data_2)
# link light object
bpy.context.collection.objects.link(light_object_2)
# make it active 
bpy.context.view_layer.objects.active = light_object_2
#change location
light_object_2.location = (15, 25, 5)
light_object_2.rotation_euler = (0.2, 0.1, 0.1) # orientation angles in radians


# LIGHT MANIPULATION
s_light_1 = bpy.data.collections['Collection'].objects['Light_point']
s_light_1.select_set(True)
bpy.context.view_layer.objects.active = s_light_1
so = bpy.context.active_object
# set light coordinates
so.location[0] = random.randint(50, 230)+0.1
so.location[1] = random.randint(1, 190)+0.1
so.location[2] = random.randint(50, 180)+0.1
            
s_light_2 = bpy.data.collections['Collection'].objects['Light_area']
s_light_2.select_set(True)
bpy.context.view_layer.objects.active = s_light_2
so = bpy.context.active_object
# set light coordinates
so.location[0] = random.randint(50, 230)+0.1
so.location[1] = random.randint(1, 190)+0.1
so.location[2] = random.randint(50, 180)+0.1
so.rotation_euler[2] = random.randint(0, 200)/100 # radians (?)

Choose which types of lighting you need:

Camera settings

Since one camera object is created by default, we only modify its settings, orientation, and location.

# origin - where you place the gcode mesh
origin_x = 120
origin_y = 110
origin_z = 0

# Make camera look at the g-code object
s_cam = bpy.data.collections['Collection'].objects['Camera']
s_cam.select_set(True)
bpy.context.view_layer.objects.active = s_cam
so = bpy.context.active_object
            
# set camera angles to zero
so.rotation_euler[0] = 0
so.rotation_euler[1] = 0
so.rotation_euler[2] = 0
    
so.location[0] = random.randint(10, 230)+0.1
so.location[1] = random.randint(10, 230)+0.1
so.location[2] = i+10+random.randint(10, 30)+0.1
    
angle_x_rad = math.atan((so.location[1]-origin_y)/(so.location[2]-origin_z))
angle_y_rad = math.atan((so.location[0]-origin_x)/(so.location[2]-origin_z))
so.rotation_euler[0] = (so.rotation_euler[0]-angle_x_rad)
so.rotation_euler[1] = (so.rotation_euler[1]+angle_y_rad)
#print(math.degrees(angle_x_rad))
print('Camera moved to ({},{},{}) m(?).'.format(so.location[0],so.location[1],so.location[2]))

Material settings

Information about ShaderNode identifiers in Python

import bpy 

# create new material
gcode_mat = bpy.data.materials.new(name = "GCode Material")
gcode_mat.use_nodes = True
nodes = gcode_mat.node_tree.nodes

material_output = nodes.get("Material Output")
material_output.location = (500,200)

# https://docs.blender.org/api/current/bpy.types.ShaderNode.html
color_RGB_1 = gcode_mat.node_tree.nodes.new('ShaderNodeRGB')
color_RGB_1.location = (-1800,700)
color_RGB_1.outputs[0].default_value = (1,0.105,0.034,1)

color_RGB_2 = gcode_mat.node_tree.nodes.new('ShaderNodeRGB')
color_RGB_2.location = (-1800,500)
color_RGB_2.outputs[0].default_value = (1,0.626,0.0767,1)

principled_node = gcode_mat.node_tree.nodes.new('ShaderNodeBsdfPrincipled')
principled_node.location = (-850,250)
texture_coords = gcode_mat.node_tree.nodes.new('ShaderNodeTexCoord')
texture_coords.location = (-2050,200)
texture_voronoi = gcode_mat.node_tree.nodes.new('ShaderNodeTexVoronoi')
texture_voronoi.location = (-1850,-50)
texture_noise = gcode_mat.node_tree.nodes.new('ShaderNodeTexNoise')
texture_noise.location = (-1850,200)
mix_rgb_1 = gcode_mat.node_tree.nodes.new('ShaderNodeMixRGB')
mix_rgb_1.location = (-1650,100)
color_ramp_1 = gcode_mat.node_tree.nodes.new('ShaderNodeValToRGB')
color_ramp_1.location = (-1450,250)
color_ramp_2 = gcode_mat.node_tree.nodes.new('ShaderNodeValToRGB')
color_ramp_2.location = (-1450,-50)
mix_rgb_2 = gcode_mat.node_tree.nodes.new('ShaderNodeMixRGB')
mix_rgb_2.location = (-1100,250)
add_node = gcode_mat.node_tree.nodes.new('ShaderNodeMath')
add_node.location = (-1100,50)
bump_node = gcode_mat.node_tree.nodes.new('ShaderNodeBump')
bump_node.location = (-1100,-200)
glossy_bsdf = gcode_mat.node_tree.nodes.new('ShaderNodeBsdfGlossy')
glossy_bsdf.location = (-550,0)
diffuse_bsdf = gcode_mat.node_tree.nodes.new('ShaderNodeBsdfDiffuse')
diffuse_bsdf.location = (-550,-200)

mixer_node_1 = gcode_mat.node_tree.nodes.new('ShaderNodeMixShader')
mixer_node_1.location = (-300,-50)
mixer_node_1.inputs[0].default_value = 0.23

transparent_bsdf = gcode_mat.node_tree.nodes.new('ShaderNodeBsdfTransparent')
transparent_bsdf.location = (-100,20)

#translucent_node = shell_mat.node_tree.nodes.new('ShaderNodeBsdfTranslucent')
#translucent_node.location = (50,0)
#translucent_node.inputs[0].default_value = (0.799,0.143,0.080,1.0)
mixer_node_2 = gcode_mat.node_tree.nodes.new('ShaderNodeMixShader')
mixer_node_2.location = (100,-70)
#mixer_node_2.inputs[0].default_value = 0.23
mixer_node_3 = gcode_mat.node_tree.nodes.new('ShaderNodeMixShader')
mixer_node_3.location = (300,100)
#shell_mat.node_tree.links.new(translucent_node.outputs[0],mixer_node_2.inputs[2])
gcode_mat.node_tree.links.new(principled_node.outputs[0],mixer_node_3.inputs[1])
gcode_mat.node_tree.links.new(mixer_node_3.outputs[0],material_output.inputs[0])

gcode_mat.node_tree.links.new(texture_coords.outputs[0],texture_noise.inputs[0])
gcode_mat.node_tree.links.new(texture_noise.outputs[1],mix_rgb_1.inputs[1])
gcode_mat.node_tree.links.new(texture_voronoi.outputs[1],mix_rgb_1.inputs[2])
gcode_mat.node_tree.links.new(mix_rgb_1.outputs[0],color_ramp_1.inputs[0])
gcode_mat.node_tree.links.new(mix_rgb_1.outputs[0],color_ramp_2.inputs[0])
gcode_mat.node_tree.links.new(color_ramp_1.outputs[0],mix_rgb_2.inputs[0])

gcode_mat.node_tree.links.new(color_RGB_1.outputs[0],mix_rgb_2.inputs[2])
gcode_mat.node_tree.links.new(color_RGB_1.outputs[0],diffuse_bsdf.inputs[0])
gcode_mat.node_tree.links.new(color_RGB_1.outputs[0],transparent_bsdf.inputs[0])

gcode_mat.node_tree.links.new(color_RGB_2.outputs[0],mix_rgb_2.inputs[1])
gcode_mat.node_tree.links.new(color_RGB_2.outputs[0],principled_node.inputs[3])
gcode_mat.node_tree.links.new(color_RGB_2.outputs[0],glossy_bsdf.inputs[0])

gcode_mat.node_tree.links.new(color_ramp_1.outputs[0],add_node.inputs[0])
gcode_mat.node_tree.links.new(add_node.outputs[0],principled_node.inputs[7])
gcode_mat.node_tree.links.new(color_ramp_2.outputs[0],bump_node.inputs[2])
gcode_mat.node_tree.links.new(bump_node.outputs[0],principled_node.inputs[22])
gcode_mat.node_tree.links.new(mix_rgb_2.outputs[0],principled_node.inputs[0])
gcode_mat.node_tree.links.new(glossy_bsdf.outputs[0],mixer_node_1.inputs[1])
gcode_mat.node_tree.links.new(diffuse_bsdf.outputs[0],mixer_node_1.inputs[2])
gcode_mat.node_tree.links.new(mixer_node_1.outputs[0],mixer_node_2.inputs[2])

gcode_mat.node_tree.links.new(transparent_bsdf.outputs[0],mixer_node_2.inputs[1])
gcode_mat.node_tree.links.new(mixer_node_2.outputs[0],mixer_node_3.inputs[2])

# https://blender.stackexchange.com/questions/189712/how-to-add-a-new-stop-to-the-color-ramp
#bpy.data.materials["Shell Material.001"].node_tree.nodes["Glossy BSDF.001"].distribution = 'BECKMANN'

texture_noise.inputs[2].default_value = 20
texture_noise.inputs[3].default_value = 8
texture_noise.inputs[4].default_value = 0.5
texture_noise.inputs[5].default_value = 2

texture_voronoi.inputs[2].default_value = 50

mix_rgb_1.inputs[0].default_value = 0.75

color_ramp_1.color_ramp.elements[0].position = (0.0)
color_ramp_1.color_ramp.elements[1].position = (1.0)

mix_rgb_2.inputs['Color1'].default_value = (0.568,1,1,1)
mix_rgb_2.inputs['Color2'].default_value = (1,1,1,1)

add_node.inputs[1].default_value = 0.3

bump_node.invert = True
bump_node.inputs[0].default_value = 0.75
bump_node.inputs[1].default_value = 20.0

glossy_bsdf.distribution = 'BECKMANN'
glossy_bsdf.inputs['Color'].default_value = (1,1,1,1)
glossy_bsdf.inputs[1].default_value = 0.8

diffuse_bsdf.inputs['Color'].default_value = (1,1,1,1)
diffuse_bsdf.inputs[1].default_value = 0.7
mixer_node_1.inputs[0].default_value = 0.5
mixer_node_2.inputs[0].default_value = 0.5
mixer_node_3.inputs[0].default_value = 0.7

principled_node.distribution = 'GGX'
principled_node.subsurface_method = 'BURLEY'

#principled_node.inputs[0].default_value = (0.799,0.074,0.051,1.0) # color
principled_node.inputs[1].default_value = 0.255 # subsurface
#principled_node.inputs[3].default_value = (1,1,1,1.0) # subsurface color

principled_node.inputs[6].default_value = 0.0 #4 - Metallic
#principled_node.inputs[7].default_value = 0.830 #5-Specular
principled_node.inputs[8].default_value = 0.0 #6-Specular tint
principled_node.inputs[9].default_value = 0.0 #7-Roughness
principled_node.inputs[10].default_value = 0.0 #8-Anisotropic
#principled_node.inputs[9].default_value = 0.0 #9-Anisotropic rotation
#principled_node.inputs[10].default_value = 0.0 #10-Sheen
principled_node.inputs[13].default_value = 0.5 #11-Sheen tint
principled_node.inputs[14].default_value = 0.0 #12-Clearcoat
principled_node.inputs[15].default_value = 0.0 #13-Clearcoat roughness
principled_node.inputs[16].default_value = 1.45 #14-IOR
principled_node.inputs[17].default_value = 1 #15-Transmission
#principled_node.inputs[16].default_value = 0.0 #16-Transmission roughness
principled_node.inputs[19].default_value = (0.2,0.2,0.2,1.0) #17-Emission
principled_node.inputs[20].default_value = 0.1 #18-Emission Strength
principled_node.inputs[21].default_value = 1 #19-Alpha

Running the script above will create a new material shader with the "GCode Material" name.

image

HDRI Maps

https://hdrmaps.com/freebies/

How to set an HDRI Map:

image


Compositing

image

image

Clone this wiki locally