I'm currently trying out the new shader globals in a project of mine. But I can't get it to update the value. I set up a very simple shader:

shader_type spatial;

uniform sampler2D _tex;
global uniform vec4 ccc;

void fragment() {
	ALBEDO = ccc.rgb;
}

And set it up in the project settings:

I'm using this shader in a simple plane, and added a script to change the global variable as below:

extends Node3D

func _enter_tree() -> void:
	print(ProjectSettings.get_setting("shader_globals/ccc"))
	ProjectSettings.set_setting("shader_globals/ccc", Color.RED)
	print(ProjectSettings.get_setting("shader_globals/ccc"))

But the image, nevertheless renders green, instead of red. The output from the code above is this:

--- Debugging process started ---
Godot Engine v4.0.alpha5.official.d7d528c15 - https://godotengine.org
Vulkan API 1.1.198 - Using Vulkan Device #0: AMD - AMD Radeon Pro 5300M
 
Registered camera OBS Virtual Camera with id 1 position 0 at index 0
Registered camera FaceTime HD Camera (Built-in) with id 2 position 0 at index 1
{type:color, value:(0, 1, 0, 1)}
(1, 0, 0, 1)
--- Debugging process stopped ---

So I tried to change the dictionary that is returned, to have the proper color:

extends Node3D

func _enter_tree() -> void:
	var dict = ProjectSettings.get_setting("shader_globals/ccc")
	print(dict)
	dict.value = Color.RED
	print(ProjectSettings.get_setting("shader_globals/ccc"))

The output looks better:

--- Debugging process started ---
Godot Engine v4.0.alpha5.official.d7d528c15 - https://godotengine.org
Vulkan API 1.1.198 - Using Vulkan Device #0: AMD - AMD Radeon Pro 5300M
 
Registered camera OBS Virtual Camera with id 1 position 0 at index 0
Registered camera FaceTime HD Camera (Built-in) with id 2 position 0 at index 1
{type:color, value:(0, 1, 0, 1)}
{type:color, value:(1, 0, 0, 1)}
--- Debugging process stopped ---

But it still renders green. And in the end I tried creating a new dictionary and setting it:

extends Node3D

func _enter_tree() -> void:
	print(ProjectSettings.get_setting("shader_globals/ccc"))
	ProjectSettings.set_setting("shader_globals/ccc", {type="color", value=Color.RED})
	print(ProjectSettings.get_setting("shader_globals/ccc"))

But that doesn't work either. Anyone have any idea on how it works, or anything that I missed or could try?

Thanks in advance, Corintho

Oh, that's pretty cool. Didn't even know they added that feature. However, I'm not sure if you can modify project settings at run-time. I think they only are used for the initial build/run. So maybe there is another way to access that variable directly, without using project settings. Or maybe that is not the intended purpose. But there should be some way.

Yeah, I thought of that possibility as well, but reading the article, what caught my attention was this: You may want to let your shaders know where the player is. As an example, the grass and some bushes will bend when the player is close, simulating being pushed The only way I can figure that working is if we can update the information in runtime. I was able to put up a workaround for now. I have a class that is responsible for generating the texture and it emits a signal, and the scripts that need that information can listen to it and update the shader params. So it's not a global uniform right now, but it got the job done for the time being.

Maybe make a repro project and submit a bug. That sounds like it's not working.

I will do that. I was just hoping I was missing something right now. And my work around proved to be quite involved when we have a lot of different shaders that read from the same information. This global uniform is really quite interesting

6 days later

I found how it works in code at least. Although it does not seem to be possible with Nodes yet. In the example above, the code should be: RenderingServer.global_variable_set("ccc", Color.RED) Although I was not able to read the values again from the RenderingServer

Although I was not able to read the values again from the RenderingServer

There's RenderingServer.global_variable_get(), did you try it?

Yes, I tried the get, but it never returned a value, always null, and the get_list always returned an empty list.

8 months later