text:
What's the most reliable way of converting a material into reusable code blocks?
I'd like to convert certain materials into executable python code without having to re-code them from scratch each time.
While doing some initial experimentation on the principled shader, I realized that there are a lot of different attribute types and sub-attributes to handle eg. ShaderNodeBsdfPrincipled.input collection is holding 23 different structs:
<bpy_struct, NodeSocketColor("Base Color") at 0x7fe51de9b0d8>
<bpy_struct, NodeSocketFloatFactor("Subsurface") at 0x7fe51de9b2a8>
<bpy_struct, NodeSocketVector("Subsurface Radius") at 0x7fe51de9b478>
...

and calling dir(ShaderNodeBsdfPrincipled) yields:

['doc', 'module', 'slots', 'bl_description', 'bl_height_default', 'bl_height_max', 'bl_height_min', 'bl_icon', 'bl_idname', 'bl_label', 'bl_rna', 'bl_static_type', 'bl_width_default', 'bl_width_max', 'bl_width_min', 'color', 'dimensions', 'distribution', 'draw_buttons', 'draw_buttons_ext', 'height', 'hide', 'input_template', 'inputs', 'internal_links', 'is_registered_node_type', 'label', 'location', 'mute', 'name', 'output_template', 'outputs', 'parent', 'poll', 'poll_instance', 'rna_type', 'select', 'show_options', 'show_preview', 'show_texture', 'socket_value_update', 'subsurface_method', 'type', 'update', 'use_custom_color', 'width', 'width_hidden']`

Q: Is there any clever python trickery using "magic" object attributes or anything in order to store and restore the nodes, their attribute values and ideally all node connections as well?

If anyone would like to have a material for testing purposes, the following blend contains some kind of production setup (from Camera projection without generating UV's?).

Very nice......

Perhaps using something like DeepDiff https://pypi.org/project/deepdiff/ on each node versus a new node to see non-default values?

All approaches are welcome @MarkusvonBroady

If a miracle happens and batFINGER's solution isn't amazing, I'll see what I can come up with.

@MarkusvonBroady great idea re comparing against new node. Looked at this a while back, there is a q about it too, re nodes not playing the typical blender bl_rna game re default settings.  For most props in blender obj.is_property_set("foo") returns False if ob.foo is default.  Brockers, be a good one to have a blend with sample material to test against.

Sure @batFINGER. Hopefully a good choice otherwise let me know.

@brockmann NP from me either, after all this q was written to pay homage to G's answer on another question.  Sad that an undesignated bounty doesn't get distributed to all answers weighted by positive votes.   (Just as I believe there could be more than one "acceptable" answer)  Apologies for not getting back sooner,  took some time away from BSE to regain sanity.  Re https://blender.stackexchange.com/questions/218377/how-can-i-know-scripts-of-what-i-am-editing-on-mesh#comment368526_218377  check out the answerer's (Films) recent questions and answers... see any patterns?

Oops, missed that comment yesterday... Agree. However, it is like it is and you absolutely deserve it! Can start another one in a few weeks for Gorgious, I don't mind :) Still hope this nice answers are getting even more attention. No need to apologize, great to have you back though... reassuring that you noticed these patterns too @batFINGER

I can serialize and deserialize any Blender material configuration in JSON. It is possible for me to save my materials in a FreeCAD file and restore all these materials in Blender from this FreeCAD file. for more information see this thread on the FreeCAD forum

Make a dummy material with each node type of material.
Following on from the suggestion in comments by @MarkusvonBroady  couldn't resist....  Am waiting to see the excellent material serialization answer from you know who,
Pretty much zip the material node / inputs / outputs etc against a newly added default of same type,  and add to string buffer when not same. Have ignored any read only property and select.
Code and test Run.
import bpy
from math import isclose

LUT = dict()
BLACK = [0.0, 0.0, 0.0, 1.0]
WHITE = [1.0, 1.0, 1.0, 1.0]
ul = f'#{"-" * 44}\n'
buffer = []

def cmp(v1, v2):
    return (
        (len(v1) == len(v2))
        and all(isclose(*v) for v in zip(v1, v2))
    )

def vformat(nums, n, indent=8):
    nums = [f"{d}" for d in nums]
    return f",\n{' ' * indent}".join([", ".join(nums[i: i + n]) for i in range(0, len(nums), n)])

def fes(collection, prop, data, size, indent):
    output(
        f'{" " * indent}{collection}.foreach_set(\n'
        f'       "{prop}", [\n'
        f'        {vformat(data, size, 8 + indent)}\n'
        f'        ])'
    )

def groups_in_tree(node_tree):
    for node in node_tree.nodes:
        if hasattr(node, "node_tree"):
            yield node.node_tree
            yield from groups_in_tree(node.node_tree)

def group_io(n):
    output(f'node = nodes.new("{n.bl_rna.identifier}")')
    output(f'node.name = "{n.name}"')
    sockets = ("inputs", "outputs") if n.type == 'GROUP_INPUT' else ("outputs", "inputs")
    for skt in getattr(n, sockets[1]):
        if skt.type != 'CUSTOM' and skt.name:
            output(
                f"skt = group.{sockets[0]}.new('{skt.__class__.__name__}', "
                f'"{skt.name}", '
                f')'
            )
            output(f'skt.name = "{skt.name}"')
            dv = skt.default_value
            val = dv[:] if hasattr(dv, "foreach_get") else dv
            output(f"skt.default_value = {val}")
    output()

def colorramp(a, b):
    n = len(a.elements)
    output(f'ramp = node.color_ramp')
    compare(a, b, fstring="ramp.{k} = {va}")
    locs, deflocs = [0.0] * n, [0.0, 1.0]
    cols, defcols = [0.0] * (n << 2), BLACK + WHITE
    a.elements.foreach_get("position", locs), a.elements.foreach_get("color", cols)
    n = n - 2
    if n:
        output(
            f"for i in range({n}):\n"
            f"    ramp.elements.new(0.0)"
        )

    if not cmp(locs, deflocs):
        fes("ramp.elements", "position", locs, 1, 0)

    if not cmp(cols, defcols):
        fes(f'ramp.elements', "color", cols, 4, 0)

def mapping(a, b):
    output(f'map = node.mapping')
    compare(a, b, fstring="map.{k} = {va}")

    for i, c in enumerate(a.curves):
        n = len(c.points)
        pts, default = [0, 0] * n, [-1.0, -1.0, 1.0, 1.0]
        n -= 2
        if n:
            output(
                f'for i in range({n}):\n'
                f'    map.curves[{i}].points.new(0.0, 1.0)\n'
            )

        c.points.foreach_get("location", pts)
        if not cmp(pts, default):
            fes(f"map.curves[{i}].points", "location", pts, 2, 0)

def output(*args):
    s = " ".join(args) if args else ""
    buffer.append(s)

def compare(a, b, fstring="{k} = {va}", sockets="", i=0, ignore={'select'}):

    props = (
            (k, v)
        for k, v in a.bl_rna.properties.items()
        if (not v.is_readonly or k in ("mapping", "color_ramp"))
        and k not in ignore
    )

    for k, v in props:
        va = getattr(a, k)
        vb = getattr(b, k, None)

        if v.type in ('FLOAT', 'INT'):
            if v.is_array:
                if not isinstance(va, float):
                    va = va[:]
                if vb and not isinstance(vb, float):
                    vb = vb[:]

        if va != vb:
            if v.type == 'ENUM':
                va = f"'{va}'"
            elif v.type == 'STRING':
                va = f'"{va}"'
            elif v.type == 'POINTER':
                if k == "parent":
                    va = f'nodes.get("{va.name}")'
                elif a.type == 'GROUP':
                    return output(f'node.node_tree = groups.get("{a.node_tree.name}")')
                elif issubclass(v.fixed_type.__class__, bpy.types.ID):
                    va = repr(va).replace(f"['{va.name}']", f'.get("{va.name}")')
                elif k == "mapping":
                    return mapping(va, vb)
                elif k.startswith("color_ramp"):
                    return colorramp(va, vb)
            name = f'"{a.name}"' if hasattr(a, "name") else i
            output(fstring.format(**locals()))

def pnode(n, dummy):
    if n.type in ('GROUP_INPUT', 'GROUP_OUTPUT'):
        return group_io(n)
    nodetype = n.bl_rna.identifier
    default = LUT.setdefault(
        nodetype, dummy.nodes.new(nodetype)
    )

    output(f'node = nodes.new("{nodetype}")')
    compare(n, default, fstring="node.{k} = {va}")
    for sockets in ("inputs", "outputs"):
        for i, (a, b) in enumerate(
                zip(
                    getattr(n, sockets),
                    getattr(default, sockets),
                )
        ):

            compare(a, b, fstring='node.{sockets}[{name}].{k} = {va}', i=i, sockets=sockets)
    output()

def material_to_text(m):
    try:
        dummy = bpy.data.node_groups.get("DUMMY")
        if not dummy:
            output("import bpy")
            dummy = bpy.data.node_groups.new("DUMMY", "ShaderNodeTree")
            output("groups = {}  # for node groups")

        if hasattr(m, "use_nodes"):
            # material
            for gn in set(groups_in_tree(m.node_tree)):
                material_to_text(gn)
            nt = m.node_tree
            output(
                f"\n"
                f"{ul}#  Material: {m.name} \n{ul}\n"
                f'mat = bpy.data.materials.new("{m.name}")\n'
                f"mat.use_nodes = True\n"
                f"node_tree = mat.node_tree\n"
                f"nodes = node_tree.nodes\n"
                f"nodes.clear()\n"
                f"links = node_tree.links\n"
            )

        else:
            # group
            nt = m
            output(
                f"\n"
                f"{ul}#  NodeGroup: {m.name} \n{ul}\n"
                f'group = bpy.data.node_groups.new("{m.name}", "{m.bl_rna.identifier}")\n'
                f'groups["{m.name}"] = group\n'
                f"nodes = group.nodes\n"
                f"links = group.links\n"
            )

        for n in sorted(
            nt.nodes,
            key=lambda n: [n.location.x, n.location.y]
        ):
            pnode(n, dummy)
        if nt.links:
            output("#Links\n")
        for l in nt.links:
            output(
                f"links.new(\n"
                f'    nodes["{l.from_node.name}"].outputs["{l.from_socket.name}"],\n'
                f'    nodes["{l.to_node.name}"].inputs["{l.to_socket.name}"]\n    )\n'
            )

    except Exception as e:
        print("There has been an ERROR")
        print(e, e.__traceback__.tb_lineno)
        return False  # failure

    if hasattr(m, "use_nodes"):
        bpy.data.node_groups.remove(dummy)
    return True  # success

if __name__ == "__main__":
    m = bpy.context.object.active_material
    material_to_text(m)

    text = bpy.data.texts.new(m.name)
    text.write("\n".join(buffer))

Test Run on default "Material" with base color set to Red.  AFAICT Generates the material in test file linked Ok.
import bpy
groups = {}  # for node groups

#--------------------------------------------
#  Material: Material
#--------------------------------------------

mat = bpy.data.materials.new("Material")
mat.use_nodes = True
node_tree = mat.node_tree
nodes = node_tree.nodes
nodes.clear()
links = node_tree.links

node = nodes.new("ShaderNodeBsdfPrincipled")
node.location = (10.0, 300.0)
node.inputs["Base Color"].default_value = (1.0, 0.0, 0.0, 1.0)

node = nodes.new("ShaderNodeOutputMaterial")
node.location = (300.0, 300.0)

#Links

links.new(
    nodes["Principled BSDF"].outputs["BSDF"],
    nodes["Material Output"].inputs["Surface"]
    )

Revision
Unlike Madonna and @Gorgeous not so much of a "Material Guy".  TBH I'm a sub-feather-weight when it comes to blenders materials and nodes, so this was a nice little excersize for me.
Ultimately the idea, as I see it,  is to be able to copy a material via a script in one blend, and re-create it in another.
Default Values.
Have kept the verbosity down a bit by not outputting default values. Could turn this off with a flag.  Since non-default values are determined from a newly instanced copy they will be non-default at time of creation. As noted if the defaults change, will need to run script again.
Node Groups
Prior handled a  group node by simply pointing the node tree  to its bpy.data.node_groups item. Instead this version makes a copy of each node group used in the material. Was a very easy step, since nodes of both is a collection of nodes. To make sure the new group is used in the generated material by means of  a dictionary groups  to associate new with old name
groups = {}  # for node groups

#--------------------------------------------
#  NodeGroup: NodeGroup.001
#--------------------------------------------

group = bpy.data.node_groups.new("NodeGroup.001", "ShaderNodeTree")
groups["NodeGroup.001"] = group

could turn this on or off to use existing node groups.
Curves and Ramps.
Wired it up to generate mapping and colorramp nodes.  Used foreach_set which enables to add an arbitrary point for each extra (over default) and set from a list.
Color Ramp
node = nodes.new("ShaderNodeValToRGB")
node.location = (-345.2741394042969, 142.6455841064453)
node.parent = nodes.get("Frame")
ramp = node.color_ramp
for i in range(4):
    ramp.elements.new(0.0)
ramp.elements.foreach_set(
       "position", [
        0.0,
        0.25,
        0.45396339893341064,
        0.6530487537384033,
        0.7999999523162842,
        1.0
        ])
ramp.elements.foreach_set(
       "color", [
        0.0, 0.0, 0.0, 1.0,
        0.41859403252601624, 0.000635193195194006, 0.0, 1.0,
        0.0, 0.006493096239864826, 0.21146051585674286, 1.0,
        0.14895662665367126, 0.17292265594005585, 0.2819954454898834, 1.0,
        0.5389295816421509, 0.18324723839759827, 1.0, 1.0,
        1.0, 1.0, 1.0, 1.0
        ])

RGB Curve
node = nodes.new("ShaderNodeRGBCurve")
node.location = (211.58743286132812, 275.4912414550781)
node.parent = nodes.get("Frame")
map = node.mapping
map.tone = 'FILMLIKE'
map.clip_max_x = 0.8999999761581421
for i in range(5):
    map.curves[0].points.new(0.0, 1.0)

map.curves[0].points.foreach_set(
       "location", [
        0.0, 0.0,
        0.15146341919898987, 0.4256756901741028,
        0.24731720983982086, 0.7837838530540466,
        0.4675609767436981, 0.5506754517555237,
        0.5421952605247498, 0.8445945978164673,
        0.6585365533828735, 0.5608108639717102,
        1.0, 1.0
        ])
for i in range(2):
    map.curves[1].points.new(0.0, 1.0)

map.curves[1].points.foreach_set(
       "location", [
        0.0, 0.0,
        0.3512195348739624, 0.6621621251106262,
        0.5926830172538757, 0.3581080138683319,
        1.0, 1.0
        ])
for i in range(3):
    map.curves[2].points.new(0.0, 1.0)

map.curves[2].points.foreach_set(
       "location", [
        0.0, 0.0,
        0.16463413834571838, 0.581081211566925,
        0.5004880428314209, 0.5777024626731873,
        0.7858536243438721, 0.28378361463546753,
        1.0, 1.0
        ])
for i in range(1):
    map.curves[3].points.new(0.0, 1.0)

map.curves[3].points.foreach_set(
       "location", [
        0.0, 0.0,
        0.6782926321029663, 0.4425675868988037,
        1.0, 1.0
        ])

Frames
Added  the frames and set as parents to respective nodes, haven't wired up re the location changing, as demonstrated by @Gorgeous.

Very nice .....

Nice !! I was scratching my head and found only hacky workarounds, I knew there was a pythonic way to handle it :) Definitely stealing that for the future !

What happened to rna_xml that you you referred to in ancient history? Or would that and/or other lower-level ways of stashing data-blocks. not count for this question?

@RobinBetts had a better check that moment on re-visiting  that 6yo answer (be a lot less ancient myself if i was 6yo at the time...)  Fortunately OP has phrased the question well --> to create something akin to https://blender.stackexchange.com/questions/65129/how-do-i-create-a-script-for-geometry-i-create  whereas the rna_xml , to me, feels more similar to importing / exporting.   (subtle, but different enough?, thoughts)

I'd rather shovel hunks of bits around, avoiding even  object-description formats, if I knew how.. but I think you're right. @brockmann must have his reasons.

@batFINGER This evolved in quite the nifty script :)

Missed this, Thankyou. @Gorgious it suffers from many problems when compared to yours.  Chop, chop add groups to your answer.

@batFINGER Hmm yes that's insufferable alright ! I'd return the favor though, I think it would be accommodated better on your script, I really like the style, it's like reading a piece of poetry but for computers ^^ I don't understand all of it but I know magic when I see it :p while mine is a hodgepodge Frankenstein monster with mud on its boots

I wrote this script a few months back for a personal project. You can see that it's a lot longer than the other answer :).
It creates statements to set the value of a node input or output, even if it is the same as the default value. I debated it, and despite leading to text files with a very high number of lines in big node trees, I prefer this option. Since the goal of this script is to create a snapshot of the material, and the defaults of today might not be the defaults of tomorrow, or of someone else's custom build, I prefer still writing explicitly all properties.
It could still be changed by the user if they want to, by implementing the proposed solution of python magician @batFINGER for not overwriting default values.
You'll need to learn how to use a script.
How to use :
Select your object, select the material you want to copy, run the script. The material code will be added in a new text block.

"""
This scripts "serializes" the active material of the currently selected object
And creates a script readable by the Blender API to recreate said Material.
As any Blender script, it is free to use in any way shape or form.
V 1.1 - 20.10.23
Fixed NodeSocketVirtual error
"""

import bpy

from bpy.types import (
    NodeSocketShader,
    NodeSocketVirtual,
    NodeSocketVector,
    NodeSocketVectorDirection,
    NodeSocketVectorXYZ,
    NodeSocketVectorTranslation,
    NodeSocketVectorEuler,
    NodeSocketColor,

    NodeReroute,

    Object,
    Image,
    ImageUser,
    Text,
    ParticleSystem,
    CurveMapping,
    ColorRamp,

    ShaderNodeTree,
)

from mathutils import Vector, Color

ERROR = "~ ERROR ~"

def get_link_statement(link):
    """
    Build the statement to re-create given link
    """
    return f"""\
links.new({link.from_node.path_from_id()}.outputs[{get_socket_index(link.from_socket)}]\
, {link.to_node.path_from_id()}.inputs[{get_socket_index(link.to_socket)}])\
    """

def value_from_socket(socket):
    """
    Returns the evaluated value of a node socket's default value
    """
    # A Shader socket (green dot) doesn't have a default value :
    if isinstance(socket, (NodeSocketShader, NodeSocketVirtual)):
        return ERROR
    elif isinstance(socket, (
            NodeSocketVector,
            NodeSocketVectorXYZ,
            NodeSocketVectorTranslation,
            NodeSocketVectorEuler,
            NodeSocketVectorDirection)):
        return f"{[socket.default_value[i] for i in range(3)]}"
    elif isinstance(socket, NodeSocketColor):
        return f"{[socket.default_value[i] for i in range(4)]}"
    else:
        return socket.default_value.__str__()

class NodeCreator:
    """
    Helper class to programmatically recreate the passed node
    """
    # These props are internal or read-only
    # and aren't useful in the serialization.
    default_props = (
        "dimensions",
        "draw_buttons",
        "draw_buttons_ext",
        "input_template",
        "inputs",
        "internal_links",
        "isAnimationNode",
        "is_registered_node_type",
        "output_template",
        "outputs",
        "poll",
        "poll_instance",
        "rna_type",
        "socket_value_update",
        "type",
        "update",
        "viewLocation",

        "texture_mapping",
        "color_mapping",

        "filepath",

        "cache_point_density",
        "calc_point_density",
        "calc_point_density_minmax",

        "interface",

        "height",
        "show_options",
        "show_preview",
        "show_texture",
        "width_hidden",
    )

    def __init__(self, node):
        """
        Initialize the node inputs and outputs,
        and the different fields' default values
        """
        self.node = node
        self.input_default_values = []
        self.output_default_values = []
        if not isinstance(node, NodeReroute):
            for _input in node.inputs:
                self.input_default_values.append(value_from_socket(_input))
            for output in node.outputs:
                self.output_default_values.append(value_from_socket(output))

        self.type = type(node).__name__
        self.properties = []  # Could use an ordered dict instead.
        for prop_name in dir(node):
            if prop_name.startswith("_") or prop_name.startswith("bl_"):
                continue
            if prop_name in NodeCreator.default_props:
                continue
            self.properties.append((prop_name, getattr(node, prop_name)))

    def statements(self):
        """
        Build the chain of statements to programmatically recreate the node
        """
        statements = []
        statements.append(f"new_node = nodes.new(type='{self.type}')")
        self.properties = sorted(self.properties, key=lambda p: p[0])
        for prop, value in self.properties:
            if isinstance(value, ImageUser):
                statements.append(f"""\
img_text = new_node.{prop}
img_text.frame_current = {value.frame_current}
img_text.frame_duration = {value.frame_duration}
img_text.frame_offset = {value.frame_offset}
img_text.frame_start = {value.frame_start}
img_text.use_auto_refresh = {value.use_auto_refresh}
img_text.use_cyclic = {value.use_cyclic}
img_text.tile = {value.tile}\
                """)
                continue
            if isinstance(value, ParticleSystem):
                # /!\ Make sure this is executed after node.object statement
                statements.append(f"""\
if new_node.object:
    new_node.{prop} = new_node.object.particle_systems.get('{value.name}')
                """)
                continue
            if isinstance(value, CurveMapping):
                statements.append(f"""\
map = new_node.{prop}
map.clip_max_x = {value.clip_max_x}
map.clip_max_y = {value.clip_max_y}
map.clip_min_x = {value.clip_min_x}
map.clip_min_y = {value.clip_min_y}
map.tone = '{value.tone}'
map.use_clip = {value.use_clip}\
                """)
                # Remove the 2 starting default points and only these :
                for i, curve in enumerate(value.curves):
                    statements.append(f"map_c = map.curves[{i}]")
                    for point in curve.points:
                        statements.append(f"""\
map_c.points.new({point.location[0]}, {point.location[1]})""")
                    statements.append("""\
removed_start = removed_end = False
for i in range(len(map_c.points) - 1, -1, -1):
    p = map_c.points[i]
    if not removed_start and p.location[0] == map.clip_min_x and p.location[1] == map.clip_min_y:
        map_c.points.remove(p)
        removed_start = True
    if not removed_end and p.location[0] == 1 and p.location[1] == 1:
        map_c.points.remove(p)
        removed_end = True\
                    """)
                statements.append(f"map.update()")
                continue
            if isinstance(value, ColorRamp):
                statements.append(f"""\
cr = new_node.{prop}
cr.color_mode = '{value.color_mode}'
cr.hue_interpolation = '{value.hue_interpolation}'
cr.interpolation = '{value.interpolation}'\
                """)
                for stop in value.elements:
                    statements.append(f"""new_stop = cr.elements.new({stop.position})
new_stop.color = {[ch for ch in stop.color]}""")
                # Remove the 2 starting default stops and only these :
                statements.append("""\
removed_black = removed_white = False
for i in range(len(cr.elements) - 1, -1, -1):
    stop = cr.elements[i]
    if not removed_black and stop.position == 0 and all([stop.color[i] == (0, 0, 0, 1)[i] for i in range(4)]):
        cr.elements.remove(stop)
        removed_black = True
    if not removed_white and stop.position == 1 and all([stop.color[i] == (1, 1, 1, 1)[i] for i in range(4)]):
        cr.elements.remove(stop)
        removed_white = True\
                """)
                continue
            if isinstance(value, ShaderNodeTree):
                statements.append(f"""\
ng = bpy.data.node_groups.get('{value.name}')
if not ng:
    new_node.label = \"Missing Node Group : '{value.name}'\"
else:
    new_node.{prop} = ng\
                """)
                continue

            if prop in ("hide", "mute", "use_custom_color"):
                if value:
                    statements.append(f"new_node.{prop} = {value}")
            elif prop == "text" and not value:
                continue
            elif prop in ("select", "shrink"):
                if not value:
                    statements.append(f"new_node.{prop} = {value}")
            elif isinstance(value, str):
                if value:
                    statements.append(f"new_node.{prop} = '{value}'")
            elif isinstance(value, Vector):
                if len(value) == 2:
                    statements.append(
                        f"new_node.{prop} = ({value[0]}, {value[1]})")
                else:
                    statements.append(
                        f"new_node.{prop} = ({value[0]}, {value[1]}, {value[2]})")
            elif isinstance(value, Object):
                statements.append(
                    f"new_node.{prop} = bpy.data.objects.get('{value.name}')")
            elif isinstance(value, Image):
                statements.append(
                    f"new_node.{prop} = bpy.data.images.get('{value.name}')")
            elif isinstance(value, Text):
                if value:
                    statements.append(
                        f"new_node.{prop} = bpy.data.texts.get('{value.name}')")
            elif prop == "parent":
                if value:
                    statements.append(f"""\
parent = nodes.get('{value.name}')
if parent:
    new_node.parent = parent
    while True:
        new_node.location += parent.location
        if parent.parent:
            parent = parent.parent
        else:
            break\
                    """)
            elif isinstance(value, Color):
                statements.append(
                    f"new_node.{prop} = ({value[0]}, {value[1]}, {value[2]})")
            else:
                statements.append(f"new_node.{prop} = {value}")
        for i, dv in enumerate(self.input_default_values):
            if dv == ERROR:
                continue
            statements.append(f"new_node.inputs[{i}].default_value = {dv}")

        for i, dv in enumerate(self.output_default_values):
            if dv == ERROR:
                continue
            statements.append(f"new_node.outputs[{i}].default_value = {dv}")

        if not isinstance(self.node, NodeReroute):
            for _input in self.node.inputs:
                if _input.hide:
                    statements.append(
                        f"new_node.inputs[{get_socket_index(_input)}].hide = True")
            for output in self.node.outputs:
                if output.hide:
                    statements.append(
                        f"new_node.outputs[{get_socket_index(output)}].hide = True")
#        DEBUG Print node location as a label :
#        statements.append("new_node.label = str(new_node.location[0]).split('.')[0] + ', ' + str(new_node.location[1]).split('.')[0]")

        return statements

def serialize_material(mat):
    """
    Returns the ordered statements necessary to build the
    Mateiral generation script
    """
    node_tree = mat.node_tree
    statements = [f"""\
import bpy
new_mat = bpy.data.materials.get('{mat.name}')
if not new_mat:
    new_mat = bpy.data.materials.new('{mat.name}')

new_mat.use_nodes = True
node_tree = new_mat.node_tree
nodes = node_tree.nodes
nodes.clear()

links = node_tree.links
links.clear()
    """]

    statements.append("# Nodes :\n")
    for node in node_tree.nodes:
        for st in NodeCreator(node).statements():
            statements.append(st)
        statements.append("")

    if node_tree.links:
        statements.append("# Links :\n")
        for link in node_tree.links:
            statements.append(get_link_statement(link))

    return statements

def write_material_to_text_block(obj):
    """
    Create or overwrite a text block with the same name as the material
    Which contains all the necessary statements to duplicate the material
    """
    if not obj or obj.type not in ('MESH', 'CURVE', 'VOLUME', 'SURFACE', 'FONT', 'META', 'GPENCIL'):
        return
    am = obj.active_material
    if not am or not am.use_nodes:
        return
    statements = serialize_material(am)

    text_block = bpy.data.texts.get(am.name)
    if text_block:
        text_block.clear()
    else:
        text_block = bpy.data.texts.new(am.name)

    for st in statements:
        text_block.write(st)
        text_block.write("\n")

    return text_block

def get_socket_index(socket):
    return socket.path_from_id().split(".")[-1].split("[")[-1][:-1]

if __name__ == "__main__":
    text_block = write_material_to_text_block(bpy.context.active_object)

The code is available there for grabbing
https://github.com/Gorgious56/Material2Script/blob/main/material_to_script.py

Very nice .....

Oops, the system has "auto-selected" the answer for the bounty and only assigned half of the rep. I'm sorry, nothing intended, hope you don't mind... sh*t. I'm going to start another one next week.

@brockmann Haha no problem :) Anyways I think the other answer deserves it more than mine, comparing the two now and my scripts feels really clunky :p

@Exporer Hello, while I understand your proposed edit of my answer, I think it would have made more sense in a comment. As you noticed my answer is limited in regards to the node group creation. I suggest you look into the other answer of this question, which tackles this gracefully. I created this script for my own use back then, and I didn't need to re-create node group so I never implemented it. Feel free to edit it if you find a better solution. Cheers :)


text:
Unwrapping head geometry similar to Epic's MetaHuman Characters?
I'd like to maximize the texture space for a game head model I'm working on.
When following the classic approach on how to unwrap a head (adding a straight line from the back and splitting those seam up into two on the top of the head), I get a lot of holes and loose a lot of potential texture space, even when packed properly:

Initial test using the female base mesh from https://blendswap.com/blend/22220

While doing some research I came across Epic's MetaHuman Creator and I've noticed that their UVs are perfectly squared and filling up the entire UV space. They are heavily stretched on the shoulders but that's perfectly fine for a game character:

I already tried to unwrap the head, pin the center verts and run a cylindrical projection which theoretically should produce a similar result. However, the pins does not stay in place when calling the cylindrical projection operator afterwards and the result is a mess.
Q: What's the trick to get a similar type of UV projection for the head and maximize the actual texture space?

My immediate thoughts are to either use Proportional Editing to pull the edges out and scale them flat (eg, S, X, 0) or to script some kind of solution to pull the island to the edge of UV space, proportionally dragging anything that's connected. I suppose this might require the edges to be marked in some way so the script could know which bits you want on which edge.

Consider  something like https://blender.stackexchange.com/a/93180/15543  find the COG then project  minimum  bounding circle to square. The conformal mapping for example will be best at center and stretched at extents. Suspect this is reason inquired about about UVBmesh script..

Another option is to use 'Pinning'. Select the vertices in the UV map of your original unwrapping along one edge and scale them along an axis to form an evenly spaced line and place them on the edge. Then 'Pin' them. Repeat for other edges. Then unwrap again and the unwrapping algorithm will leave those pinned vertices where they are and unwrap the rest of them taking the pinned positions into account. I guess it all depends on how automated a solution you require.

Thanks @RichSedman, good input. I already tried to unwrap the head, pin the center verts and run a cylindrical projection which theoretically should produce a similar result,  but unfortunately the pins does not stay in place when running the operator. Also there is no control about the seam of the cylindrical projection, which is quite disappointing.

Thanks @batFINGER I think I get your idea, have to investigate though.

Perhaps something like this would be suitable :

This was achieved manually (but the manipulation of the UV could potentially be automated) from the female base mesh mentioned, using the following steps :

In Edit mode, select the whole mesh and Clear Seams. Mark the back of the head seam as suggested.

In the UV editor, select all and 'unpin' all vertices (the downloaded mesh already included some pinned vertices). Perform a basic 'Unwrap'.

In the UV editor, re-position and straighten the island. Select all the bottom row of vertices.

Scale to zero in the Y axis (SY0Enter). Move and scale them along the bottom edge of the UV space (G and S). 'Pin' them (P).

Select the left-hand edge. Rotate them so they are close to vertical.

Scale to zero in the X axis. Position, scale and 'Pin' them in place along the left-hand edge of UV space (as for bottom row).

Repeat on the right-hand vertices.

Perform another basic 'Unwrap'

It would be feasible to script some of these actions (so you could potentially select an edge of vertices and then have an operator to automatically position and scale them along an edge).
Note that the 'basic' Unwrap function takes account of the 'pinned' vertices, leaving those in position and unwrapping the mesh with those restricted. However, some of the other unwrap functions (such as Cylinder, Cube, Sphere) ignore the pinned vertices and so cannot be used for this.

EDIT: Removing the 'T' from the forehead and unpinning a few vertices down the edge, then Unwrap again produces this - which looks pretty close to your example :

Thanks Rich! Tested the whole day based on your answer. I even get less distortion when pinning the face too and unwrap the other parts over and over again. I think we are pretty close. Automating the process isn't necessary, thanks. Demystifying the process will be perfectly fine.

Fantastic. Glad I could help.

@brockmann Let me know if there is anything else I can do to improve this answer.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Blending two procedural "reptile-scale" textures - at scale edges
I'm creating procedural creatures with procedural "dragon-skin" or "scales" textures (based on Voronoi texture nodes).
I want to blend multiple of these procedural textures together. However, I don't want a linear blend, instead I want the textures to end exactly where a scale of the first texture ends, so that it looks like these scales lie above the other texture.
Here's what I have so far:

As you can see, the two textures are blended (currently I use a vertex color to influence the blending and to control how the gradient flows along the body). However, instead of blending linearly within the (dragon-)scales of the texture, I want the darker scales to be fully opaque... until some threshold, at which they are fully transparent. This will lead to a "jagged" transition line (because some scales end earlier and some end later).
My idea is to replace the current gradient with a gradient-texture that gets the Voronoi's "position" vector as input. That gives me a grayscale texture where each of the scales has a different color. However, then this color does not increase/decrease in the same direction as my original gradient (i.e. the gradient will no longer be a controlled gradient across the side of the creature's body)...
Edit: This is roughly the effect I want:

Edit2: Here's an example .blend file:

Note that the gradient comes from a vertex attribute (vertex color) called "ring_pos". Visualizing this gradient gives you something like this ("ring_pos" encodes the position of the vertex within its "ring" of vertices, allowing me to have a different texture on the top than on the bottom. This is just a simple example, I want to add more complex patterns later, but in any case they should be encoding where I want one texture to show and where I want the other to show. There's no guarantee that these values will for a simple gradient later on.)

When sampling (as suggested in the comments) a gradient texture with the Voronoi's position, I get something that I can use as a mask:

However, this is in the wrong space, i.e. the wrong parts of the model are bright.

You should do something with UVs. Scaling UVs in one side may help. working with textures most probably fails.

You could use the 'Position' of the Voronoi to look up the value of the gradient, and mask according to whether the looked up value passes a threshold.. it depends how your gradient is generated. Is the gradient procedural, or a UV texture?

Hello, interesting question.  I think I need an additional angle to understand the mesh.

@MohammadHosseinJamshidi I don't understand your comment, sorry. There are no UVs involved...

@RobinBetts Yes, that would be perfect. However, the gradient is created procedurally and stored on the mesh as vertex colors and I don't know how to combine that with the gradient texture (the voronoi and gradient is in another, arbitrary space). Even if I had UV coords, how would that help?

@Germanunkol I mean where you need the texture to be bigger, you should scale down UV's. They should be more compact compared to where you need the texture to be smaller.

@AllenSimpson I added a .blend file and more explanation, maybe that helps?

@MohammadHosseinJamshidi Ah, now I understand, thanks. Sorry, that's not an option either because the two textures may be entirely different ones in the future. So they're not the same type that I can just scale differently. Also, that would still give me some sort of gradient, which I don't want - I want the gradient to be replaced by something like a mask.

@Germanunkol are you using EEVEE? We need something, given P, will return the vertex color at P. Maybe via  Shader to RGB? Or, would it be OK to bake the vertex color to a UV map?

@RobinBetts All I need in the final result is to bake diffuse (and maybe specular) to an image for export and usage in a game engine. Beyond that, I'm open to any renderer etc. Yes, I think it's EEVEE atm. Could you explain how shader to color would help here? What would I render in that shader? If I render the vertex color, don't I end up with the same thing as using the vertex color directly? I.e. how do I sample the color output from the shader-to-RGB node at point P?

@Germanunkol You're right. I was having a brainf**t.

In principle, whatever space is being used to generate your mask or gradient, use the same space to generate the masked scales, and the mask for the masked scales.
Here, the mask is a function of Object space, (shown on the left, below.) It might have been coordinates in UV space, looking up into an image texture, whatever. So long as the same space is used to generate the scales, it can also be used by the 'Position' of a parallel Voronoi (same type, scale, randomness) to generate a per-cell mask.

These are the nodes for the textured example on the right..

If, for some reason, you can't use the same space for the gradient and the scales, you would have to be able to map one space to the other, somehow. That would depend... If I've missed the point, and that's your question, maybe share your .blend, so we can have a go.

Mapping between the spaces will be very hard. The sample with the gradient above is a relatively simple one (later I want the vertex colours to describe more complex features like which part of a leg something belongs to etc.) and then merge textures accordingly. I think the best way might be if I could use the Voronoi's "position" to look up the vertex colours at the vertices somehow?
P.S. Thanks for the sample pictures - it's exactly what I'm going or, except for the problem with the "gradient" being in the wrong space.

Can I maybe interpolate the vertex colors into a 3D image texture (which is as large as the model) and then sample that texture using the Voronoi's position?

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
ensure_lookup_table creates indices in random order?
I have a python script that creates a sphere, then randomly selects a face and extrudes it.
This creates new geometry and deletes the old geometry, so I need to call bm.faces.ensure_lookup_table.
When I set the random.seed to a fixed number, I expect the same mesh to be created every time. However, the resulting new indexing does not seem to be consistent, so the first few extrusions are the same every time, but later extrusions happen at different faces every run.
Note that if the number of extrusions is low enough (20, for example), the mesh is always the same. I believe this is because in this case it always finds original faces where the indices are consistent.
MWE:
import bpy
import random
import bmesh

random.seed(3)

scene = bpy.context.scene

# Create an empty mesh and the object.
mesh = bpy.data.meshes.new('RandomMesh')
object = bpy.data.objects.new("RandomMesh", mesh)

# Add the object into the scene.
scene.objects.link(object)
scene.objects.active = object
object.select = True

# Construct the bmesh sphere and assign it to the blender mesh.
bm = bmesh.new()
diameter=random.uniform(0.05,0.15)
print("diameter", diameter)
bmesh.ops.create_icosphere(bm, subdivisions=2, diameter=diameter)
bm.to_mesh(mesh)

# Extrude the mesh a certain number of times:
extrusions = 40
print("extrusions",extrusions)
bm.faces.ensure_lookup_table()
bpy.ops.object.mode_set(mode='EDIT')
for i in range( 0, extrusions ):

    # Deselect everything
    for v in bm.verts:
        v.select = False
    bm.select_flush(False)

    # Choose a random face
    id = random.randint(0, len(bm.faces)-1)
    print("id",id)
    face = bm.faces[id]
    face.select_set(True)

    # Extrude the selection
    selection = [f for f in bm.faces if f.select]
    extruded = bmesh.ops.extrude_face_region(bm, geom=selection)
    vec = -selection[0].normal*0.05
    # Delete previous faces
    bmesh.ops.delete(bm, geom=selection, context=5)
    # Move the new faces outpaaaawards:
    verts = [v for v in extruded['geom'] if isinstance(v, bmesh.types.BMVert)]
    bmesh.ops.translate(bm, vec=vec, verts=verts)

    bm.faces.ensure_lookup_table()

bpy.ops.object.mode_set(mode='OBJECT')
bm.to_mesh(object.data)
bm.free()

I'm using Blender 2.79.


text:
How to extrude a wall by specific length and at a specific angle?
I would like to extrude a section of a thick wall, but be able to specify:
a) how far the wall is extruded,
b) the exact angle that it comes off at,
c) have the extruded wall be the same thickness as the original bit (and be a consistent thickness all the way).
The picture below tries to show what I would like to learn how to do:

I have tried extruding and then trying to rotate the new surface, and trying also to do it with the shear tool, but it always seems to end up not fulfilling either a),b) or c) above.
Thanks

Take a look at the "Solidify" modifier.

@Zyzio how does it help? (Given that I want to start from the shape shown)

You can simplify the base shape and let Solidify create the thickness for you.  Saves you having to fiddle with the extra verts and you won't accidentally make something non-planar

If you want the angle to be something different from 90º or 45º and you need the exact length of the exterior to be something specific and you don't want to be changing the transformation orientation then I would install the Tiny CAD addon. It lets you create a vertex where 2 edges intersect.
https://youtu.be/O-0sIgSCiDM
With that, you can select the face you want to extrude and duplicate it first, then rotate it using one of the outside vertices as the pivot and then extrude it along it normal. This gives you complete control on the length of the wall.
This will leave you with 2 wall sections that are intersecting. You can now select one of the pairs of edges that are intersecting at the top and bottom and use Tiny CAD to place a vertex where they do. Then merge the ends of those edges into the newly created vertex. Repeat this for the bottom and/or any other edge loops the wall has.
This leaves you with the unchanged thickness and the controlled length of extruded segment. But it also creates some interior faces and overlapping vertices so when you are done, select and delete the interior faces, merge all vertices by distance and recalculate the normals.
On another note, if you don't care about precision that much and only need it to 'look' right you can use the Shear tool in the tools bar to rotate the edgeloop in the middle until it looks right

Worked nicely, gives complete control over length and angle

How did you activate the labels in your video, which show the dimensions?

In edit mode, in the Viewport Overlays (Top right of the screen next to the Toggle X-Ray button). There's check boxes at the bottom for lengths and angles

here is a way to do it:

be aware that i set the pivot point to 3d cursor and the snapping to

i set the cursor already on the upper vertex where i want the rotation to be.
Then i double the face (face select, shift-D, return)
Now you can press R (angle you want) return
E -> extrude as long as you want the wall to be
Change to Normal as transform orientation and check snapping,
select the two vertices as you can see in the gif, subdivide, then select middle vertex and press G Z and move your mouse to the edge as i did in the gif
do the same for the two lower vertices
of course you then have to create the faces - but i hope you know how to do that.

Hi Chris, thanks for your answer. I am able to follow your approach up to when you subdivide the edge to get the new vertex. I have a problem with the step when trying to move that vertex backwards, so that it snaps to one of the edges. When I press G + Z (with normal transform orientation enabled), my vertex does not move constrained nicely to the axis shown in your GIF, but instead moves along some other (random as far as I can see) axis. Do you know what could be going wrong?

i don't know how familiar you are with snapping - i must admit that i hated it at the beginning and i had no idea how it worked. But after some month, i got more familiar with it. did you check whether you really have the same snapping settings as i do? i go with the cursor right to the upper long edge of the right cube - then it snaps right.

One way to do it with the built-in tools.  Start with a plane and extrude one edge out using the number keys or the operator pane in the bottom left to define the length of the new face.
Select one of the 'hinge' vertices and use the F3 search function to move Cursor to Selected.  Then you can change your pivot point to cursor and rotate the new face around the cursor, again defining an amount with number keys or the operator pane.

Anyone can edit this, I'm on my phone and can't craft a great answer


text:
Converting Bezier shape into mesh with nicer topology
I have an SVG image of a letter "t" (contains some curved and some straight segments), which has been imported to Blender. After the import, everything is nicely defined as Bezier curves.
Next I want to create a mesh object from this (with the ultimate goal being to try to animate the letter eventually). I have tried using the "Convert to Mesh" command, which results in many triangles and poles. Using the "Decimate" and "Remesh" modifiers also doesn't lead to good results:

How can I create some nicer mesh topology from this Bezier object (with the ability to add a well-behaved Subdivision Surface modifier as well in the end) ?
File here:

actually it all depends on what you want to do afterwards, you're talking about animation, what animation do you want to achieve?

@moonboots I'd like to be able to do some squash and stretch (to make it look like it jumps). I'd also like to bring the two arms of the "t" forwards (to make it look like it is picking something up).

As you're talking about animation, you could create this kind of topology, which will allow to easily move the parts, rig it and add a Subdivision Surface modifier:

I see.  Did you use Convert to Mesh as a first step, then delete lots of stuff? And then add in extra edges using Knife Tool? Can you explain your approach to making this? Thanks!

Convert to Mesh then some J (join) between the vertices of the opposite edges, Ctrl R to add edge loops along the outer edges to keep the angles sharp...


text:
How to morph one shape into two separate ones
Is there a way to animate one shape splitting into two separate ones? For example, in the scenario below I have one mesh which is just a cube, and another mesh which is two ellipsoids that are spatially separated. I would like to cube to morph into a double ellipsoid shape. (The number of vertices in each mesh are not equal).

I have seen some solutions for morphing by using shape keys (which requires the same number of vertices), or by using duplicating the shape and using shrinkwrap (which works when you don't need to split into two objects).

what woul be the intermediate shapes between the cube and the 2 ellipsoids?

@moonboots. I don't have a specific intermediate shape in mind. Just something which makes the transition look smooth. For example, the cube should first become rounded, then split, then the remaining shapes should gradually become elongated.

You could begin with a cube that morphs into an ellipsoid with a shape key, then replace the cube with 2 metaballs (I just moved the cube away from the view and moved the metaballs into the view) that have the same shape and location. At last split the 2 metaballs and scale them down:

This looks great... thanks! Can you add more detail about how you did the animation of moving the cube out and the metaballs in? Is it an instantaneous change from one frame to the next? With no interpolation?

You could keyframe its visibility (Object panel > Visibility) but I just moved it away from the camera view, so just 2 location keyframes, same for the metaballs


text:
How to make an object cut out which follows the general outline of this array?
I have this array of bars, which is created by using an array modifier and then a curve modifier. Note that each bar is tilted backwards by 10 degrees.

I would now like to add a few new pieces at different heights, such that they follow the general shape of the array of bars, like this:

How can I do this?
Things I tried, but didnt work:

Trying to use a boolean modifer to cut out the shape.
Trying to use knife project.

(Note, what I currently have was actually created by using "instancing" on each face of a helper plane, which prevents each bar from deforming.)

Can't you use the curve? It (or a copy of it) can be extrude in the properties panel or with Geometry Nodes.

@Blunder I need to somehow extract what the correct radius of curvature is, depending on the distance from the top. The curve shown is only the correct radius for the very top position. Further down from the top I would need a curve with a different radius of curvature.

That's true. But since you have the top and bottom arcs you can interpolate the radius. I guess you want something like this (https://i.sstatic.net/GrWH6wQE.jpg)?

@Blunder yes exactly. How did you do it? How to automatically give the central bands the correct radius?

Since you have a top arc and a bottom arc, you can use them to create a copy that interpolates the positions of the control points so that the new arc appears between them. In other words: the control points' position is mixed between the top position and the bottom position. The factor thus determines the height of the new arc. It's similar to a shape key.

The Mix node (1) mixes the positions of the two arcs (2) and (3). You can define them and the Factor in the modifier's setting (4). The labels of the Group Input node can be changed in the side panel of the Geometry Nodes editor (press key N with the mouse in the editor to open it).
The Set Position node (5) adjusts the position of the control points with an offset along the Normals (7) so that the rails are in front or behind the slats.
With Curve to Mesh (6) you can give the new arc some geometry. Of course, you also could instance other objects on its points, similar to the Array and Curve modifiers that you use.
The material (8) must be set by a Set Material node. If you drag it to a Group Input node you can define the material in the GN modifier settings (4).
For some reason I don't know, the Top Arc curve is considered a mesh and not a curve. It's a curve in the outliner, but it can be converted implicitly to a mesh when it has shape keys, or in the Properties > Geometry section the Bevel/Extrude settings are used. That's not the case here, but Blender still complains that the Top Arc is a mesh, while the Bottom Arc is a real curve. (If there is an error you will see a little (!) in the top right corner of the node. Hover it to see the error message.). That's why we use the Mesh To Curve node (9) to ensure that the curve is really a curve and has not been implicitly converted to a mesh for some reason.

Nice answer. I appreciate your detailed explanation, thank you. I was thinking there might be a modifier that works directly in such a situation ("shrinkwrap" or "surface deform" sounded like they might be appropriate). But geometry node is so much more powerful.


text:
Problem with screw modifier
I am trying to make a rope with the circle mesh.
First I added an array modifier to the circle, then I added a screw modifier.
[]

I was following a tutorial on youtube. Anyone else have this problem?

It looks like the origin of your object is in the center of one of the circles. Move the whole mesh (in edit mode) so that the origin (the little orange dot) is in the midpoint between all of the circles.

Thanks, Christopher that worked!


text:
I Need Sharp Edge And Have Problems With Redirecting Edge Flow
After sub d I get no sharp edge but I think on that side must be sharp, can you help me with edge flow?

could you please highlight precisely the part that should be sharp and share your file? https://blend-exchange.giantcowfilms.com/

i add extra img with red circle and here is link of blender file

I think this topology works:

I beveled these edges and rearranged a bit all around:

Here is what it gives with the Subdivision Surface modifier:

Previous shape:

THANKS MAN. i will try, what u think generally about my topology on that shape i am very beginner in 3d modeling

a bit messy but not too bad, but this part was difficult imho

I've corrected because I forgot the sharp angle that goes horizontally on the right


text:
Texture is black and won’t change

I’ve been watching “Blender Guru” make a donut and following. I first made my texture paint fine, but when I did the displacement something went wrong. I don’t remember why, it just turned black.
I went to redo my texture paint and now it’s just black. No matter what I do, my paint won’t show and it is only black.
Also, this might help more. I did change the blend in texture painting and I could paint on it. But it was the cloud texture. I tried to change it, but now I can’t paint anything on it.

Do you have a light in the scene?

I do have a light

Share some screenshots of your setting or even share your Blend File

I got it to work. I did this by starting over from a few steps back. There was a mask texture on it, and I deleted it. Then it worked

I had the same problem too, but I fixed it by following the instructions to this answer. Here are the steps:
1. In the Texture Paint tab, press N, and click Tool on the right side-bar.
2. Under Brushes click the X button to delete the brush, then add a new brush.
3. Then select a colour under Brush Settings, go to the Colour Picker dropdown, and then draw over the object.
I hope this works for you.


text:
How to set Ctrl+MMB to Orbit?
How do i set my MMB + Ctrl to orbit. What is the hotkey term in keymap settings?
Very much grateful for any suggestions, Stewart

Just be aware that the Ctrl+MMB is already used for the zoom, so you may want to change that as well or deactivate in the meantime.

The shortcut for rotate view can be changed in user preferences. Assuming you are using 2.8 keymap, see the gif below:

Open user preferences.
Go to keymap section and search for rotate view to middle mouse in key binding.
Then you may simply change the shortcut for Ctrl + MMB from the default
MMB

thanks tim, that works very well:) do u think its possible to click RMB to rotate instead and try in keymap but it just disappears the feather from list?


text:
Mirror modifier without seam
I'm using mirror modifier with merge and clipping enabled to create a very low poly model. Generally - every single triangle counts. I'm also a newbie, so this question might be stuipid.
Is there a way to use mirror modifier so that it DOESN'T create new vertexes at the point my model and mirrored parts merge? I know they are needed in most cases, but in my it's just extra work to remove them.

The merge option means that vertices at the centre don't get duplicated, only the vertices away from the merge line get duplicated across. Do you mean your getting faces through the mirrored line? An image or two may help clarify.

AFAIK, no. The best you can do is delete the edge loop after applying the modifier. You could try the Snap to symmetry tool, but it's a lot less convenient than using the mirror modifier.

Assuming you mean by seam an edge loop like the one selected in this image (along the y-axis).

Once you have applied the mirror modifier you could:

Select the edge loop Ctrl-RMB
Delete edge loop X

I wouldn't recommend to apply the modifier since you couldn't apply symetrical changes as easy as before. IMHO it's not worth to sacrifice editability for saving a few faces.

Well, deleting all the edge loops produced is pain, but it seems that there isn't any other way. And sadly, thanks to some weirdnes in performance, removing edge loops gives me a very decent boost to performance.

@madziorek15 I thought you only want to remove the edge loop along y-axis, removing more of them would decompose your geometry. Game engines render millions of triangles, so you shouldn't be worried about a few faces.

Well, not this one sadly, it's streaming content through net and sadly it all counts. To give you impression - removing all edge loops gave me about 6 times less cost to stream it.

@madziorek15 what do you mean 'all' the edge loops? It's just 1 single loop around the middle.

if you have a joint mesh yes, but my model is in quite a lot of parts

@madziorek15 In that case, my idea for you is: Select those "border" vertices BEFORE applying the Mirror modifier. After applying, Tab into Edit Mode, you'll see that all the vertices are already selected. :) Just keep that selection unchanged, then simply X > Edge Loop (or Dissolve Edges) to delete them all. Tip for quick selection on border: Ctrl Shift Alt M when in Vertex / Edge Select mode. (Suppose the openings of your model are where will be merged by Mirror Modifier)

I had a similar problem it took a while but I figured it out, my mesh seemed to split in the middle when I applied a multires modifier.  I found that when I turned off the mirror modifier for some reason when I had done an edge loop cut and slide it had added faces to the loop edge that was my clipping so when ever I was applying the mirror it was confused because the edge loop it was supposed to merge had faces.  Turn off the mirror and if the side you want to merge has faces delete them and all will be good. (Tthe side you want to merge is the side you can't see when the mirror mod is on.)

I don't understand what you are writing here. Please use shorter sentences and try to be clearer.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Bokeh defocus not working on certain frames
I'm currently working on a short animation (Blender 2.69 r60995) for an expo and i'm having a problem with bokeh defocus that it isn't composition on some frames, here's a gif clip:

As you can see, the defocus is working right, but certain frames don't get composited (the compositing pass doesn't even show up).
Here are my compositing nodes:

I have toggled "Use Z-Buffer" several times and the fStop, also tried not to use the Z-Buffer, and the problem is always the same, certain frames don't get rendered.
EDIT: Here's the defocus keyframe graph.

I see that there is some keyframe(s) on the "Max Blur" parameter (it's green). Are you sure this value is not at 0 for the concerned frame ?

Indeed the blur is animated and it got only 2 keyframes: One at the beginning when nothing is blurred and another one when the camera zooms in to the subject and defocus everything else. There are no extra keyframes.

OK, and I saw on your GIF that it was frames 3, 6 and 13 that are not blured. Quite strange. Did you tried disabling the Max Blur animation, and fix it to 8.0 (just to see if it works well) ? Oh, and another thing: is it every time the same frames that are not computed ?

The weird thing is that i have another scene with perfect bokeh defocus. Will check if removing the animation works.

Looks like it was that issue. Thanks Polosson.

Can you answer your question ? Please explain how your resolved the issue in detail. Thanks!

I noticed some changes to the defocus node on developer.blender.org yesterday. Can you try with an updated build and see if the problem persists?

I'm going to try, because the problem has persisted. Will report back when done testing. Although the diff is an angle related thing :-(

If this has been resolved, please post the solution as an answer to get this off of the unanswered list.

No, it wasn't answered, i went along with the horrible bokeh jumping... the event for what this was intended flopped, so it was a non-issue.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
How to render in cycles volume with camera inside
I know there were tricks like cutting inside the volume object with another object with boolean modifier (this one I'd like to avoid) and another with putting the camera inside some sort of a bubble with inverted normals. The latter is the one I'd like to use, however I can't set it up properly.
Does the "bubble" object need some specific material or is there something more I need to know? Or that doesn't work anymore?
Well, seems like there is a fix on the way, as pointed out:
https://developer.blender.org/D794

Is this a volume with a surface BSDF, or is this a 2.7.0+ volumetric shader?

2.7.0+ volumetric shader.

A patch is in the works to do camera inside volume rendering. See this test render There is a link that leads to the patch if you want to build your own early test version.

Yes, I've seen the news today! So the issue is resolved thanks to the devs.

What's wrong with the boolean modifier trick?

It's not elegant. Also with specific scene setup it might be visible.

Update
Camera in volume is now natively supported as of 2.73:

Cycles: Add support for cameras inside volume
Basically the title says it all, volume stack initialization now is
  aware that camera might be inside of the volume. This gives quite
  noticeable render time regressions in cases camera is in the volume
  (didn't measure them yet) because this requires quite a few of
  ray-casting per camera ray in order to check which objects we're
  inside. Not quite sure if this might be optimized.
But the good thing is that we can do quite a good job on detecting
  whether camera is outside of any of the volumes and in this case there
  should be no time penalty at all (apart from some extra checks during
  the sync state).
For now we're only doing rather simple AABB checks between the
  viewplane and volume objects. This could give some false-positives,
  but this should be good starting point.
Need to mention panoramic cameras here, for them it's only check for
  whether there are volumes in the scene, which would lead to speed
  regressions even if the camera is outside of the volumes. Would need
  to figure out proper check for such cameras.
There are still quite a few of TODOs in the code, but the patch is
  good enough to start playing around with it checking whether there are
  some obvious mistakes somewhere.
Currently the feature is only available in the Experimental feature
  sey, need to solve some of the TODOs and look into making things
  faster before considering the feature is ready for the official
  feature set. This would still likely happen in current release cycle.

As user sambler pointed out, fix is on the way.


text:
Bevelling concave curve part results in buggy mesh
I want to create some extruded, bevelled letters, and thus have created letters with the Font tool, then converted them to curves.
I have an issue with the letter B, which creates a buggy mesh surface near a concave curve point (selected here).

As soon as I bevel this object a little, the curve part starts to get modelled badly:

There's indeed only one curve vertex, not multiple at the same spot (I thought that might have been the problem). I don't find a way to easily fix this; the bevel should of course not create such a weirdly sticking-out part.
Did I miss a bevel option? Do I have to set sharp edges or something?

What you are seeing are shading artifacts from intersecting geometry.
Very tight sharp corners always cause problems when beveling in graphics software in general, since the software can't automatically handle these hard corner-cases cases unless it is specifically programmed to, or an option exists to clip/trim or extend said bevel options.
Blender has no special tools to deal with these so they end up self intersecting.
I usually solve it with the Offset modification available to the left of Bevel value.
Since beveling offsets the curve "outside" by the same amount of units used as bevel factor, all you have to do is counter this by using that value as a negative factor for offset so Blender "insets" the growth.

Additionally you may want to add an Edge Split modifier to your curve to avoid smoothing artifacts or errors.

I tried that, and while it gets rid of the "bug", it makes the letters a lot "thinner"... is there any way around that? I wish I could have them in the thickness they had before applying the offset.

In that case I would advise to use a font that originally has the correct thickness or desired text weigh before modification, so that when you bevel it you can still correct the weight increase get the desired final shape you want after bevel correction. Alternatively if you drew each character by hand draw them with the correct final weight and look you are aiming for so once again you can compensate for bevel and still get the desired shape.

Yeah, I guess that would be the only correct solution to use a better font. I just had the task to remaster a very old game logo, given a set font, and somehow he made the bevel look unbugged, but he used different tools though back then. Anyway, eventually I fixed that bevel of the B manually, as it was the only bug in the end. =)


text:
Sharp edges not sharp enough when bending?
I modelled an emblem with a skull and base/background, and I want the side borders to be smoothed, while the faces themselves get their own "smoothing group".
For that, I marked the edges between the surface / sides as sharp and - to get subdivision right - set the mean crease to 1.0.
This worked out fine until I bent the object to fit on the surface of another object.
If I look closely on the emblems skull now, some triangles get the wrong smoothing color, as if I didn't mark some edges correctly as sharp.

The emblem is a converted SVG curve, which may already be suboptimal, but I didn't know better for my 3rd model ever. The creased edges seen here are also marked as sharp.

Same goes to the background of the emblem, though even more sublime. If you crank up your monitors brightness, or just look at my edited picture, you can see different colors, as if the mean crease was not high enough (it's at 1 for that surface).

It was a simple cylinder once with some extrusion. Creased edges are also marked as sharp.

I don't even know if that can be corrected, as the surface is bent and somewhere the lightning just does its job. But the first thing is really going on my eyes.
I tried playing around with the modifier order, but nothing helped.

The models should be made with quads to avoid that kind of problem, use grid fill on the inner circle and butify faces on the skull.

To avoid smoothing artifacts the mesh should be made with even quads as possible.

You're using NGons (faces with more than 4 vertices/edges) and a curve converted to mesh, resulting in bad triangulated topology.
They're exactly what you don't want to bend.
Smoothed curve surfaces need quad topology.
All you can do is trying the face beauty fill (Ctrl+F menu with faces selected), or selecting the flat faces deleting them and reconstruct something better (extruding/scaling inside the outer loop) or using remesh modifier.
For your big round face of the background, inset it with I multiple times to the center and Alt+M at the center to merge the last loop at the center.
This is an exemple of a manual retopo. All quads, can be subsurfed, no bending artifact.

Blend file here

Thanks, it works nicely. Just to punish myself a little and learn never to use an SVG for these things again, I also manually remade the skull and now its perfect :)


text:
BMesh: How to map vertex-based UV-coordinates to loops?
I have a game model format which stores the UV coordinates for each vertex. To implement seams in the UV mapping, a vertex just appears twice, each having a different UV coordinate (it solves the lighting issues introduced with that by using custom normals stored for each vertex, but sadly I can't teach Blender custom normals correctly yet as I learned... another story).
Basically, my vertex data looks like this (made-up data):
Index   X       Y       Z       U       V
0       1.4235  0.2434  -0.322  0.0     0.5
1       2.3242  0.231   0.323   0.5     0.0
2       1.2242  0.531   -0.323  0.5     0.5
...

So I started writing an importer for this format, and thought it's easy enough to just set an uv property of a BMVert instance - just to find out that BMVert does not have a property for UV mapping at all.
From looking at the samples, it (logically) looks like I have to set the UV coordinates by iterating through loops rather than the vertices. But I'm a little stumped for an answer on how to find out the index of the vertex having the required UV coordinate when iterating through the loops.
The answer here UV Vertex using Python? was suggested, but it does not show how to retrieve the corresponding index of a vertex.
My current code to import the XYZ vertex positions (and normals) is as follows:
# Get the vertices and indices of the most detailled LoD model.
vertices = get_vertices(...)
indices = get_indices(...)
# Create a mesh and a bmesh to represent the polygon.
mesh = bpy.data.meshes.new(fshp.header.name_offset.name)
bm = bmesh.new()
bm.from_mesh(mesh)
# Go through the vertices and add them to the bmesh.
for vertex in vertices:
    bm_vert = bm.verts.new(vertex.p0)
    #bm_vert.normal = vertex.n0 # TODO: Blender does not really support custom normals yet, and they look weird.
bm.verts.ensure_lookup_table() # Required after adding / removing vertices and before accessing them by index.
# Connect the faces, they are organized as a triangle list.
for i in range(0, len(indices), 3):
    bm.faces.new(bm.verts[j] for j in indices[i:i + 3])
# TODO: Set the UV coordinates??
uv_layer = bm.loops.layers.uv.active
for face in bm.faces:
    for loop in face.loops:
        loop[uv_layer].uv = #..?
# Write the bmesh data back to the mesh.
bm.to_mesh(mesh)
bm.free()
mesh_obj = bpy.data.objects.new(mesh.name, mesh)
bpy.context.scene.objects.link(mesh_obj)

Possible duplicate of UV Vertex using Python?

Also related, but not using Bmesh: http://blender.stackexchange.com/questions/30677/set-coordinates-for-uv-vertices-using-python

There is a shortcoming in your idea: a vertex can have as many UV coordinates as the number of faces it is connected to. The right approach is to work with faces and loops and go down to vertex level from there.

@kheetor: I know that, but that's how the format works (I cannot change it). It has two vertices at UV seam points to make the seams possible. It's basically like a "compiled" version of a model, prepared to be sent to the GPU.

Yes and that's fine, that is how many formats handle vertices with split normals and UVs. But IMO in the beginning you need to start compiling the initial vertice list by going through the loops, not the bmverts.

@kheetor: Hm, I see. But, in the end, I can just create the vertices as given by the model, then just merge those with the same position together, as I noticed. That keeps (/ creates real) seams, and results in only one vertex. I just didn't want to make the model parser even more complicated... it's a horrible format to begin with xDc

It took me some time to realize I could just ask the vert property of a BMLoop when iterating through them, and then ask the index property of the retrieved BMVert to find my index.
It required to call bm.verts.index_update() before, or all the retrieved indices would've been -1.
This is my working code:
vertices = model.get_vertices()
# Add the vertices to the model.
for vertex in vertices:
    bm_vert = bm.verts.new(vertex.p0)
    #bm_vert.normal = vertex.n0 # TODO: Blender does not really support custom normals yet, and they look weird.
bm.verts.ensure_lookup_table() # Required after adding / removing vertices and before accessing them by index.
bm.verts.index_update()  # Required to actually retrieve the indices later on (or they stay -1).
# Connect the faces, they are organized as a triangle list.
for i in range(0, len(indices), 3):
    bm.faces.new(bm.verts[j] for j in indices[i:i + 3])
# Set the UV coordinates by iterating through the face loops.
uv_layer = bm.loops.layers.uv.new()
for face in bm.faces:
    for loop in face.loops:
        # Get the index of the vertex the loop contains.
        loop[uv_layer].uv = vertices[loop.vert.index].u0

This doesn't look like working code, vertices[]: is an error. Please show a full working example (if this is to be considered a good answer).

@ideasman42: Whoops, there was a concept of visibility groups in that format, only requiring a slice of the vertices. I left it out for readability because it's unimportant for the problem, but forgot to remove the braces. Thanks!

You do the mapping like this:
for face in bm.faces:
    for vert, loop in zip(face.verts, face.loops):
        loop[uv_layer].uv = get_uvs(vert.index, face.index,...)

The last line depends on your file format and how are the UVs stored. You should be able to retrieve the appropriate UV coords from vert.index and face.index info.

@RayKoopa if there can be only 1uv per physical vertex then you cannot have any seams and so there is only support for planar meshes. Your function is then very simple (something like get_uvs(vert.index, file_path)).

Yeah, as said, the model file format splits vertices to realize seams; it's like a model version readily compiled for use by the game engine so the game doesn't have to split them before sending them to the GPU, I guess. I found a solution; maybe it makes my question more clear ='3


text:
How to deform button pattern around curved bench
I am trying to model a simple version of a "banquette". Something like this:

I have started by making the curved part by extruding a plane, and just adding a bevel modifier for the corner and then solidify modifier. I have also made a very simplifed version of the button pattern:

I would now like to make this array pattern fit onto the front surface of the bench, but had little success with any of the obvious modifiers (Shrinkwrap, Surface Deform, or Simple Deform). Can anyone suggest how I might go about doing this?
Thanks

https://blender.stackexchange.com/questions/306353/modelling-a-couch-cushion-with-complex-seams https://blender.stackexchange.com/questions/19241/model-upholstery-with-buttons

@DuarteFarrajotaRamos Thanks, these are useful links. However, they are more about how to make an intricate and realistic button pattern. My concern is more about the high level shape, i.e. assuming we have a nice button pattern (a task for another day), how do we make it into the curved global bench shape?

Curve modifier https://blender.stackexchange.com/questions/95978/how-can-i-model-an-irregular-object-made-from-laser-cutting-metal-sheet/ https://blender.stackexchange.com/questions/49639/how-to-smooth-an-arrayed-object-so-the-breaks-between-objects-are-less-obvious/49651#49651

@DuarteFarrajotaRamos So I need to somehow convert only one edge of the bench into a curve, and then map the pattern onto that? Can you provide example?

Both those answers have examples you can follow along. Just create a curve object roughly following the shape of you couch, then array a single module to fill the length of that curve and deform it. See https://blender.stackexchange.com/questions/65567/problems-with-curve-modifier/65571#65571 for all the known caveats

@DuarteFarrajotaRamos yes I know what you mean. The issue is that I want to manipulate the dimensions of the couch base, and then have the buttons follow with it. Ideally I don't want an intermediate object (your  curve) which is only "roughly" the same shape, and which i need to also adjust if I adjust the couch dimensions. Does it make sense?

I believe you are thinking about it the wrong way.
The curve would be your actual couch, in such way that it would control its shape, rather than something you would have to keep updated manually.

Make a single tufted couch module.
Optionally make bespoke end caps for the array
Array it to fit a bezier curve
Add a curve modifier afterwards to make it follow the curve

May I ask how you capture your gifs ? I'd like to do the same. Thank you !

@Lutzi See https://blender.meta.stackexchange.com/questions/963/what-is-the-process-for-creating-gifs-for-questions-and-answers/ I use ScreenToGIF

@DuarteFarrajotaRamos Ah I see, this is a quite different approach to what I had in mind. Looks good! Could you share the blend file so I can play with it?

Sorry I don't have  one, I never saved it


text:
How to randomly distribute a specific number of instances?
I would like to distribute a specific number of instances (say, a torus) on a mesh (say, a plane), using geometry nodes. This answer got me close, as you can see:

However, when I increase the number of instances they do not distribute randomly, but rather from the bottom up:

Can someone a) help me understand why this is, and b) how I can fix it to make them randomly distribute?
Thanks

The indices of points spawned by "Distribute Points on Faces" are not random - there is a clear correlation between faces and point indices. I didn't investigate the source, but it seems:

the algorithm estimates how many points need to be spawned per face, to distribute the points evenly across the entire surface (I do the same thing below),
then the algorithm goes through face by face (I think actually through the triangulated faces), spawning the calculated number of points on each face (or with calculated probability), similarly to what I do [here],(https://blender.stackexchange.com/a/221597/60486)
finally it seems the algorithm does a second pass if not enough points were spawned?

Not sure, maybe something completely different happens.
The solution is to either implement your own "Distribute Points on Faces", which I think isn't that hard, or use the dedicated node, but then shuffle the indices, which I do below:

Am I missing something?

..and point indices seem to be randomly distributed too, for further segmentation of the space.

..OK, this doesn't address the more general case

Hi Robin, thanks for this. I wasn't aware of the "Points" node. I am using Blender version 3.1.2, and it looks like maybe "Points" was introduced later than this? I think your answer solves my problem - but I'm not sure what you mean that it doesn't solve the general case?

Hi, @teeeeee the wizard's solution can be used to randomly distribute n points across any set of faces.. mine will only work evenly  on a square plane.. it needs tweaking even for a rectangle, so his answer is much stronger. In fact I think I should delete this one.

Ah, I see. As long as the limitations are pointed out, I think keep it here (I found it usefu, as someone who is starting to learn Geo Nodes, so maybe others will). I will accept the other answer. Thanks again.


text:
How to make this type of array in Geometry Nodes?
Is there a way to make this kind of shape with curves in Geometry Nodes?

I had a go, but think I am just getting down a rabbit hole. For sme reason, I don't have access to the rotation of each instance. Also, I am not sure how to make the instances increase in number until they fit around the circle.

Hi. Please use a title that matches the content of the question. It should be descriptive but succinct, unique and identifying, summarizing the issue in such way that anyone searching for a similar problem is likely to find it. Use the [edit] link above, remove anything superfluous, avoid words like "this", "help", "issue with" or "question about". Remember, your title is the first thing potential visitors see, answers you get depend heavily on how insightful it is. See What is the problem of asking “How do I do this?"

Why don't you just extrude a circle?

+1 damn, that was easy! ;)

and if you want faces: https://i.imgur.com/GV8AS3L.png

@MarkusvonBroady, but mine was with faces... It's just wireframe shading mode. Am I missing something?

@MartynasŽiemys ohhh... Makes sense now that I think of it.

I don't get it though... :D The simpler the answer, the more up-votes. You spend 1 minute on the simplest question and it gets up-voted more than the ones that take days to figure out. :D


text:
Mirror going wrong

I'm new in Blender and I'm stuck here for days. Can someone please explain to me, how does the mirror work so badly when both my origin point and 3d cursor are perfectly aligned to the centre of the axes?

mirror depends on your transforms
just apply transforms

Thank you so much @GloriaTheAnimator

If someone answered your question, consider accepting it by pressing the checkbox on the top left of the answer.


text:
Can't move vertices down
I'm following the donut series on youtube and I have a problem when I want to move vertices of icing down to look more like an icing. the problem is that when I hit g I can move them down but while holding alt + s, something weird happens and it seems that vertices are going inward the donut rather than outward.
the first picture, is while pressing alt + s and second one shows when I press g.
I apologize for my poor level of English. I hope you get what I mean

Why are you pressing Alt S? Alt S is for Shrink/Fatten, not sure it's what you want here. Also, it doesn't look like you've enabled the Snap option, you can activate it with the Ctrl key but anyway, you need to choose the Snap to Face if you want the vertex to snap to the donut face. At last, the vertices may still go into the donut because it has a Subdivision Surface modifier and it makes the surface look round


text:
Hot element's glare in a colored lamp in rotational animation?
The problem was acceptably solved by using ideas from Hexbob6's reply, plus the ideas from the link he gave me in discussion of his reply (the link is in the discussion of his reply).
Problem's very gist: Need to maintain the glow of a colored lamp's hot element (the glow remains visible even in rotation, when the hot element of the green lamp disappears from sight but a part of the lamp is still seen), plus to have the element's color be close in color to its blackbody temperature all the time (and the glow be affected by it).
Tried to add glare to hot element before Z combine - didn't work (no glare visible at all). Only worked if whole scene uses glare [2.png]. Plus if the scene is rotated such that the hot element is not seen on screen directly [1b.png], the light is not giving out the glare or shine from the lamp. Tried to Alpha-Over the glare-added colored glass (without the hot element) in the compositor onto the whole scene [4.png], but the solid case around the colored glass wrongly looked transparent.
If I could also have an advice on how to make a very/even more realistic light like this, it would be really nice. Thank you!
Edit: If anyone could help with a custom node setup to control the length of light falloff such that the non-compositor "glare" fades out right after leaving surface of the colored glass (and before it leaves the volume scattering enabled cube around it which otherwise makes the glare to have a square shape), it would be really nice. Thanks a lot!

4:
3b:
3a:
2:
1a:
1b:

The issue stems from the fact that the Glare node in the compositor is a post-production effect, and doesn't take into account actual cycles emission materials. Instead, it bases how much glow to give the image based on how bright the rendered pixels are (hence the brighter green receives glow, because it is brighter). You could try increasing the Threshold value of the Glare node to see if you can capture all of the green pixels (viewable by setting the Mix value to 1), or you could use a different method entirely (material/object IDs or volumetric materials to simulate fog).

Tried material ID, didn't work out well for some reason - the color of the hot elements gets changed to purple, etc.: https://snag.gy/ux7IlD.jpg. As for volumetric scattering, I don't know how to make the rays shoot a shorter distance from the lamp, plus it renders too slow.

interesting, I can't see what would be causing that purple colour! Are you rendering using the Filmic colour management settings? I know not all mix nodes support it (possibly neither Alpha Over?) and you can get weird artefacts such as those?

No, not the Filmic c/m was used for the renders. It was fine and then it became like that when I kept on tweaking.

Any idea how I can control light fall off using ray length to make volume scatter rays be so short they fade almost right away after leaving lamps surface (which produces a sort of a small glow) ? (Can't figure out the node set-up)

Found one set-up on https://blender.stackexchange.com/questions/983/exclusive-lighting and https://blender.stackexchange.com/questions/1818/is-it-possible-for-light-sources-in-cycles-to-have-nonphysical-falloff-like-in-b and it sort of worked after some tweaking (https://snag.gy/a0cujV.jpg, https://snag.gy/0C4M2r.jpg, https://snag.gy/cNZVYi.jpg, https://snag.gy/90cwpr.jpg, https://snag.gy/IruKtH.jpg), but still not really what I was looking for. Can't get the light to fade sooner.

The following set-up appeared to be a good improvement: https://snag.gy/L4dAtk.jpg. The next step (for another question if I need to) would be to take the light after it escapes the colored glass and to apply color ramp or something else to try to make the hot element yellowish (its plain green now).

@Dimitri is this more of the effect that you were looking for? If so I'll write a quick tutorial in the answer below :) // https://snag.gy/KTcW49.jpg // https://snag.gy/te3qj7.jpg //

@Hexbob6: Thank you very much! This is pretty much it. Twice or trice more glow is even better though. Thanks so much for the offer. I'm definitely saying yes. Sounds absolutely fantastic!

If you could also colorramp the element's core to look yellow from the glow (I don't know how to do it), it would be even better. Though already it would be so unbelievably nice of you!!!

@Dimitri no problem, the technique is a compositing effect, rather than in-camera, but it should allow you to scale the intensity of the glare, alter the colour and increase the falloff distance.

Let's see!! Sounds good enough!

In Blender it's not 100% physics anyway - it ain't taking gravitational lensing into account, does it?! So, what works, works!

How to Create a Glow Effect in Cycles

Okay so although you suggested that you'd prefer this not to be a compositing-based solution, as mentioned in the comments I'll put this together regardless as it is a very useful and adaptable effect.
Here's the end result of what we'll be creating:

The bulb itself is fairly simple, with a coloured-glass, domed bulb and an inner filament object. The materials are also fairly simple. The glass bulb simply uses the Principled BSDF shader with the following settings:

It is also important to set the Pass Index to 1 in the Settings dropdown of the Material tab in the Properties panel, as this will create an ID mask of the bulb object visible to the camera, which we will use in the compositing step. The final part of this process is to adjust the render and scene settings. Rendering glass with a thickness is always a bit process-intensive and can cause fireflies and noise, so I used the Branched Path Tracing method with the following settings to help reduce it:

Now, once that is rendered out, on to the compositor! The first step is adding a Glare node and adjusting the threshold and size. This step will require tweaking on a per-scene basis, but it will add a centralised glow at the heart of the bulb, wherever the filament is visible.

Next, the outer-glow effect can be developed. Remember that material Pass Index that we set earlier? We'll access that with an ID Mask node, giving us a b/w mask of only the bulb.

Using this mask, we'll now add a Blur node and set it to Fast Gaussian. This node will act as the 'spread', or light falloff control, of our lamp; the greater the blur, the larger the width of the glow.

The penultimate step of the compositing process is adding a Color Ramp to act as our light intensity controller. The left side of the ramp should be set to pure black, however the right side should have a dark-grey value. How dark this right side is, defines how intense, or bright, the final glow will be, and should be adjusted accordingly.

Finally, this edited mask can be used as the Fac input of an Add node to mix between the original image and a glow colour. This glow colour should technically be the colour of the bulb's glass shader, however you can be artistic with it!

And there we go, a compositing node setup that adds a realistic yet entirely customisable glow to the render! Here's the final node setup in its entirety, and I've also added my .blend file to you to play about with as well.

Hope this is of some help to you, and don't forget to upvote/mark as the right answer if it is! :)

That worked really well (https://snag.gy/I0bBoW.jpg, https://snag.gy/HtAJRa.jpg)! Composer CAN be used for this kind of thing afterall! I couldn't get the core to yellow-out when I tilt the lamp toward's the scene's back though. The effect gets layed on top of the picture like this: https://snag.gy/WBqv1Q.jpg. I guess I would need Z combine and renderlayers for the element material?

In particular, the following set-up is troublesome to me in this regard: https://snag.gy/ZYE0Km.jpg. I want to make an animation, and to be able to tilt the lamp without loosing the yellow effect. Any idea whether I should use alpha-over or the math-add (neither works as the summing node), or somethign else here?

Your tutorial is an eye opener in many a regard. You are a very good teacher! Thank you very much. And I am sorry if I seem like a never-happy idiot with all my after-questions.

At the top (https://i.sstatic.net/K2O9H.png) your result had a yellow core, and possibly the same set-up didn't exhibit the yellow glow overlaying when the model is tilted (https://i.sstatic.net/K2O9H.png). How did you connect things in the composer for that if so?

@Dmitri the yellow core is a secondary glow effect added manually around the filament object. Your original question wasn't related to animation so the solution is tailored to suit a static rendered image. Technically, I believe, you wouldn't get the orange glow if the filament object isn't in direct view of the camera, as the bulb itself is green... (cont.)

... On this logic you could probably add another Pass Index to isolate the filament and repeat the steps in the tutorial to create the second glow, but that runs into the issue described here https://blender.stackexchange.com/questions/103310/how-to-utilize-material-or-object-index-behind-a-refractive-material-in-cycle , and solving that is an obstacle in and of itself which would go far beyond the scope of the original question.

Interesting and challenging! Will definitely look into that! Thanks a lot again for your help - I am extremely grateful to you for it!!!

@Dmitri , no problem, if it did help as I mentioned could you mark it as correct so that others visiting the question can view it as being solved? Thanks!

I'm sorry I didn't realize I had to tick the checkmark for that. Earlier I clicked to up the answer but didn't have enough privilege.

I went to the link you gave and used Rich Sedman's answer to create the mask for the glowing element which is inside the colored lamp. Then I alphaovered the blurred and color-changed glow of the mask itself on top of the lamp's glow to create the effect I needed. Thanks for the link! (1) https://snag.gy/wPclam.jpg, (2) https://snag.gy/SEimI4.jpg, (3) https://snag.gy/kEV6vZ.jpg. Here I have created a material called mask and assigned it as the override material of the layer used for the mask. The hot element's object ID is 10 and the lamp's 5.


text:
Can't get the environment texture to emit light
Can't get the environment texture to emit light. I as usual enabled camera, diffused and glossy settings on World Background, set the background color as always to environment texture HDR, but the object with a non-black diffuse material shows up black unless AO is anabled (in-design render works fine and the object is not excluded from render by being placed in an exluded layer, its ray visibility is also fully on). The object is not excluded from rendering, all of its cycles settings are enabled (camera, diffuse, glossy, etc.). Checked nodes for background and composing - all is good. Rendered fine before. Even appended all model's key items into a fresh blender file - to no avail. No clue what's happenning.

Please post your blend file. If I can play with it I may be able to figure out what went wrong.

I figured it out. The issue was that the object was too small in comparison to the standard grid size (how small can it get before the background won't affect it?). When I scaled it up, the background started to emit light as it should. For some reason the grid also looks clipped at the far and near ends like it never had before, though I changed the clipping settings (correctly?) to try to extend the visible range.


text:
Unfold / peel off animation
I have to create a similar animation with the attached image.
How to create  this effect in Blender?
Thanks in advance!

https://blender.stackexchange.com/a/192079/2214

https://blender.stackexchange.com/questions/54114/how-to-make-peeling-edges-of-a-paper

You can try Plane deformed by Curve modifier plus Mirror modifier

It is quite tricky to work with curve for me. But in this case just add Curve, switch type to 2D (under Curve Properties), rotate 90°on X, in edit mode shape curve as you need. In object mode rotate on Z axis to let curve peel from cornet. Before you add paper a Curve modifier move curve object origin to paper's left top corner. Animate curve's Location.


text:
Is Texture Paint While In Viewport Render Possible With Cycles?
Is it possible to texture paint while rendering with Cycles?
I've done it with EEVEE but can't seem to find anyway to have cycles viewport update while texture painting.

I had a similar circumstance where I was not able to see updates in the Cycles viewport.   I learned to live with it.  It was not essential for me.  I suppose you could have special circumstance that could be explained.

Language Language ....

So there's probably not a way to use cycles while in texture paint at this moment?

I'm going to hazard a guess that this isn't possible at least without performance degradation.  The cycles integrator has to assume a somewhat static state of the shader, otherwise it is forced to restart the render every time you make a change.  So two things stick out in my mind.  Doing this would pause the viewport to such an extent it would become unwieldy, and it may be the case that cycles only updates the viewport when you change a noodle in the node editor, not when an image is changed.

No, render view in Cycles will not update as you paint, no fix for this.
I have spent a lot of time painting in blender, and in the newer post 2.8 builds I find that either Solid View or Material Preview are the best to paint in regardless of which renderer I have set up, and for preview of the paint I swap to the Shading workspace to see it or just set up a duplicate editor in a small view and set that one to render view.


text:
Remove mesh editing limit in sculpting
I'm on Blender 2.9 attempting to sculpt. Earlier in the year in 2.83 I could clearly remember ticking/unticking something to be able to keep endlessly adding/subtracting volume with brushes like Clay Strips by continuously sculpting on a surface. Even if it was facing the camera, I could go in circles and just make a cylinder. Right now the default is to add to some limit, then just keep smoothing it out.
It's not masked, I have dyntopo on etc. I can obliterate the whole mesh by making a massive brush, it's nothing like that. I know it's possible to sculpt functionally endlessly long thin strips by just adding more volume from a small area for example. Right now there's some kind of maximum limit the mesh can be deformed.
What setting exactly enables limitless volume editing in sculpt mode?

You're looking for the Accumulate checkbox in the sculpt tool options of the properties editor.
https://docs.blender.org/manual/en/dev/sculpt_paint/sculpting/tool_settings/brush_settings.html#advanced