Featured post

new redirect for blender.org bpy docs.

http://www.blender.org/api/blender_python_api_current/ As of 10/11 november 2015 we can now link to the current api docs and not be worr...

June 27, 2013

automatic colour ramped shader from geometry height

As part of BlenderSciViz it's going to be useful to generate materials automatically.

This is going to be fun. or not.

Given whatever kind of mesh, i want to be able to run a function that checks the mesh data and makes a shader automatically. Let's try some basic stuff first, like add nodes and connect sockets via a script.
  • allow to easily define custom color ramps
  • allow easy floor and ceiling for ramp
  • arrange neatly
  • hide unused sockets
This script places the nodes, and connects them as in the image
import bpy
def empty_materials():
for mat in mats.keys():
mats.remove(mats[mat])
def create_cycles_material(settings):
scn = bpy.context.scene
if not scn.render.engine == 'CYCLES':
scn.render.engine = 'CYCLES'
mat = bpy.data.materials.new('zheight')
mat.use_nodes = True
nodes = mat.node_tree.nodes
'''Make or move nodes'''
node = nodes['Diffuse BSDF']
node.location = 600, 120
node = nodes['Material Output']
node.location = 800, 120
node = nodes.new('ShaderNodeNewGeometry')
node.name = 'Geometry_0'
node.location = -300, 120
node = nodes.new('ShaderNodeVectorMath')
node.operation = 'ADD'
node.label = 'ADD'
node.name = 'ADD_0'
node.location = -100, 120
node = nodes.new('ShaderNodeVectorMath')
node.operation = 'DOT_PRODUCT'
node.label = 'DOT'
node.name = 'DOT_0'
node.location = 100, 120
node = nodes.new('ShaderNodeValToRGB')
node.location = 300, 120
'''Connect nodes
Geometry|Position > ADD_0|0
#ADD_0|Vector > DOT_0|0
#DOT_0|Value > ColorRamp|Fac
#ColorRamp|Color_Out > DiffuseBSDF|Color_In
'''
''' Geometry|Position > ADD_0|0 '''
output = nodes['Geometry_0'].outputs['Position']
input = nodes['ADD_0'].inputs[0]
mat.node_tree.links.new(output, input)
''' ADD_0|Vector > DOT_0|0 '''
output = nodes['ADD_0'].outputs['Vector']
input = nodes['DOT_0'].inputs[0]
mat.node_tree.links.new(output, input)
''' DOT_0|Value > ColorRamp|Fac '''
output = nodes['DOT_0'].outputs['Value']
input = nodes['ColorRamp'].inputs['Fac']
mat.node_tree.links.new(output, input)
''' ColorRamp|Color > Diffuse BSDF|Color '''
output = nodes['ColorRamp'].outputs['Color']
input = nodes['Diffuse BSDF'].inputs['Color']
mat.node_tree.links.new(output, input)
pass
create_cycles_material(None)
As you can imagine, this much repitition is going to get on my nerves. So it will be useful to write a mini node connecting grammar. Something like:
'''Connect nodes
Geometry|Position > ADD_0|0
ADD_0|Vector > DOT_0|0
DOT_0|Value > ColorRamp|Fac
ColorRamp|Color > DiffuseBSDF|Color
where left is always an ouput node, and
right is always an input node
'''


Node links mini grammar (faster link scripting)

This is a simple but effective way to reduce lines of code needed to connect nodes and sockets.
# sci_viz module can be found at
# https://github.com/zeffii/BlenderSciViz/tree/master/modules
import bpy
from sci_viz.node_tools import make_link
def empty_materials():
mats = bpy.data.materials
for mat in mats.keys():
mats.remove(mats[mat])
def create_cycles_material(settings):
scn = bpy.context.scene
if not scn.render.engine == 'CYCLES':
scn.render.engine = 'CYCLES'
mat = bpy.data.materials.new('zheight')
mat.use_nodes = True
nodes = mat.node_tree.nodes
'''Make or move nodes'''
node = nodes['Diffuse BSDF']
node.location = 600, 120
node = nodes['Material Output']
node.location = 800, 120
node = nodes.new('ShaderNodeNewGeometry')
node.name = 'Geometry_0'
node.location = -300, 120
node = nodes.new('ShaderNodeVectorMath')
node.operation = 'ADD'
node.label = 'ADD'
node.name = 'ADD_0'
node.location = -100, 120
node = nodes.new('ShaderNodeVectorMath')
node.operation = 'DOT_PRODUCT'
node.label = 'DOT'
node.name = 'DOT_0'
node.location = 100, 120
node = nodes.new('ShaderNodeValToRGB')
node.location = 300, 120
# using connection grammar
connection_list = [
'Geometry_0|Position > ADD_0|0',
'ADD_0|Vector > DOT_0|0',
'DOT_0|Value > ColorRamp|Fac',
'ColorRamp|Color > Diffuse BSDF|Color'
]
for link in connection_list:
make_link(mat, link)
create_cycles_material(None)