RenderingServer.material_set_param
最后同步日期:2026-04-15 | Godot 官方原文 — RenderingServer.material_set_param
RenderingServer.material_set_param
定义
RenderingServer.material_set_param() 是底层渲染服务器提供的方法,用于动态修改材质(Material)的着色器参数。
你可以把材质想象成"衣服",着色器参数就是"衣服上的颜色、花纹、透明度"等属性。普通开发中我们用的是 ShaderMaterial 节点上的 SetShaderParameter() 方法。而 RenderingServer.material_set_param() 则直接在渲染服务器层面操作,不需要通过节点,速度更快,适合需要频繁更新材质参数的场景(如大量物体的颜色变化、动态环境效果等)。
函数签名
public static void MaterialSetParam(Rid material, stringName parameter, Variant value)func material_set_param(material: RID, parameter: StringName, value: Variant) -> void参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
material | Rid | 是 | 目标材质的 RID。可以是通过 RenderingServer.MaterialCreate() 创建的,也可以从已有材质获取 |
parameter | StringName | 是 | 着色器参数的名称。必须与着色器代码中 uniform 声明的变量名完全一致 |
value | Variant | 是 | 要设置的参数值。类型必须与着色器中声明的 uniform 类型匹配 |
返回值
无返回值(void)。这是一个纯操作函数,设置后立即生效。
代码示例
基础用法:修改着色器参数
using Godot;
/// <summary>
/// 假设我们有一个着色器,里面声明了:
/// uniform vec4 albedo_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
/// uniform float glow_intensity = 0.0;
/// 下面演示如何通过 RenderingServer 修改这些参数。
/// </summary>
public partial class MaterialParamDemo : Node
{
private Rid _materialRid;
public override void _Ready()
{
// 假设场景中有一个 MeshInstance3D 使用了 ShaderMaterial
var mesh = GetNode<MeshInstance3D>("Model");
// 获取材质的 RID
var shaderMat = mesh.GetSurfaceOverrideMaterial(0) as ShaderMaterial;
if (shaderMat != null)
{
_materialRid = shaderMat.GetRid();
// 修改颜色为红色
RenderingServer.MaterialSetParam(
_materialRid,
"albedo_color",
new Color(1f, 0.2f, 0.2f, 1f)
);
// 设置发光强度
RenderingServer.MaterialSetParam(
_materialRid,
"glow_intensity",
0.8f
);
GD.Print("材质参数已修改");
// 运行结果: 材质参数已修改
}
}
}extends Node
## 假设我们有一个着色器,里面声明了:
## uniform vec4 albedo_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
## uniform float glow_intensity = 0.0;
## 下面演示如何通过 RenderingServer 修改这些参数。
var _material_rid: RID
func _ready():
# 假设场景中有一个 MeshInstance3D 使用了 ShaderMaterial
var mesh = %Model as MeshInstance3D
# 获取材质的 RID
var shader_mat = mesh.get_surface_override_material(0) as ShaderMaterial
if shader_mat:
_material_rid = shader_mat.get_rid()
# 修改颜色为红色
RenderingServer.material_set_param(
_material_rid,
"albedo_color",
Color(1.0, 0.2, 0.2, 1.0)
)
# 设置发光强度
RenderingServer.material_set_param(
_material_rid,
"glow_intensity",
0.8
)
print("材质参数已修改")
# 运行结果: 材质参数已修改实际场景:批量修改大量物体的材质颜色
using Godot;
/// <summary>
/// 团队颜色系统:根据玩家所属阵营,批量修改所有单位材质的颜色。
/// 比如即时战略游戏中的"红队 vs 蓝队"。
/// </summary>
public partial class TeamColorSystem : Node
{
[Export] public Color ExTeamRedColor = new(0.9f, 0.15f, 0.15f);
[Export] public Color ExTeamBlueColor = new(0.15f, 0.3f, 0.9f);
public enum EnumTeam { Red, Blue }
/// <summary>
/// 将指定节点下所有 MeshInstance3D 的 team_color 着色器参数设为对应阵营颜色
/// </summary>
public void ApplyTeamColor(Node3D unitRoot, EnumTeam team)
{
var color = team == EnumTeam.Red ? ExTeamRedColor : ExTeamBlueColor;
// 递归查找所有 MeshInstance3D
ApplyColorRecursive(unitRoot, color);
GD.Print($"已为 {unitRoot.Name} 应用 {(team == EnumTeam.Red ? "红队" : "蓝队")} 颜色");
// 运行结果: 已为 Unit_01 应用 红队 颜色
}
private void ApplyColorRecursive(Node node, Color teamColor)
{
if (node is MeshInstance3D mesh && mesh.GetSurfaceOverrideMaterial(0) is ShaderMaterial mat)
{
var matRid = mat.GetRid();
RenderingServer.MaterialSetParam(matRid, "team_color", teamColor);
}
foreach (var child in node.GetChildren())
{
ApplyColorRecursive(child, teamColor);
}
}
}extends Node
## 团队颜色系统:根据玩家所属阵营,批量修改所有单位材质的颜色。
## 比如即时战略游戏中的"红队 vs 蓝队"。
@export var team_red_color: Color = Color(0.9, 0.15, 0.15)
@export var team_blue_color: Color = Color(0.15, 0.3, 0.9)
enum Team { RED, BLUE }
## 将指定节点下所有 MeshInstance3D 的 team_color 着色器参数设为对应阵营颜色
func apply_team_color(unit_root: Node3D, team: Team) -> void:
var color = team_red_color if team == Team.RED else team_blue_color
# 递归查找所有 MeshInstance3D
_apply_color_recursive(unit_root, color)
var team_name = "红队" if team == Team.RED else "蓝队"
print("已为 %s 应用 %s 颜色" % [unit_root.name, team_name])
# 运行结果: 已为 Unit_01 应用 红队 颜色
func _apply_color_recursive(node: Node, team_color: Color) -> void:
if node is MeshInstance3D:
var mesh = node as MeshInstance3D
var mat = mesh.get_surface_override_material(0) as ShaderMaterial
if mat:
var mat_rid = mat.get_rid()
RenderingServer.material_set_param(mat_rid, "team_color", team_color)
for child in node.get_children():
_apply_color_recursive(child, team_color)进阶用法:动画化着色器参数实现动态效果
using Godot;
/// <summary>
/// 通过每帧更新着色器参数实现动态视觉效果。
/// 示例:角色受伤时的闪烁效果,和死亡时的溶解效果。
/// </summary>
public partial class ShaderEffectPlayer : Node3D
{
private Rid _materialRid;
private float _hitFlashTimer = 0f;
private float _dissolveProgress = 0f;
[Export] public MeshInstance3D TargetMesh { get; set; }
[Export] public float ExFlashDuration = 0.15f;
[Export] public float ExDissolveSpeed = 0.5f;
private bool _isDissolving = false;
public override void _Ready()
{
if (TargetMesh != null && TargetMesh.GetSurfaceOverrideMaterial(0) is ShaderMaterial mat)
{
_materialRid = mat.GetRid();
// 初始化着色器参数
RenderingServer.MaterialSetParam(_materialRid, "hit_flash", 0f);
RenderingServer.MaterialSetParam(_materialRid, "dissolve_threshold", 0f);
}
}
/// <summary>
/// 触发受击闪烁效果
/// </summary>
public void OnHit()
{
_hitFlashTimer = ExFlashDuration;
RenderingServer.MaterialSetParam(_materialRid, "hit_flash", 1f);
}
/// <summary>
/// 开始溶解效果(死亡动画)
/// </summary>
public void StartDissolve()
{
_isDissolving = true;
_dissolveProgress = 0f;
}
public override void _Process(double delta)
{
var dt = (float)delta;
// 受击闪烁倒计时
if (_hitFlashTimer > 0f)
{
_hitFlashTimer -= dt;
if (_hitFlashTimer <= 0f)
{
RenderingServer.MaterialSetParam(_materialRid, "hit_flash", 0f);
}
}
// 溶解效果推进
if (_isDissolving)
{
_dissolveProgress += dt * ExDissolveSpeed;
if (_dissolveProgress >= 1f)
{
_dissolveProgress = 1f;
_isDissolving = false;
GD.Print("溶解完成");
// 运行结果: 溶解完成
}
RenderingServer.MaterialSetParam(_materialRid, "dissolve_threshold", _dissolveProgress);
}
}
}extends Node3D
## 通过每帧更新着色器参数实现动态视觉效果。
## 示例:角色受伤时的闪烁效果,和死亡时的溶解效果。
@export var target_mesh: MeshInstance3D
@export var flash_duration: float = 0.15
@export var dissolve_speed: float = 0.5
var _material_rid: RID
var _hit_flash_timer: float = 0.0
var _dissolve_progress: float = 0.0
var _is_dissolving: bool = false
func _ready():
if target_mesh:
var mat = target_mesh.get_surface_override_material(0) as ShaderMaterial
if mat:
_material_rid = mat.get_rid()
# 初始化着色器参数
RenderingServer.material_set_param(_material_rid, "hit_flash", 0.0)
RenderingServer.material_set_param(_material_rid, "dissolve_threshold", 0.0)
## 触发受击闪烁效果
func on_hit() -> void:
_hit_flash_timer = flash_duration
RenderingServer.material_set_param(_material_rid, "hit_flash", 1.0)
## 开始溶解效果(死亡动画)
func start_dissolve() -> void:
_is_dissolving = true
_dissolve_progress = 0.0
func _process(delta: float) -> void:
# 受击闪烁倒计时
if _hit_flash_timer > 0.0:
_hit_flash_timer -= delta
if _hit_flash_timer <= 0.0:
RenderingServer.material_set_param(_material_rid, "hit_flash", 0.0)
# 溶解效果推进
if _is_dissolving:
_dissolve_progress += delta * dissolve_speed
if _dissolve_progress >= 1.0:
_dissolve_progress = 1.0
_is_dissolving = false
print("溶解完成")
# 运行结果: 溶解完成
RenderingServer.material_set_param(_material_rid, "dissolve_threshold", _dissolve_progress)注意事项
参数名必须与着色器 uniform 完全匹配:
parameter参数中的字符串必须和着色器代码中uniform变量的名称一字不差,包括大小写。如果名称不匹配,调用不会报错但也不会有任何效果。值的类型必须匹配:传入的
value类型需要与着色器中声明的 uniform 类型一致。比如着色器中声明了uniform float,你传入一个整数也可以(会自动转换),但如果声明了uniform vec4而你传入一个 float,则可能无法正常工作。也可以从 ShaderMaterial 获取 RID:不需要一定要用
RenderingServer.MaterialCreate()创建材质。你可以从场景中已有的ShaderMaterial通过GetRid()/get_rid()获取 RID,然后用此方法修改参数。性能优势:相比通过
ShaderMaterial.SetShaderParameter()修改参数,直接使用 RenderingServer API 省去了节点层面的中间步骤,在需要频繁修改大量材质参数时性能更好。修改立即生效:调用后参数会立即更新,不需要额外的"提交"或"刷新"操作。如果你在
_Process中每帧更新参数,效果会实时反映在画面上。
