Refactor and enhance geometry node groups for depth plane and material layers
- Updated the depth plane node group to load from an asset and simplified the interface. - Created a new build script for depth plane geometry nodes. - Introduced material layer groups for image and depth materials with appropriate sockets. - Added functionality to connect balloon normal scale to the image material. - Enhanced tests to validate the new node groups and their connections. - Ensured that production code does not create node groups directly.
This commit is contained in:
Binary file not shown.
@@ -84,10 +84,6 @@ def set_modifier_input(modifier, identifier, value):
|
||||
|
||||
DISPLACEMENT_STRENGTH = 1.0
|
||||
DISPLACEMENT_MIDLEVEL = 0.0
|
||||
BUMP_BASE_DISTANCE = 0.001
|
||||
MATERIAL_DISPLACEMENT_ATTRIBUTE = "o_material_displacement"
|
||||
BACKGROUND_DEPTH_ATTRIBUTE = "o_background_depth"
|
||||
DEPTH_SCALE_ATTRIBUTE = "o_depth_scale"
|
||||
IMAGE_MATERIAL_NODE_GROUP_NAME = "O Image Layer"
|
||||
DEPTH_MATERIAL_NODE_GROUP_NAME = "O Image Depth Layer"
|
||||
SHADELESS_NODE_GROUP_NAME = "O Shadeless"
|
||||
@@ -143,186 +139,7 @@ def material_node_group(depth_plane=False):
|
||||
if depth_plane
|
||||
else IMAGE_MATERIAL_NODE_GROUP_NAME
|
||||
)
|
||||
existing = bpy.data.node_groups.get(group_name)
|
||||
if existing is not None:
|
||||
for item in existing.interface.items_tree:
|
||||
if (
|
||||
item.item_type == "SOCKET"
|
||||
and item.in_out == "INPUT"
|
||||
and item.name == "Normal"
|
||||
):
|
||||
item.default_value = (0.5, 0.5, 1.0, 1.0)
|
||||
return existing
|
||||
group = bpy.data.node_groups.new(group_name, "ShaderNodeTree")
|
||||
interface = group.interface
|
||||
input_sockets = [
|
||||
("Color", "NodeSocketColor"),
|
||||
("Alpha", "NodeSocketFloat"),
|
||||
("Bump Scale", "NodeSocketFloat"),
|
||||
]
|
||||
normal_group = not depth_plane
|
||||
if normal_group:
|
||||
input_sockets.insert(2, ("Normal", "NodeSocketColor"))
|
||||
input_sockets.insert(3, ("Normal Scale", "NodeSocketFloat"))
|
||||
input_sockets.insert(4, ("Object Space", "NodeSocketBool"))
|
||||
if depth_plane:
|
||||
input_sockets.insert(2, ("Depth", "NodeSocketFloat"))
|
||||
for name, socket_type in input_sockets:
|
||||
socket = interface.new_socket(
|
||||
name=name,
|
||||
in_out="INPUT",
|
||||
socket_type=socket_type,
|
||||
)
|
||||
if name == "Alpha":
|
||||
socket.default_value = 1.0
|
||||
socket.min_value = 0.0
|
||||
socket.max_value = 1.0
|
||||
socket.subtype = "FACTOR"
|
||||
elif name == "Bump Scale":
|
||||
socket.default_value = 0.0
|
||||
socket.min_value = -10000.0
|
||||
socket.max_value = 10000.0
|
||||
elif name == "Normal":
|
||||
socket.default_value = (0.5, 0.5, 1.0, 1.0)
|
||||
elif name == "Normal Scale":
|
||||
socket.default_value = 1.0
|
||||
socket.min_value = 0.0
|
||||
socket.max_value = 10.0
|
||||
elif name == "Object Space":
|
||||
socket.default_value = False
|
||||
output_sockets = [
|
||||
("Color", "NodeSocketColor"),
|
||||
("Roughness", "NodeSocketFloat"),
|
||||
("Alpha", "NodeSocketFloat"),
|
||||
("Normal", "NodeSocketVector"),
|
||||
]
|
||||
if depth_plane:
|
||||
output_sockets.append(("Displacement", "NodeSocketVector"))
|
||||
for name, socket_type in output_sockets:
|
||||
interface.new_socket(
|
||||
name=name,
|
||||
in_out="OUTPUT",
|
||||
socket_type=socket_type,
|
||||
)
|
||||
|
||||
nodes = group.nodes
|
||||
links = group.links
|
||||
group_input = nodes.new("NodeGroupInput")
|
||||
group_input.location = (-500.0, 100.0)
|
||||
group_output = nodes.new("NodeGroupOutput")
|
||||
group_output.location = (300.0, 100.0)
|
||||
roughness_curve = nodes.new("ShaderNodeFloatCurve")
|
||||
roughness_curve.mapping.initialize()
|
||||
curve_points = roughness_curve.mapping.curves[0].points
|
||||
curve_points[0].location = (0.0, 0.5)
|
||||
curve_points[-1].location = (1.0, 0.1)
|
||||
roughness_curve.mapping.update()
|
||||
roughness_curve.location = (-250.0, 350.0)
|
||||
bump = nodes.new("ShaderNodeBump")
|
||||
bump.location = (100.0, 0.0)
|
||||
if normal_group:
|
||||
tangent_normal = nodes.new("ShaderNodeNormalMap")
|
||||
tangent_normal.space = "TANGENT"
|
||||
tangent_normal.location = (-500.0, -100.0)
|
||||
object_normal = nodes.new("ShaderNodeNormalMap")
|
||||
object_normal.space = "OBJECT"
|
||||
object_normal.location = (-500.0, -350.0)
|
||||
choose_normal = nodes.new("ShaderNodeMix")
|
||||
choose_normal.data_type = "VECTOR"
|
||||
choose_normal.location = (-150.0, -150.0)
|
||||
for normal_map in (tangent_normal, object_normal):
|
||||
links.new(group_input.outputs["Normal"], normal_map.inputs["Color"])
|
||||
links.new(
|
||||
group_input.outputs["Normal Scale"],
|
||||
normal_map.inputs["Strength"],
|
||||
)
|
||||
links.new(group_input.outputs["Object Space"], choose_normal.inputs[0])
|
||||
links.new(tangent_normal.outputs["Normal"], choose_normal.inputs[4])
|
||||
links.new(object_normal.outputs["Normal"], choose_normal.inputs[5])
|
||||
links.new(choose_normal.outputs["Result"], bump.inputs["Normal"])
|
||||
displacement = None
|
||||
|
||||
processed_alpha = group_input.outputs["Alpha"]
|
||||
bump_depth = group_input.outputs["Color"]
|
||||
if depth_plane:
|
||||
displacement = nodes.new("ShaderNodeDisplacement")
|
||||
displacement.inputs["Midlevel"].default_value = 0.0
|
||||
displacement.inputs["Scale"].default_value = 1.0
|
||||
group_input.location = (-1200.0, 100.0)
|
||||
group_output.location = (1050.0, 100.0)
|
||||
roughness_curve.location = (-300.0, 450.0)
|
||||
bump.location = (750.0, 50.0)
|
||||
displacement.location = (750.0, -300.0)
|
||||
background_attribute = nodes.new("ShaderNodeAttribute")
|
||||
background_attribute.attribute_type = "GEOMETRY"
|
||||
background_attribute.attribute_name = BACKGROUND_DEPTH_ATTRIBUTE
|
||||
background_attribute.location = (-950.0, -500.0)
|
||||
material_attribute = nodes.new("ShaderNodeAttribute")
|
||||
material_attribute.attribute_type = "GEOMETRY"
|
||||
material_attribute.attribute_name = MATERIAL_DISPLACEMENT_ATTRIBUTE
|
||||
material_attribute.location = (-50.0, -650.0)
|
||||
strength_attribute = nodes.new("ShaderNodeAttribute")
|
||||
strength_attribute.attribute_type = "GEOMETRY"
|
||||
strength_attribute.attribute_name = DEPTH_SCALE_ATTRIBUTE
|
||||
strength_attribute.location = (200.0, -650.0)
|
||||
foreground_mask = nodes.new("ShaderNodeMath")
|
||||
foreground_mask.operation = "GREATER_THAN"
|
||||
foreground_mask.inputs[1].default_value = 0.5
|
||||
foreground_mask.location = (-950.0, -250.0)
|
||||
clamp_foreground = nodes.new("ShaderNodeMath")
|
||||
clamp_foreground.operation = "MAXIMUM"
|
||||
clamp_foreground.location = (-650.0, -400.0)
|
||||
masked_depth = nodes.new("ShaderNodeMix")
|
||||
masked_depth.data_type = "FLOAT"
|
||||
masked_depth.location = (-350.0, -350.0)
|
||||
enabled_depth = nodes.new("ShaderNodeMath")
|
||||
enabled_depth.operation = "MULTIPLY"
|
||||
enabled_depth.location = (250.0, -350.0)
|
||||
scaled_depth = nodes.new("ShaderNodeMath")
|
||||
scaled_depth.operation = "MULTIPLY"
|
||||
scaled_depth.location = (450.0, -350.0)
|
||||
links.new(group_input.outputs["Alpha"], foreground_mask.inputs[0])
|
||||
links.new(group_input.outputs["Depth"], clamp_foreground.inputs[0])
|
||||
links.new(background_attribute.outputs["Fac"], clamp_foreground.inputs[1])
|
||||
links.new(foreground_mask.outputs[0], masked_depth.inputs[0])
|
||||
links.new(background_attribute.outputs["Fac"], masked_depth.inputs[2])
|
||||
links.new(clamp_foreground.outputs[0], masked_depth.inputs[3])
|
||||
links.new(masked_depth.outputs["Result"], enabled_depth.inputs[0])
|
||||
links.new(material_attribute.outputs["Fac"], enabled_depth.inputs[1])
|
||||
links.new(enabled_depth.outputs[0], scaled_depth.inputs[0])
|
||||
links.new(strength_attribute.outputs["Fac"], scaled_depth.inputs[1])
|
||||
processed_alpha = foreground_mask.outputs[0]
|
||||
processed_depth = scaled_depth.outputs[0]
|
||||
|
||||
links.new(group_input.outputs["Color"], group_output.inputs["Color"])
|
||||
links.new(group_input.outputs["Color"], roughness_curve.inputs["Value"])
|
||||
links.new(
|
||||
roughness_curve.outputs["Value"],
|
||||
group_output.inputs["Roughness"],
|
||||
)
|
||||
links.new(processed_alpha, group_output.inputs["Alpha"])
|
||||
links.new(bump_depth, bump.inputs["Height"])
|
||||
bump_distance = nodes.new("ShaderNodeMath")
|
||||
bump_distance.operation = "MULTIPLY"
|
||||
bump_distance.inputs[1].default_value = BUMP_BASE_DISTANCE
|
||||
bump_distance.location = (500.0, 100.0) if depth_plane else (-250.0, 150.0)
|
||||
links.new(group_input.outputs["Bump Scale"], bump_distance.inputs[0])
|
||||
links.new(bump_distance.outputs[0], bump.inputs["Distance"])
|
||||
links.new(bump.outputs["Normal"], group_output.inputs["Normal"])
|
||||
if displacement is not None:
|
||||
links.new(processed_depth, displacement.inputs["Height"])
|
||||
links.new(
|
||||
displacement.outputs["Displacement"],
|
||||
group_output.inputs["Displacement"],
|
||||
)
|
||||
group.color_tag = "SHADER"
|
||||
group.description = (
|
||||
"Prepare image depth material outputs."
|
||||
if depth_plane
|
||||
else f"Prepare {group_name} material outputs."
|
||||
)
|
||||
group.use_fake_user = True
|
||||
return group
|
||||
return load_asset_node_group(group_name)
|
||||
|
||||
|
||||
def create_image_material(
|
||||
|
||||
@@ -1,198 +1,18 @@
|
||||
"""Runtime Geometry Nodes for Depth Plane."""
|
||||
|
||||
import bpy
|
||||
"""Asset-backed Geometry Nodes for Plane conversion."""
|
||||
|
||||
from ..common.mesh_result import load_asset_node_group
|
||||
|
||||
|
||||
MESH_PLANE_NODE_GROUP_NAME = "O Mesh Plane"
|
||||
DEPTH_PLANE_NODE_GROUP_NAME = "O Image Depth Plane"
|
||||
|
||||
|
||||
def mesh_plane_node_group():
|
||||
return load_asset_node_group(MESH_PLANE_NODE_GROUP_NAME)
|
||||
|
||||
|
||||
def _interface_socket(group, name, in_out, socket_type):
|
||||
socket = group.interface.new_socket(
|
||||
name=name,
|
||||
in_out=in_out,
|
||||
socket_type=socket_type,
|
||||
)
|
||||
if in_out == "INPUT" and hasattr(socket, "structure_type"):
|
||||
socket.structure_type = "SINGLE"
|
||||
return socket
|
||||
|
||||
|
||||
def _group_input(nodes, location, visible_names):
|
||||
node = nodes.new("NodeGroupInput")
|
||||
node.location = location
|
||||
visible = set(visible_names)
|
||||
for output in node.outputs:
|
||||
output.hide = output.name not in visible
|
||||
return node
|
||||
|
||||
def depth_plane_node_group():
|
||||
group_name = "O Image Depth Plane"
|
||||
group = bpy.data.node_groups.get(group_name)
|
||||
if group is not None:
|
||||
return group
|
||||
if group is None:
|
||||
group = bpy.data.node_groups.new(group_name, "GeometryNodeTree")
|
||||
else:
|
||||
group.nodes.clear()
|
||||
group.interface.clear()
|
||||
group.is_modifier = True
|
||||
_interface_socket(group, "Geometry", "INPUT", "NodeSocketGeometry")
|
||||
subdivide = _interface_socket(group, "Subdivide", "INPUT", "NodeSocketInt")
|
||||
subdivide.default_value = 7
|
||||
subdivide.min_value = 0
|
||||
subdivide.max_value = 10
|
||||
thickness = _interface_socket(group, "Thickness", "INPUT", "NodeSocketFloat")
|
||||
thickness.default_value = 0.1
|
||||
thickness.min_value = 0.0
|
||||
thickness.subtype = "DISTANCE"
|
||||
depth_amount = _interface_socket(group, "Depth Amount", "INPUT", "NodeSocketFloat")
|
||||
depth_amount.default_value = 1.0
|
||||
depth_amount.min_value = 0.0
|
||||
reference_depth = _interface_socket(
|
||||
group, "Reference Depth", "INPUT", "NodeSocketFloat"
|
||||
)
|
||||
reference_depth.hide_in_modifier = True
|
||||
uniform_scale = _interface_socket(
|
||||
group, "Uniform Scale", "INPUT", "NodeSocketFloat"
|
||||
)
|
||||
uniform_scale.hide_in_modifier = True
|
||||
depth_image = _interface_socket(group, "Depth Image", "INPUT", "NodeSocketImage")
|
||||
depth_image.hide_in_modifier = True
|
||||
material = _interface_socket(group, "Material", "INPUT", "NodeSocketMaterial")
|
||||
material.hide_in_modifier = True
|
||||
_interface_socket(group, "Geometry", "OUTPUT", "NodeSocketGeometry")
|
||||
|
||||
nodes = group.nodes
|
||||
links = group.links
|
||||
geometry_input = _group_input(
|
||||
nodes,
|
||||
(-1850.0, 450.0),
|
||||
{"Geometry", "Subdivide", "Material"},
|
||||
)
|
||||
shape_input = _group_input(
|
||||
nodes,
|
||||
(-1250.0, 850.0),
|
||||
{"Thickness", "Depth Amount"},
|
||||
)
|
||||
image_input = _group_input(
|
||||
nodes,
|
||||
(-1050.0, 50.0),
|
||||
{"Depth Image", "Reference Depth", "Uniform Scale"},
|
||||
)
|
||||
cleanup_input = _group_input(nodes, (650.0, -200.0), {"Thickness"})
|
||||
group_output = nodes.new("NodeGroupOutput")
|
||||
group_output.location = (1850.0, 450.0)
|
||||
mesh_plane = nodes.new("GeometryNodeGroup")
|
||||
mesh_plane.node_tree = mesh_plane_node_group()
|
||||
mesh_plane.inputs["Thickness"].default_value = 0.0
|
||||
mesh_plane.location = (-1550.0, 450.0)
|
||||
links.new(geometry_input.outputs["Geometry"], mesh_plane.inputs["Geometry"])
|
||||
links.new(geometry_input.outputs["Subdivide"], mesh_plane.inputs["Subdivide"])
|
||||
links.new(geometry_input.outputs["Material"], mesh_plane.inputs["Material"])
|
||||
|
||||
extrude = nodes.new("GeometryNodeExtrudeMesh")
|
||||
extrude.mode = "FACES"
|
||||
extrude.inputs["Offset"].default_value = (0.0, 0.0, -1.0)
|
||||
extrude.inputs["Individual"].default_value = False
|
||||
extrude.location = (-1200.0, 450.0)
|
||||
links.new(mesh_plane.outputs["Geometry"], extrude.inputs["Mesh"])
|
||||
links.new(shape_input.outputs["Thickness"], extrude.inputs["Offset Scale"])
|
||||
geometry = extrude.outputs["Mesh"]
|
||||
|
||||
uv = nodes.new("GeometryNodeInputNamedAttribute")
|
||||
uv.data_type = "FLOAT_VECTOR"
|
||||
uv.inputs["Name"].default_value = "UVMap"
|
||||
uv.location = (-1000.0, 50.0)
|
||||
texture = nodes.new("GeometryNodeImageTexture")
|
||||
texture.location = (-800.0, 50.0)
|
||||
links.new(image_input.outputs["Depth Image"], texture.inputs["Image"])
|
||||
links.new(uv.outputs["Attribute"], texture.inputs["Vector"])
|
||||
separate = nodes.new("ShaderNodeSeparateXYZ")
|
||||
separate.location = (-600.0, 50.0)
|
||||
links.new(texture.outputs["Color"], separate.inputs["Vector"])
|
||||
relative_depth = nodes.new("ShaderNodeMath")
|
||||
relative_depth.operation = "SUBTRACT"
|
||||
relative_depth.location = (-600.0, -150.0)
|
||||
links.new(image_input.outputs["Reference Depth"], relative_depth.inputs[0])
|
||||
links.new(separate.outputs["X"], relative_depth.inputs[1])
|
||||
local_depth = nodes.new("ShaderNodeMath")
|
||||
local_depth.operation = "MULTIPLY"
|
||||
local_depth.location = (-350.0, -150.0)
|
||||
links.new(relative_depth.outputs[0], local_depth.inputs[0])
|
||||
links.new(image_input.outputs["Uniform Scale"], local_depth.inputs[1])
|
||||
raw_depth = nodes.new("ShaderNodeMath")
|
||||
raw_depth.operation = "MULTIPLY"
|
||||
raw_depth.location = (-100.0, 150.0)
|
||||
links.new(local_depth.outputs[0], raw_depth.inputs[0])
|
||||
links.new(shape_input.outputs["Depth Amount"], raw_depth.inputs[1])
|
||||
inward_limit = nodes.new("ShaderNodeMath")
|
||||
inward_limit.operation = "MULTIPLY"
|
||||
inward_limit.inputs[1].default_value = -0.98
|
||||
inward_limit.location = (-100.0, -50.0)
|
||||
links.new(shape_input.outputs["Thickness"], inward_limit.inputs[0])
|
||||
clamp = nodes.new("ShaderNodeMath")
|
||||
clamp.operation = "MAXIMUM"
|
||||
clamp.location = (150.0, 50.0)
|
||||
links.new(raw_depth.outputs[0], clamp.inputs[0])
|
||||
links.new(inward_limit.outputs[0], clamp.inputs[1])
|
||||
has_thickness = nodes.new("ShaderNodeMath")
|
||||
has_thickness.operation = "GREATER_THAN"
|
||||
has_thickness.inputs[1].default_value = 1e-6
|
||||
has_thickness.location = (-100.0, -350.0)
|
||||
links.new(shape_input.outputs["Thickness"], has_thickness.inputs[0])
|
||||
choose_depth = nodes.new("GeometryNodeSwitch")
|
||||
choose_depth.input_type = "FLOAT"
|
||||
choose_depth.location = (400.0, 50.0)
|
||||
links.new(has_thickness.outputs[0], choose_depth.inputs["Switch"])
|
||||
links.new(raw_depth.outputs[0], choose_depth.inputs["False"])
|
||||
links.new(clamp.outputs[0], choose_depth.inputs["True"])
|
||||
combine = nodes.new("ShaderNodeCombineXYZ")
|
||||
combine.location = (600.0, 50.0)
|
||||
links.new(choose_depth.outputs["Output"], combine.inputs["Z"])
|
||||
front = nodes.new("FunctionNodeBooleanMath")
|
||||
front.operation = "NOT"
|
||||
front.location = (400.0, 300.0)
|
||||
links.new(extrude.outputs["Top"], front.inputs[0])
|
||||
set_position = nodes.new("GeometryNodeSetPosition")
|
||||
set_position.location = (800.0, 450.0)
|
||||
links.new(geometry, set_position.inputs["Geometry"])
|
||||
links.new(front.outputs[0], set_position.inputs["Selection"])
|
||||
links.new(combine.outputs["Vector"], set_position.inputs["Offset"])
|
||||
geometry = set_position.outputs["Geometry"]
|
||||
|
||||
zero_thickness = nodes.new("ShaderNodeMath")
|
||||
zero_thickness.operation = "LESS_THAN"
|
||||
zero_thickness.inputs[1].default_value = 1e-6
|
||||
zero_thickness.location = (1000.0, -150.0)
|
||||
links.new(cleanup_input.outputs["Thickness"], zero_thickness.inputs[0])
|
||||
back_or_side = nodes.new("FunctionNodeBooleanMath")
|
||||
back_or_side.operation = "OR"
|
||||
back_or_side.location = (1000.0, 150.0)
|
||||
links.new(extrude.outputs["Top"], back_or_side.inputs[0])
|
||||
links.new(extrude.outputs["Side"], back_or_side.inputs[1])
|
||||
delete_selection = nodes.new("FunctionNodeBooleanMath")
|
||||
delete_selection.operation = "AND"
|
||||
delete_selection.location = (1200.0, 50.0)
|
||||
links.new(zero_thickness.outputs[0], delete_selection.inputs[0])
|
||||
links.new(back_or_side.outputs[0], delete_selection.inputs[1])
|
||||
delete_geometry = nodes.new("GeometryNodeDeleteGeometry")
|
||||
delete_geometry.domain = "FACE"
|
||||
delete_geometry.location = (1350.0, 450.0)
|
||||
links.new(geometry, delete_geometry.inputs["Geometry"])
|
||||
links.new(delete_selection.outputs[0], delete_geometry.inputs["Selection"])
|
||||
shade_smooth = nodes.new("GeometryNodeSetShadeSmooth")
|
||||
shade_smooth.domain = "FACE"
|
||||
shade_smooth.inputs["Shade Smooth"].default_value = True
|
||||
shade_smooth.location = (1600.0, 450.0)
|
||||
links.new(delete_geometry.outputs["Geometry"], shade_smooth.inputs["Geometry"])
|
||||
links.new(shade_smooth.outputs["Geometry"], group_output.inputs["Geometry"])
|
||||
group.use_fake_user = True
|
||||
return group
|
||||
return load_asset_node_group(DEPTH_PLANE_NODE_GROUP_NAME)
|
||||
|
||||
|
||||
def plane_node_group(shape):
|
||||
|
||||
@@ -10,6 +10,7 @@ from ..common.image_data import (
|
||||
)
|
||||
from ..common.depth_data import camera_depth_values, depth_uniform_scale
|
||||
from ..common.mesh_result import (
|
||||
IMAGE_MATERIAL_NODE_GROUP_NAME,
|
||||
create_image_material,
|
||||
finalize_object_result,
|
||||
load_asset_node_group,
|
||||
@@ -30,6 +31,7 @@ from .geometry import (
|
||||
)
|
||||
from .shape import (
|
||||
BALLOON_ATTRIBUTE_NAME,
|
||||
BALLOON_CUTOUT_SHAPES,
|
||||
CUTOUT_NODE_GROUP_NAME,
|
||||
CUTOUT_SHAPE_INDICES,
|
||||
DEPTH_CUTOUT_SHAPES,
|
||||
@@ -124,6 +126,24 @@ def load_cutout_node_group():
|
||||
return load_asset_node_group(CUTOUT_NODE_GROUP_NAME)
|
||||
|
||||
|
||||
def _connect_balloon_normal_scale(material):
|
||||
nodes = material.node_tree.nodes
|
||||
image_layer = next(
|
||||
node
|
||||
for node in nodes
|
||||
if node.bl_idname == "ShaderNodeGroup"
|
||||
and node.node_tree is not None
|
||||
and node.node_tree.name == IMAGE_MATERIAL_NODE_GROUP_NAME
|
||||
)
|
||||
attribute = nodes.new("ShaderNodeAttribute")
|
||||
attribute.attribute_type = "GEOMETRY"
|
||||
attribute.attribute_name = BALLOON_ATTRIBUTE_NAME
|
||||
attribute.location = (-550.0, -250.0)
|
||||
material.node_tree.links.new(
|
||||
attribute.outputs["Fac"], image_layer.inputs["Normal Scale"]
|
||||
)
|
||||
|
||||
|
||||
def create_shape_object(
|
||||
context,
|
||||
source_object,
|
||||
@@ -178,6 +198,8 @@ def create_shape_object(
|
||||
scene=context.scene,
|
||||
)
|
||||
depth_reference = None
|
||||
if shape in BALLOON_CUTOUT_SHAPES:
|
||||
_connect_balloon_normal_scale(material)
|
||||
uniform_scale = None
|
||||
depth_direction = None
|
||||
if shape in DEPTH_CUTOUT_SHAPES:
|
||||
|
||||
@@ -19,3 +19,4 @@ CUTOUT_SHAPE_INDICES = {
|
||||
}
|
||||
CUTOUT_SHAPES = frozenset(CUTOUT_NODE_GROUP_NAMES)
|
||||
DEPTH_CUTOUT_SHAPES = frozenset({"DEPTH_BALLOON", "DEPTH_SURFACE"})
|
||||
BALLOON_CUTOUT_SHAPES = frozenset({"BALLOON", "DEPTH_BALLOON"})
|
||||
|
||||
Reference in New Issue
Block a user