Materials

MolecularNodes ships a small set of pre-built materials, available as classes in mn.material. Instantiating one creates a new, independent Blender material — starting values are set through the constructor, and every parameter remains tweakable on the instance afterwards.

import molecularnodes as mn
from molecularnodes.nodes import geometry as g
from nodebpy import shader as s

cv = mn.Canvas(engine="EEVEE", resolution=(800, 800), transparent=True)

Pre-built materials

Pass a preset directly to add_style(). The parameters map onto the inputs of the nodes inside the material, so changing them updates the render immediately.

mat = mn.material.AmbientOcclusion(distance=2.0)
mol = mn.Molecule.fetch("8H1B").add_style("surface", material=mat)

cv.look_at(mol)
display(cv.snapshot())

mat.distance = 0.15
cv.snapshot()
(a) distance=2.0
(b) distance=0.15
Figure 1: The Ambient Occlusion material is performant and aesthetically pleasing. Parameters can be tweaked on the instance after creation.

To swap the material on an already-created style, assign a new material to the style node’s material socket:

flat = mn.material.Flat(thickness=0.2)
mol.tree.tree.nodes["Style Surface"].inputs["Material"].default_value = (
    flat.material
)
cv.snapshot()
Figure 2

Each preset is a separate material datablock, so tweaking one style’s material never affects another’s. The underlying Blender material is always available as .material, and the nodes used to build it are kept as attributes on the instance (e.g. mat.ao, mat.bsdf) for access to anything not exposed as a parameter.

Custom materials

For full control, build a material from scratch with the nodebpy shader nodes. Anything built inside the with s.material() block becomes the material’s node tree, and the MNColor node provides the per-atom colors.

with s.material("Custom Material") as custom:
    custom.nodes.clear()
    col = mn.nodes.shader.MNColor()
    ao = s.AmbientOcclusion(col, distance=1.0, samples=128)
    ao.o.color >> s.MaterialOutput().i.surface

# regular node lookup and property assignment
mol.tree.tree.nodes["Style Surface"].inputs["Material"].default_value = (
    custom.material
)
cv.snapshot()
Figure 3: A custom material built with nodebpy’s shader nodes.

Render Engines and Materials

The different render engines handle materials diferently.

import MDAnalysis as mda
import itertools
from MDAnalysis.tests.datafiles import PSF, DCD

cv = mn.Canvas(resolution=(800, 800), transparent=True)