From BlenderWiki

Jump to: navigation, search
Project status:
in progress Inprogress75.jpg 75%
 committed to Blender svn trunk on Feb 09

Current State

.blend file
.blend file
Media:Dev-pynodes-test_halftone.blend (this file contains a NPR-type shader. It's by me, jesterKing, so the code may not be all too beautiful ;)

PyNodes are now available in the main Blender development version (svn trunk). Only shader pynodes work for now, accessible from the list of node types in the Nodes window, as "Dynamic" nodes.

This page explains how to write pynode scripts:


  • All Python in Blender had to be updated to support threads. This is an important update that needs to be well tested, it affects every use of scripting in Blender, except the game engine.
  • The API is not final yet, a few small changes can occur.
  • More ShadeInput (shi) data will be made accessible to pynodes.
  • Composite pynodes should be added as soon as possible.

Known problems:

  • A patch here (against r13811) should fix this problem. Do test. Crash when rendering with more than one thread. Investigating. Disabling pynodes execution when using more than one thread for rendering. This prevents the crashes while a proper fix isn't implemented. Thanks jensverwiebe for testing and reporting and ibkanat for confirming, both in #blendercoders.

Development Information

Warning: some parts of the sections below are outdated

Add bug reports to BlenderDev/PyNodes/Bugs

From the patch tracker: "This patch adds Python Nodes to the shader tree. An example .blend will be added to play with. It'll show the format of the script for Python Nodes (basically a class with two functions implemented).

When an empty script node is added, you can choose a script for it. This script defines both the input and output sockets and the execution body. After initialisation, the new typeinfo will be added to the tree's alltypes, and from then on can be added also from the add menu "Dynamic > MyScriptNode".

Nodes can be updated on the fly (see They work after instantiation just like any other node, so they can be appended and grouped and whatnot (see also

For this to work there has been some changes as how the typeinfos internally are kept: from a static global array to a ListBase in the ntree itself. This in itself is not necessarily the best way, since atm you'll see only added script nodes for the tree being edited, but that shouldn't be the biggest issue now (but will be tackled)."

PyNodes: What are they

Python nodes give the user a means of creating quickly new nodes to use in a shader tree (and in the future also in the node compositor).

Through a fairly simple interface such a node can be created, added to a tree and used like any other node.

Most important feature is that one can quickly develop/prototype new shaders, which might later on be written in C for better performance.

Since the execution code is run through Python, you'll see lower performance, but it should still be quite ok to use. When you have a fully developed python node script and you use it a lot, it would be good to consider rewriting it in C.

PyNodes: The internals

Add pictures explaining the internal workings

  • adding from empty script node
  • loading from .blender
  • updating existing script node
  • creating the typeinfo
  • populating the typeinfo->inputs and typeinfo->outputs
  • execution model


PyNodes: Finishing

Nathan is too busy at the moment and can't dedicate enough time to PyNodes. Willian (that's me) offered to help where possible.


Collecting here the names of PyNodes related files, as I check them (list is not complete nor in proper order):

In source/blender/:

  • In nodes/:
    • intern/SHD_nodes/SHD_dynamic.c
  • In src/:
    • drawnode.c
    • editnode.c
  • In blenkernel/:
    • BKE_node.h
    • intern/node.c


Randomized pixels

Simplistic test to get a feel of how to write a pynodes script:

# Randomized pixels, Color -> Color
from Blender import Node
from Blender.Noise import random
class MyNode(Node.node):
	def __init__(self, sockets):
		col = ['col', Node.RGBA, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0]
		sockets.input = [col]
		sockets.output = [col]
	def __call__(self):
		ocol = list(self.input['col'])
		ocol[0] *= random()
		ocol[1] *= random()
		ocol[2] *= random()
		self.output['col'] = ocol


Open Blender with default scene plus the randomize pixels script written above and a node material for the default cube.

Open Blender. Select some object and add a material to it. Make sure material is node based one ("Nodes" button in the material settings). Open the script in Blender's text editor. Open the node editor. Add a dynamic node to the node network. The node should have a file selector. You should see the file opened in the text editor there. Select it. Build your node setup as usual after this.

Note that if you make changes to a PyNode script, you need to hit the "Update" button found in the node.


  • Basically it works, needs more testing and small additions here and there: access to more data, interface polish, etc.


  1. Sync to current Blender trunk SVN -- Done by Nathan
  2. Understand well the PyNodes system: ideas, how it works, how it was implemented. Done.
  3. Test, fix bugs
  4. Implement missing bits
  5. Update to follow current BPython guidelines
  6. Get some examples and user documentation done