[Godot 4] How to update shader global uniform correctly?
Asked Answered
H

8

0

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

Hafer answered 26/3, 2022 at 14:11 Comment(0)
E
0

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.

Elope answered 26/3, 2022 at 19:27 Comment(0)
H
0

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.

Hafer answered 26/3, 2022 at 20:0 Comment(0)
E
0

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

Elope answered 27/3, 2022 at 2:31 Comment(0)
H
0

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

Hafer answered 28/3, 2022 at 8:59 Comment(0)
H
0

I created an issue: https://github.com/godotengine/godot/issues/59645 And I will update here when I know the proper way to do it, or if the issue is fixed

Hafer answered 28/3, 2022 at 20:59 Comment(0)
H
0

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

Hafer answered 3/4, 2022 at 10:44 Comment(0)
G
0

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

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

Glassy answered 4/4, 2022 at 18:23 Comment(0)
H
0

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

Hafer answered 4/4, 2022 at 19:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.