This page documents the VisualShaderNode base class and the node system used in the Visual Shader Editor. It covers the port system (input/output ports), default values, node categories, constants, parameters, and the custom node extension mechanism. For information about the overall VisualShader graph structure and varying system, see page 12.1 (VisualShader Architecture). For details on shader code generation and compilation, see page 12.3 (Shader Code Generation).
VisualShaderNode is the abstract base class for all nodes in the visual shader graph. Each node represents a shader operation and defines a set of input and output ports with specific data types.
Key Responsibilities:
Sources: scene/resources/visual_shader.h269-390
Nodes communicate through typed ports. Each port has one of the following types:
| PortType | GLSL Type | Description |
|---|---|---|
PORT_TYPE_SCALAR | float | Floating-point scalar |
PORT_TYPE_SCALAR_INT | int | Integer scalar |
PORT_TYPE_SCALAR_UINT | uint | Unsigned integer scalar |
PORT_TYPE_VECTOR_2D | vec2 | 2D vector |
PORT_TYPE_VECTOR_3D | vec3 | 3D vector |
PORT_TYPE_VECTOR_4D | vec4 | 4D vector |
PORT_TYPE_BOOLEAN | bool | Boolean |
PORT_TYPE_TRANSFORM | mat4 | 4x4 transform matrix |
PORT_TYPE_SAMPLER | sampler reference | Texture sampler (input only) |
Sources: scene/resources/visual_shader.h272-284 doc/classes/VisualShaderNode.xml71-102
Each node subclass must implement these virtual methods to define its interface:
Sources: scene/resources/visual_shader.h320-337
Single-output vector ports can be "expanded" so each component (x, y, z, w) is exposed as a separate scalar output port. The base class tracks expanded state per port in expanded_output_ports (a HashMap<int, bool>). The method is_output_port_expandable() returns true only for vector ports on nodes with exactly one output port. The expanded count is accessible via get_expanded_output_port_count().
Sources: scene/resources/visual_shader.h354-359 scene/resources/visual_shader.cpp266-328
The VisualShaderNode base class tracks which ports are connected to support conditional logic and optimization:
Connection Tracking Methods:
is_input_port_connected(int p_port) - Check if an input port has a connectionis_output_port_connected(int p_port) - Check if an output port has connectionsset_input_port_connected() / set_output_port_connected() - Called by VisualShader to track connectionsThe output port map stores a count rather than a boolean, since one output can connect to multiple inputs.
Sources: scene/resources/visual_shader.h304-306 scene/resources/visual_shader.cpp222-260
When an input port is not connected, the node can use a default value. These values are stored per-port and can be set in the editor or programmatically.
Type Conversion: When changing a port connection that alters the expected type, the default value is intelligently converted. For example, if a float default value exists and the port type changes to vec3, the float is splatted to vec3(f, f, f).
Sources: scene/resources/visual_shader.cpp60-216 scene/resources/visual_shader.h326-331
Default values are serialized as a flat array for storage:
[port_index_0, value_0, port_index_1, value_1, ...]
This format is used by get_default_input_values() and set_default_input_values().
Sources: scene/resources/visual_shader.cpp390-407
Several abstract intermediate classes provide shared behavior for groups of nodes.
VisualShaderNodeVectorBase is the base for nodes that can operate on 2D, 3D, or 4D vectors interchangeably. Subclasses inherit an op_type property (OP_TYPE_VECTOR_2D, OP_TYPE_VECTOR_3D, OP_TYPE_VECTOR_4D) and the base class automatically maps that to the correct PORT_TYPE_VECTOR_* on both input and output ports.
Concrete subclasses include VisualShaderNodeVectorOp, VisualShaderNodeVectorFunc, VisualShaderNodeVectorLen, and others.
Sources: scene/resources/visual_shader_nodes.h43-81 scene/resources/visual_shader_nodes.cpp37-98
VisualShaderNodeResizableBase extends VisualShaderNode to support UI-level resizable nodes (such as VisualShaderNodeCurveTexture). VisualShaderNodeGroupBase further extends that for nodes that expose editable port lists (such as VisualShaderNodeExpression).
Sources: scene/resources/visual_shader.h608-680
Nodes are organized into categories for the editor's "Add Node" menu. The Category enum is defined on VisualShaderNode and each concrete class overrides get_category():
| Category | Purpose | Example Classes |
|---|---|---|
CATEGORY_OUTPUT | Final output nodes | VisualShaderNodeOutput |
CATEGORY_COLOR | Color operations | Color mixing, conversion |
CATEGORY_CONDITIONAL | Conditional logic | VisualShaderNodeIf, VisualShaderNodeSwitch, VisualShaderNodeCompare |
CATEGORY_INPUT | Built-in shader inputs and constants | VisualShaderNodeInput, VisualShaderNodeConstant subclasses |
CATEGORY_SCALAR | Scalar operations | VisualShaderNodeFloatOp, VisualShaderNodeFloatFunc |
CATEGORY_TEXTURES | Texture sampling | VisualShaderNodeTexture, SDF nodes |
CATEGORY_TRANSFORM | Transform operations | VisualShaderNodeTransformOp, VisualShaderNodeTransformFunc |
CATEGORY_UTILITY | Utility functions | VisualShaderNodeRemap, VisualShaderNodeRandomRange |
CATEGORY_VECTOR | Vector operations | VisualShaderNodeVectorBase subclasses |
CATEGORY_PARTICLE | Particle system nodes | VisualShaderNodeParticleEmitter subclasses |
CATEGORY_SPECIAL | Special nodes | VisualShaderNodeExpression, VisualShaderNodeCustom |
Sources: scene/resources/visual_shader.h286-300
Constant nodes output fixed values that can be edited in the editor. They have no input ports and a single output port.
Example: FloatConstant
The constant value is stored as a member variable (float constant) and exposed as an editable property.
Sources: scene/resources/visual_shader_nodes.h89-108 scene/resources/visual_shader_nodes.cpp100-679
Parameter nodes represent shader uniforms that can be set from code or the material inspector. They have no input ports and one output port.
Key Feature: Parameter Names
Each parameter node has a parameter_name that becomes the uniform name in the generated shader. The VisualShader class validates and ensures unique parameter names when nodes are added.
Sources: scene/resources/visual_shader_nodes.h1500-1900 scene/resources/visual_shader.cpp929-961
VisualShaderNodeInput provides access to built-in shader inputs like UV, VERTEX, NORMAL, TIME, etc. The available inputs depend on the shader mode (Spatial, CanvasItem, Particle, Sky, Fog) and shader type (Vertex, Fragment, Light).
Input Port Registry:
The ports static array in VisualShaderNodeInput contains all possible inputs with their mode, type, port type, name, and GLSL string. The node has one output port whose type matches the selected built-in input.
Sources: scene/resources/visual_shader.h494-551
VisualShaderNodeOutput is the final output node in each shader type's graph. It defines input ports for shader outputs like ALBEDO, NORMAL, EMISSION, etc.
Like VisualShaderNodeInput, output ports are defined in a static array (static const Port ports[]) and filtered by shader mode and type. The output node is always at node ID NODE_ID_OUTPUT (0) and is created automatically by VisualShader for each type graph.
Sources: scene/resources/visual_shader.h555-606
VisualShaderNodeCustom allows users to create custom nodes using GDScript by overriding virtual methods. This is the primary extension mechanism for the visual shader system.
Inheritance chain:
Virtual methods available for override:
| Method | Required | Description |
|---|---|---|
_get_name() | No | Node title in editor |
_get_description() | No | Tooltip in member dialog |
_get_category() | No | Menu path, e.g. "MyGame/Noise" |
_get_return_icon_type() | No | Icon port type |
_get_input_port_count() | Yes | Number of input ports |
_get_input_port_type(port) | No | Port type (default: PORT_TYPE_SCALAR) |
_get_input_port_name(port) | No | Port label |
_get_input_port_default_value(port) | No | Default value when disconnected |
_get_output_port_count() | Yes | Number of output ports |
_get_output_port_type(port) | No | Port type |
_get_output_port_name(port) | No | Port label |
_get_code(input_vars, output_vars, mode, type) | Yes | GLSL code string |
_get_global_code(mode) | No | Shader-global helpers |
_get_func_code(mode, type) | No | Per-function preamble |
_get_property_count() | No | Drop-down property count |
_get_property_name(index) | No | Property label |
_get_property_options(index) | No | Options array |
_get_property_default_index(index) | No | Default selection |
_is_highend() | No | Mark as high-end only |
_is_available(mode, type) | No | Filter by shader mode/type |
For a node to appear in the editor it must be a @tool script with a class_name.
The custom node system dynamically builds its port lists by calling virtual methods. update_ports() is called when a node is added to the graph (VisualShader::add_node()) or when a drop-down property changes (_set_option_index()).
Port data is stored in List<Port> input_ports and List<Port> output_ports inside VisualShaderNodeCustom. The runtime accessor methods (get_input_port_count(), get_input_port_type(), etc.) read from these lists.
Sources: scene/resources/visual_shader.cpp491-563 scene/resources/visual_shader.h396-413
The code generation flow for custom nodes:
User-provided code from _get_code() is indented and wrapped in a scoped block { } before being inserted into the final shader. This prevents local variable name collisions between nodes.
Global helpers from _get_global_code() are emitted once at the top of the shader (deduplicated by class name). Per-function preamble from _get_func_code() is emitted once at the beginning of each shader function.
Sources: scene/resources/visual_shader.cpp614-679
Custom nodes support drop-down properties for configuration. Properties are stored as a serialized string:
"property_index,selected_option_index;property_index,selected_option_index;..."
Methods:
_get_property_count() - Number of properties_get_property_name(index) - Property name_get_property_options(index) - Array of option strings_get_property_default_index(index) - Default selected indexget_option_index(option) - Get current selected indexSources: scene/resources/visual_shader.cpp493-510 scene/resources/visual_shader.cpp565-572 scene/resources/visual_shader.h404-413
Every VisualShaderNode subclass must implement generate_code() to produce GLSL shader code:
In addition to generate_code(), nodes can provide additional code segments that are inserted elsewhere in the generated shader:
| Method | Signature | Purpose |
|---|---|---|
generate_global() | (mode, type, id) | Uniform declarations or global variables, emitted once per node per shader type |
generate_global_per_node() | (mode, id) | Helper function definitions emitted once per node (shared across all types) |
generate_global_per_func() | (mode, type, id) | Code inserted at the beginning of each shader function body, once per type |
The distinction between generate_global() and generate_global_per_node() matters for helper functions that are referenced by multiple shader type stages — the _per_node variant guarantees they appear only once even when several types use the node.
Sources: scene/resources/visual_shader.h376-382 scene/resources/visual_shader.cpp370-382
As a concrete illustration, VisualShaderNodeFloatConstant::generate_code() simply assigns a literal float to the output variable:
See: scene/resources/visual_shader_nodes.cpp136-138
The output variable name (p_output_vars[0]) is provided by the VisualShader code generator and is unique per node per type. The node only has to produce the assignment body.
VisualShaderNodeTransformConstant::generate_code() assembles a mat4(...) literal from the stored Transform3D, transposing the basis because GLSL uses column-major order:
See: scene/resources/visual_shader_nodes.cpp644-653
All node classes are registered with Godot's class system using GDREGISTER_CLASS and GDREGISTER_ABSTRACT_CLASS macros inside register_scene_types(). Abstract classes (those that cannot be instantiated directly) use GDREGISTER_ABSTRACT_CLASS. The registration block for visual shader nodes spans:
See: scene/register_scene_types.cpp775-892
Registration makes each node class available to:
ResourceFormatSaverText, ResourceFormatLoaderText) for .tres serializationNode class hierarchy overview:
Sources: scene/register_scene_types.cpp775-892 scene/resources/visual_shader.h269-490 scene/resources/visual_shader_nodes.h43-450
Key Files:
VisualShaderNode and VisualShaderNodeCustom class definitionsRefresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.