Skip to content

Instantly share code, notes, and snippets.

@blender8r
Created May 4, 2023 13:07
Show Gist options
  • Select an option

  • Save blender8r/1105dbb73d2f3442f1ab552e0537fb74 to your computer and use it in GitHub Desktop.

Select an option

Save blender8r/1105dbb73d2f3442f1ab552e0537fb74 to your computer and use it in GitHub Desktop.
Python code for Blender that reproduces the Ghibli Shader technique by Kristof Dedene
import bpy
IMAGE = None
TEXTURE_PATH = 'D:\\images\\textures\\hatch_1.jpg'
for i in bpy.data.images:
if i.filepath == TEXTURE_PATH:
IMAGE = i
if not IMAGE:
IMAGE = bpy.data.images.load(TEXTURE_PATH)
# create an ico sphere and set to smooth shade
bpy.ops.mesh.primitive_ico_sphere_add()
sphere = bpy.context.active_object
for p in sphere.data.polygons:
p.use_smooth = True
# add subd modifier
subd = sphere.modifiers.new('subsurf', type='SUBSURF')
subd.levels = 3
# create new material
mat_name = 'Ghibli Hatch Shader'
mat = bpy.data.materials.new(mat_name)
mat.use_nodes = True
node_tree = mat.node_tree
nodes = node_tree.nodes
links = node_tree.links
sphere.data.materials.append(mat)
# get main shader material output node
node_mat_output = nodes['Material Output']
# delete default bsdf node
nodes.remove(nodes['Principled BSDF'])
# create new nodes and set their values
node_emission = nodes.new(type='ShaderNodeEmission')
node_mix1 = nodes.new(type='ShaderNodeMixRGB')
node_mix1.blend_type = 'MULTIPLY'
node_mix1.inputs['Fac'].default_value = 1.0
node_mix1.label = 'Ink Effect Blend'
node_mix2 = nodes.new(type='ShaderNodeMixRGB')
node_mix2.blend_type = 'SOFT_LIGHT'
node_mix2.inputs['Fac'].default_value = 0.75
node_mix2.label = 'Secondary Noise Strength'
node_mix3 = nodes.new(type='ShaderNodeMixRGB')
node_mix3.blend_type = 'SOFT_LIGHT'
node_mix3.label = 'Hatching Effect Blend'
node_mix4 = nodes.new(type='ShaderNodeMixRGB')
node_mix4.blend_type = 'MIX'
node_mix4.inputs['Fac'].default_value = 0.8
node_mix4.label = 'Speckle Effect Blend'
node_color_ramp1 = nodes.new(type='ShaderNodeValToRGB')
node_color_ramp1.color_ramp.elements[0].position = 0.0
node_color_ramp1.color_ramp.elements[0].color = (0.0373, 0.0752, 0.0305, 1.0)
node_color_ramp1.color_ramp.elements[1].position = 0.7
node_color_ramp1.color_ramp.elements[1].color = (0.4351, 0.4297, 0.0953, 1.0)
node_color_ramp1.label = 'Secondary Color Blend'
node_color_ramp2 = nodes.new(type='ShaderNodeValToRGB')
node_color_ramp2.color_ramp.elements[0].position = 0.15
node_color_ramp2.color_ramp.elements[1].position = 0.3
node_color_ramp2.label = 'Hatching Falloff'
node_color_ramp3 = nodes.new(type='ShaderNodeValToRGB')
node_color_ramp3.label = 'Voronoi Strength'
node_color_ramp4 = nodes.new(type='ShaderNodeValToRGB')
node_color_ramp4.color_ramp.elements[0].position = 0.5
node_color_ramp4.color_ramp.elements[1].position = 0.7
node_color_ramp4.label = 'Speckle Falloff'
node_color_ramp5 = nodes.new(type='ShaderNodeValToRGB')
node_color_ramp5.color_ramp.elements[0].position = 0.0
node_color_ramp5.color_ramp.elements[1].position = 0.9
node_color_ramp5.label = 'Voronoi Softness Variation'
node_img_tex = nodes.new(type='ShaderNodeTexImage')
node_img_tex.image = IMAGE
node_img_tex.label = 'Hatching Texture Map'
node_shader2RGB = nodes.new(type='ShaderNodeShaderToRGB')
node_mapping = nodes.new(type='ShaderNodeMapping')
node_mapping.inputs[3].default_value = (8.0, 8.0, 8.0)
node_tex_coords = nodes.new(type='ShaderNodeTexCoord')
node_diff_bsdf = nodes.new(type='ShaderNodeBsdfDiffuse')
node_voronoi = nodes.new(type='ShaderNodeTexVoronoi')
node_voronoi.feature = 'SMOOTH_F1'
node_voronoi.inputs[2].default_value = 10.0
node_musgrave = nodes.new(type='ShaderNodeTexMusgrave')
node_musgrave.inputs[2].default_value = 25.0
node_noise = nodes.new(type='ShaderNodeTexNoise')
node_noise.inputs[2].default_value = 5.0
node_noise.inputs[4].default_value = 0.5
# link nodes together
links.new(node_mat_output.inputs['Surface'], node_emission.outputs['Emission'])
links.new(node_emission.inputs['Color'], node_mix1.outputs['Color'])
links.new(node_mix1.inputs['Color1'], node_color_ramp1.outputs['Color'])
links.new(node_mix1.inputs['Color2'], node_color_ramp2.outputs['Color'])
links.new(node_color_ramp1.inputs['Fac'], node_mix2.outputs['Color'])
links.new(node_color_ramp2.inputs['Fac'], node_mix3.outputs['Color'])
links.new(node_mix2.inputs['Color2'], node_mix4.outputs['Color'])
links.new(node_mix4.inputs['Color2'], node_color_ramp4.outputs['Color'])
links.new(node_color_ramp4.inputs['Fac'], node_musgrave.outputs['Fac'])
links.new(node_mix4.inputs['Color1'], node_color_ramp3.outputs['Color'])
links.new(node_color_ramp3.inputs['Fac'], node_voronoi.outputs['Color'])
links.new(node_voronoi.inputs['Smoothness'], node_color_ramp5.outputs['Color'])
links.new(node_color_ramp5.inputs['Fac'], node_noise.outputs['Color'])
links.new(node_mix2.inputs['Color1'], node_shader2RGB.outputs['Color'])
links.new(node_mix3.inputs['Color1'], node_shader2RGB.outputs['Color'])
links.new(node_shader2RGB.inputs['Shader'], node_diff_bsdf.outputs['BSDF'])
links.new(node_mix3.inputs['Color2'], node_img_tex.outputs['Color'])
links.new(node_img_tex.inputs['Vector'], node_mapping.outputs['Vector'])
links.new(node_mapping.inputs['Vector'], node_tex_coords.outputs['UV'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment