How to edit a value inside a shader?

Godot Version

4.3

Question

Help Programming Shaders
I’ve seen people using material.set_shader_param() to modify the values inside a shader, but I cannot make it work, this is the code that I’m using:

func _ready() -> void: #Gives a random skin to the passenger
	rng = RandomNumberGenerator.new()
	shirt = Vector3(rng.randi_range(0,255),rng.randi_range(0,255),rng.randi_range(0,255))
	material.set_shader_param("new_color", shirt)

The error it gives me says Attempt to call "set_shader_param" in base "null instance" on a null instance.
Any help on how to fix this would help me a lot, thanks in advance.

Edit: I was missing the material, so it was giving me that error. The main error now is “Invalid call. Nonexistent function "set_shader_param" in set "ShaderMaterial

Where are you getting material from? What type of node is this script on? Can we see the entire script?

extends CharacterBody2D

const SPEED:float = 300.0
const humanShader:Resource = preload("res://other/shaders/passenger.gdshader")
const passengerShader:Resource = preload("res://other/shaders/passenger.gdshader")
var isPassenger:bool = false
var rng:RandomNumberGenerator

@onready var sprite:Sprite2D = $Sprite2D

var shirt:Vector3

func _ready() -> void: #Gives a random skin to the passenger
	rng = RandomNumberGenerator.new()
	shirt = Vector3(rng.randi_range(0,255),rng.randi_range(0,255),rng.randi_range(0,255))
	material.set_shader_param("new_color", shirt)
	var weights = PackedFloat32Array([0.7, 1, 0.3, 1, 1])
	var randomNumber:int = rng.rand_weighted(weights)
	match randomNumber:
		0: sprite.texture = load("res://sprites/npcs/baldMan.png")
		1: sprite.texture = load("res://sprites/npcs/hoodieMan.png")
		2: sprite.texture = load("res://sprites/npcs/jonkler.png")
		3: sprite.texture = load("res://sprites/npcs/man.png")
		4: sprite.texture = load("res://sprites/npcs/woman.png")	
	rng = null
	
func _physics_process(delta: float) -> void:
	if isPassenger:
		if sprite.material.shader != passengerShader: 
			sprite.material = ShaderMaterial.new()
			sprite.material.shader = Shader.new()
			sprite.material.shader = passengerShader
	move_and_slide()


func updatePassenger() -> void:
	rng = RandomNumberGenerator.new()
	var randomNumber = rng.randf_range(0, 100)
	if randomNumber == 1: isPassenger = true
	if isPassenger == true: sprite.material.shader = passengerShader
	else: sprite.material.shader = humanShader
	rng = null
		
func _visible_entered() -> void:
	if isPassenger: sprite.material.shader = passengerShader
	#sprite.visible = true
	
func _visible_exited() -> void:
	sprite.material.shader = humanShader
	#sprite.visible = false

If I try adding sprite before (sprite.material.set_shader_param("new_color", shirt)), it says that it cannot find the function.
P.S. I just found out the first error it gave me (Attempt to call "set_shader_param" in base "null instance" on a null instance) was happening because CharacterBody2D didn’t have a material, now the problem is “Invalid call. Nonexistent function "set_shader_param" in set "ShaderMaterial

I think you’re looking to set_shader_parameter. See docs: ShaderMaterial — Godot Engine (stable) documentation in English

1 Like

That worked in Godot 3. You must use set_shader_parameter() in Godot 4.

1 Like