Making the fog shader move based on movement

Godot Version

4.2.1

Question

ezgif-1-c75e306472

I got this shader that gives this fog effect, the problem I have with it, is when the character moves the fog doesnt move(not that it should, it doesnt have the code!) and i have no idea how to make that effect with code, can someone help? this is the code for shader:

shader_type canvas_item;

// Credit for the original shader goes to Gonkee: https://github.com/Gonkee/Gonkees-Shaders/blob/master/fog.shader
// Pixelate by Godot Shaders: https://godotshaders.com/shader/pixelate/

uniform vec4 color : source_color;
uniform int OCTAVES = 10;
uniform bool enable_pixelation = true;
uniform int pixelation_amount = 150;
uniform sampler2D fog_mask;  // Texture mask for fog control
uniform vec2 fog_direction = vec2(1.0, 1.0); // Use -1 and 1 values to change direction. Increase the speed in that direction with values higher/lower than 1
uniform bool scroll_noise_tex = false; 
uniform vec2 noise_scroll_direction = vec2(1.0, 0.0);  // Direction to scroll the noise texture
// Noise texture
uniform sampler2D noise_texture: repeat_enable, filter_nearest;
// Fog density
uniform float density: hint_range(0.0, 1.0) = 0.25;
// Fog speed
uniform vec2 speed = vec2(0.02, 0.01);

float rand(vec2 coord){
    return fract(sin(dot(coord, vec2(56, 78)) * 1000.0) * 1000.0);
}

float noise(vec2 coord){
    vec2 i = floor(coord);
    vec2 f = fract(coord);

    float a = rand(i);
    float b = rand(i + vec2(1.0, 0.0));
    float c = rand(i + vec2(0.0, 1.0));
    float d = rand(i + vec2(1.0, 1.0));

    vec2 cubic = f * f * (3.0 - 2.0 * f);

    return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;
}

float fbm(vec2 coord){
    float value = 0.0;
    float scale = 0.5;

    for(int i = 0; i < OCTAVES; i++){
        value += noise(coord) * scale;
        coord *= 2.0;
        scale *= 0.5;
    }
    return value;
}

void fragment() {
	vec2 uv = UV + speed * TIME;
	// Sample the noise texture
	float noise = texture(noise_texture, uv).r;
	// Convert the noise from the (0.0, 1.0) range to the (-1.0, 1.0) range
	// and clamp it between 0.0 and 1.0 again
	float fog = clamp(noise * 2.0 - 1.0, 0.0, 1.0);
	// Apply the fog effect
	COLOR.a *= fog * density;
	
    vec2 grid_uv = UV;
    if (enable_pixelation) {
        grid_uv = round(UV * float(pixelation_amount)) / float(pixelation_amount);
    }
    
    // Compute noise based on pixelated or non-pixelated coordinates
    vec2 coord = grid_uv * 5.0;

    // Scroll the noise texture if enabled
    if (scroll_noise_tex) {
        coord += noise_scroll_direction * TIME;
    }

    vec2 motion = vec2(fbm(coord + fog_direction * TIME*.5));

    float final = fbm(coord + motion);
    
    // Get the fog density from the texture mask
    float mask_value = texture(fog_mask, UV).r;  // Assuming the mask is grayscale
    
    // Modulate the fog density by the mask value
    final *= mask_value;

    // Use the alpha value of the color to control the overall fog opacity
    COLOR = vec4(color.rgb, final * color.a * 0.5);
}

and I did try to ask chat gpt what to do and it told me to write this line of code in the map, but it didnt work at all, it just made the fog thicker:

extends Node2D

@onready var setfog = $CanvasLayer/ColorRect2  # ColorRect for the fog's visual
@onready var char = $player  # Reference to the player node
@onready var fogshader = $CanvasLayer/ColorRect  # ColorRect for the fog shader
var last_position = Vector2.ZERO
var player_move_direction = Vector2.ZERO  # To track player movement direction

# Fog movement speed multiplier (increase to make the fog move faster)
var fog_speed_multiplier = 2.0  # Increase this value for faster fog movement

# Called when the node enters the scene tree for the first time
func _ready():
	# Ensure the fog shader has a ShaderMaterial assigned
	var shader_material = ShaderMaterial.new()
	shader_material.shader = load("res://Scenes/test_tile.gdshader")  # Update with your shader path
	fogshader.material = shader_material

	last_position = char.position  # Set the initial position of the player

# Called every frame to update the fog and movement
func _process(delta):
	update_fog_opacity(delta)
	update_fog_movement(delta)

# Update fog opacity based on player's vertical movement
func update_fog_opacity(delta):
	var direction = char.position - last_position
	last_position = char.position  # Update the last position to the current position

	if direction.y < 0:  # Moving up
		setfog.color = Color(1, 1, 1, max(0.1, setfog.color.a - 0.05 * delta))  # Reduce opacity
	elif direction.y > 0:  # Moving down
		setfog.color = Color(1, 1, 1, min(1.0, setfog.color.a + 0.05 * delta))  # Increase opacity

# Update the fog movement based on the player's direction
func update_fog_movement(delta):
	# Calculate the movement direction from the player's current and last positions
	player_move_direction = (char.position - last_position).normalized()

	# Invert the direction to make the fog move opposite of the player
	var fog_direction = -player_move_direction * fog_speed_multiplier  # Multiply by fog speed multiplier

	# Update shader parameter for fog movement direction
	var shader_material = fogshader.material as ShaderMaterial
	if shader_material:
		shader_material.set_shader_parameter("player_move_direction", fog_direction)  # Pass the inverted direction to the shader

I do not know how to do this with shaders but you can use ParallaxBackground and ParallaxLayer to make the fog move with the camera.

Also in 4.3 there is 2D Parallax.

1 Like

I dont think i can use parallax for shaders

Maybe you need to flip the fog direction

player_move_direction = last_position.direction_to(char.position)
1 Like

you mean flip_h? if so, flip does not work for shaders.

No, like calculate the fog in the opposite direction of the player movement.

1 Like

I have no idea how to do that mate

Ah I didn’t see that you used ChatGPT, therefor this entire section is worthless. your shader does not even have a player_direction uniform.


Your shader has a noise_scroll_direction you could edit to face the oposite of the player’s movement direction.

1 Like

I dont know anything about the codes of shader and things…

What do you have for your player? Can you locate a variable within their script similar to a movement direction?

1 Like

you mean direction from the scene code or shader code?