Spotlight Effect/Transition with Feathering & Position

Shader code
shader_type canvas_item;
render_mode unshaded;

uniform float circle_size = 0.5;
uniform float feather = 0.05;
uniform vec2 circle_position = vec2(0.5, 0.5);
uniform float screen_width = 1920;
uniform float screen_height = 1080;

void fragment() {
    float ratio = screen_width / screen_height;
    vec2 adjusted_uv = vec2(mix(circle_position.x, UV.x, ratio), UV.y);
    float dist = distance(circle_position, adjusted_uv);
    float edge_start = circle_size - feather;
    float edge_end = circle_size + feather;
    COLOR.a = smoothstep(edge_start, edge_end, dist);
}
Tags
circle, spotlight, transition
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Circle Mask (with Feathering & Position)

Simple Transition Effect

Gentle Breathing Effect for Face & Body Animation

guest

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
casualtyxy
casualtyxy
9 months ago

Perfection!

Zibetnu
9 months ago

Thanks for posting this! It worked great in my game:
https://store.steampowered.com/news/app/2499500/view/693091765959262924

Gerardo LCDF
1 day ago

I have made this small script so that it follows the player with a simple incrementing animation and an offset from the player, as well as a small delay, in order to make it look more natural.

extends ColorRect
##nodo al cual va a seguir el circulo 
@export var player_node: Node2D 
const MAX_CIRCLE_SIZE = 0.075##el tamano al que se va a incrementar el circulo
const GROWTH_SPEED = 0.5 ## velocidad con la que va a seguir al nodo player
const FOLLOW_LERP_SPEED = 8.0 ##la velocidad a la que se a incrmenetqar y mover al player


var current_circle_size = 0.0
var target_circle_position = Vector2(0.5, 0.5) 


func _ready():
	if not material is ShaderMaterial:
		push_error("El nodo ColorRect2 debe tener un ShaderMaterial.")
		set_process(false)
		return
	material.set_shader_parameter("circle_size", 0.0)


func _process(delta):
	var shader_material: ShaderMaterial = material
	if current_circle_size < MAX_CIRCLE_SIZE:
		current_circle_size = min(current_circle_size + GROWTH_SPEED * delta, MAX_CIRCLE_SIZE)
		shader_material.set_shader_parameter("circle_size", current_circle_size)
	if player_node:


		var player_screen_pos = player_node.global_position
		var rect_size = size
		var player_uv_pos = player_screen_pos / rect_size
		
		target_circle_position = target_circle_position.lerp(player_uv_pos, delta * FOLLOW_LERP_SPEED)
		
		shader_material.set_shader_parameter("circle_position", target_circle_position)