2D Shader Uniform Variables not reaching Material Shader
Asked Answered
L

6

0

I am working on a 2D platformer game where I need to develop what seems should be a simple screen shader which turns the ocean dark as the coordinate y pixels during game play get "deeper" or more positive. I have gd script code passing the two global values to my shader material but I must be addressing the shader incorrectly as it is not being seen by the shader. A screenshot of the game play showing the script and that the uniforms are working correctly in the script....

And now the shader parameters are shown in the same live run.

I have looked at tutorials - to the best of my knowledge there are no typos or misspellings. I have been struggling with this. It may be that I am not coding the "self.material" in my gd script correctly. Not sure how else to write it.

Ludivinaludlew answered 8/5, 2022 at 11:14 Comment(0)
L
0

And a copy of the shader code:

shader_type canvas_item;

uniform vec2 global_posit;
uniform float ocean_depth;
uniform vec4 deep_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
varying float depth_factor; 
//	self.material.set_shader_param("ocean_depth", ocean_depth)
//	self.material.set_shader_param("global_posit", global_posit)

void fragment() {
	vec3 c = texture(SCREEN_TEXTURE, SCREEN_UV).rgb;
	depth_factor = (FRAGCOORD.y)/ocean_depth;
	c.rgb = mix(c.rgb, deep_color.rgb, depth_factor);
	COLOR.rgb = c.rgb;
}
Ludivinaludlew answered 8/5, 2022 at 11:15 Comment(0)
L
0

Okay - I must have missed a tutorial note. Why do you have to select local to scene in the inspector when I trying to pass the uniform code to the shader? I made a couple of changes... to my script which is shown in the two pictures; I changed "self.get_material().set_shader_param()" to "self.material.set_shader_param()".

2nd - I simply clicked "local to scene" as true. Then it started updating my parameters real time! If anyone has a quick answer to why the need for local to scene so I understand better I would appreciate it.

EDIT: The local to scene had nothing to do with it. I tried to use "get_material()" and apparently that did not work. I changed back to self.material. and it works.

Unfortunately, can't get my shader to actually darken the screen....

Ludivinaludlew answered 8/5, 2022 at 11:26 Comment(0)
L
0

@joedad said: Okay - I must have missed a tutorial note. Why do you have to select local to scene in the inspector when I trying to pass the uniform code to the shader? I made a couple of changes... to my script which is shown in the two pictures; I changed "self.get_material().set_shader_param()" to "self.material.set_shader_param()".

2nd - I simply clicked "local to scene" as true. Then it started updating my parameters real time! If anyone has a quick answer to why the need for local to scene so I understand better I would appreciate it.

EDIT: The local to scene had nothing to do with it. I tried to use "get_material()" and apparently that did not work. I changed back to self.material. and it works.

Unfortunately, can't get my shader to actually darken the screen....

UPDATE: Shader is working! Easily and very well I might add. So my trouble was not passing the uniform to the shader code and it was not finding the "correct shader material". The trouble turned out to be trying to change variables within the shader incorrectly. I simply changed my method of updating the shader to be based on the global position and ocean depth instead of trying to get each screen line to have a different depth factor. I feed the Depth Factor from the gd_script into the shader. Turns out this is a LOT simpler and looks more realistic in my opinion. Final Shader code below....

shader_type canvas_item;

uniform vec4 deep_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform float depth_factor;

void fragment() {
	vec3 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb;
	c.rgb = mix(c.rgb, deep_color.rgb, depth_factor);
	COLOR.rgb = c;
}
Ludivinaludlew answered 9/5, 2022 at 11:26 Comment(0)
L
0

Final gd script code:

## deeptexture node script; defines uniforms for use in the material shader
extends ColorRect

## Currently entire scene needs to be a child of GameLevel.tscn
onready var my_parent = get_parent().get_parent().get_parent().get_node("GameLevel")
onready var player = get_parent().get_parent().get_node("RescueSub")
onready var global_posit = player.global_position    ## current screen depth calculated from Player y position + 450
onready var ocean_depth = my_parent.depth_get()  ## Max ocean depth from stage generator
onready var depth_factor

func _ready():
	pass

func _physics_process(_delta):
	ocean_depth = float(my_parent.depth_get())
	global_posit = player.global_position
	depth_factor = float(global_posit.y/ocean_depth)
	self.material.set_shader_param("depth_factor", depth_factor)
Ludivinaludlew answered 9/5, 2022 at 11:28 Comment(0)
L
0

A picture of the effect as it stands now. My only possible add is to work out a method to get the lights to work within the ocean deep better. As it stands now the Shader works on the light2d texture as well and when it is black the lights do not help the player.

Ludivinaludlew answered 9/5, 2022 at 11:42 Comment(0)
L
0

Okay - not sure where the picture was from my previous post but the final game is here: https://joehubdad.itch.io/submarine-rescue-ops.

You can watch the video, download the Windows executable or play via the web at the above website.

Ludivinaludlew answered 5/11, 2022 at 2:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.