Skip to content

Commit 3bc4ed3

Browse files
committed
feat(Card): add effect shaders on focus
1 parent 85ff606 commit 3bc4ed3

File tree

4 files changed

+280
-3
lines changed

4 files changed

+280
-3
lines changed

assets/shaders/god_rays.gdshader

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
Shader from Godot Shaders - the free shader library.
3+
godotshaders.com/shader/god-rays
4+
5+
Feel free to use, improve and change this shader according to your needs
6+
and consider sharing the modified result on godotshaders.com.
7+
*/
8+
9+
shader_type canvas_item;
10+
11+
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
12+
uniform float angle = -0.3;
13+
uniform float position = -0.2;
14+
uniform float spread : hint_range(0.0, 1.0) = 0.5;
15+
uniform float cutoff : hint_range(-1.0, 1.0) = 0.1;
16+
uniform float falloff : hint_range(0.0, 1.0) = 0.2;
17+
uniform float edge_fade : hint_range(0.0, 1.0) = 0.15;
18+
19+
uniform float speed = 1.0;
20+
uniform float ray1_density = 8.0;
21+
uniform float ray2_density = 30.0;
22+
uniform float ray2_intensity : hint_range(0.0, 1.0) = 0.3;
23+
24+
uniform vec4 color : source_color = vec4(1.0, 0.9, 0.65, 0.8);
25+
26+
uniform bool hdr = false;
27+
uniform float seed = 5.0;
28+
29+
// Random and noise functions from Book of Shader's chapter on Noise.
30+
float random(vec2 _uv) {
31+
return fract(sin(dot(_uv.xy,
32+
vec2(12.9898, 78.233))) *
33+
43758.5453123);
34+
}
35+
36+
float noise (in vec2 uv) {
37+
vec2 i = floor(uv);
38+
vec2 f = fract(uv);
39+
40+
// Four corners in 2D of a tile
41+
float a = random(i);
42+
float b = random(i + vec2(1.0, 0.0));
43+
float c = random(i + vec2(0.0, 1.0));
44+
float d = random(i + vec2(1.0, 1.0));
45+
46+
47+
// Smooth Interpolation
48+
49+
// Cubic Hermine Curve. Same as SmoothStep()
50+
vec2 u = f * f * (3.0-2.0 * f);
51+
52+
// Mix 4 coorners percentages
53+
return mix(a, b, u.x) +
54+
(c - a)* u.y * (1.0 - u.x) +
55+
(d - b) * u.x * u.y;
56+
}
57+
58+
mat2 rotate(float _angle){
59+
return mat2(vec2(cos(_angle), -sin(_angle)),
60+
vec2(sin(_angle), cos(_angle)));
61+
}
62+
63+
vec4 screen(vec4 base, vec4 blend){
64+
return 1.0 - (1.0 - base) * (1.0 - blend);
65+
}
66+
67+
void fragment()
68+
{
69+
70+
// Rotate, skew and move the UVs
71+
vec2 transformed_uv = ( rotate(angle) * (UV - position) ) / ( (UV.y + spread) - (UV.y * spread) );
72+
73+
// Animate the ray according the the new transformed UVs
74+
vec2 ray1 = vec2(transformed_uv.x * ray1_density + sin(TIME * 0.1 * speed) * (ray1_density * 0.2) + seed, 1.0);
75+
vec2 ray2 = vec2(transformed_uv.x * ray2_density + sin(TIME * 0.2 * speed) * (ray1_density * 0.2) + seed, 1.0);
76+
77+
// Cut off the ray's edges
78+
float cut = step(cutoff, transformed_uv.x) * step(cutoff, 1.0 - transformed_uv.x);
79+
ray1 *= cut;
80+
ray2 *= cut;
81+
82+
// Apply the noise pattern (i.e. create the rays)
83+
float rays;
84+
85+
if (hdr){
86+
// This is not really HDR, but check this to not clamp the two merged rays making
87+
// their values go over 1.0. Can make for some nice effect
88+
rays = noise(ray1) + (noise(ray2) * ray2_intensity);
89+
}
90+
else{
91+
rays = clamp(noise(ray1) + (noise(ray2) * ray2_intensity), 0., 1.);
92+
}
93+
94+
// Fade out edges
95+
rays *= smoothstep(0.0, falloff, (1.0 - UV.y)); // Bottom
96+
rays *= smoothstep(0.0 + cutoff, edge_fade + cutoff, transformed_uv.x); // Left
97+
rays *= smoothstep(0.0 + cutoff, edge_fade + cutoff, 1.0 - transformed_uv.x); // Right
98+
99+
// Color to the rays
100+
vec3 shine = vec3(rays) * color.rgb;
101+
102+
// Try different blending modes for a nicer effect. "Screen" is included in the code,
103+
// but take a look at https://godotshaders.com/snippet/blending-modes/ for more.
104+
// With "Screen" blend mode:
105+
shine = screen(texture(SCREEN_TEXTURE, SCREEN_UV), vec4(color)).rgb;
106+
107+
COLOR = vec4(shine, rays * color.a);
108+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
shader_type canvas_item;
2+
render_mode blend_premul_alpha;
3+
4+
uniform float Line_Smoothness : hint_range(0, 0.1) = 0.045;
5+
uniform float Line_Width : hint_range(0, 0.2) = 0.09;
6+
uniform float Brightness = 3.0;
7+
uniform float Rotation_deg : hint_range(-90, 90) = 30;
8+
uniform float Distortion : hint_range(1, 2) = 1.8;
9+
uniform float Speed = 0.7;
10+
uniform float Position : hint_range(0, 1) = 0;
11+
uniform float Position_Min = 0.25;
12+
uniform float Position_Max = 0.5;
13+
uniform float Alpha : hint_range(0, 1) = 1;
14+
15+
vec2 rotate_uv(vec2 uv, vec2 center, float rotation, bool use_degrees){
16+
float _angle = rotation;
17+
if(use_degrees){
18+
_angle = rotation * (3.1415926/180.0);
19+
}
20+
mat2 _rotation = mat2(
21+
vec2(cos(_angle), -sin(_angle)),
22+
vec2(sin(_angle), cos(_angle))
23+
);
24+
vec2 _delta = uv - center;
25+
_delta = _rotation * _delta;
26+
return _delta + center;
27+
}
28+
29+
void fragment() {
30+
31+
vec2 center_uv = UV - vec2(0.5, 0.5);
32+
float gradient_to_edge = max(abs(center_uv.x), abs(center_uv.y));
33+
gradient_to_edge = gradient_to_edge * Distortion;
34+
gradient_to_edge = 1.0 - gradient_to_edge;
35+
vec2 rotaded_uv = rotate_uv(UV, vec2(0.5, 0.5), Rotation_deg, true);
36+
37+
float remapped_position;
38+
{
39+
float output_range = Position_Max - Position_Min;
40+
remapped_position = Position_Min + output_range * Position;
41+
}
42+
43+
float remapped_time = TIME * Speed + remapped_position;
44+
remapped_time = fract(remapped_time);
45+
{
46+
float output_range = 2.0 - (-2.0);
47+
remapped_time = -2.0 + output_range * remapped_time;
48+
}
49+
50+
vec2 offset_uv = vec2(rotaded_uv.xy) + vec2(remapped_time, 0.0);
51+
float line = vec3(offset_uv, 0.0).x;
52+
line = abs(line);
53+
line = gradient_to_edge * line;
54+
line = sqrt(line);
55+
56+
float line_smoothness = clamp(Line_Smoothness, 0.001, 1.0);
57+
float offset_plus = Line_Width + line_smoothness;
58+
float offset_minus = Line_Width - line_smoothness;
59+
60+
float remapped_line;
61+
{
62+
float input_range = offset_minus - offset_plus;
63+
remapped_line = (line - offset_plus) / input_range;
64+
}
65+
remapped_line = remapped_line * Brightness;
66+
remapped_line = min(remapped_line, Alpha);
67+
COLOR.rgb = vec3(COLOR.xyz) * vec3(remapped_line);
68+
COLOR.a = remapped_line;
69+
}

core/ui/components/card.gd

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ var logger := Log.get_logger("GameCard")
4343
@onready var name_label := $%NameLabel
4444
@onready var progress := $%ProgressBar as ProgressBar
4545
@onready var tap_timer := $%TapTimer as Timer
46+
@onready var shine_rect := $%ShineShader as ColorRect
47+
@onready var god_rays_rect := $%GodRaysShader as ColorRect
4648

4749

4850
# Called when the node enters the scene tree for the first time.
@@ -98,10 +100,62 @@ func set_library_item(item: LibraryItem, free_on_remove: bool = true) -> void:
98100

99101
func _on_focus() -> void:
100102
highlighted.emit()
103+
_shader_godrays_fade_in()
104+
_shader_shine_fade_in()
105+
106+
107+
func _shader_godrays_fade_in() -> void:
108+
var tween := create_tween()
109+
var shader := god_rays_rect.material as ShaderMaterial
110+
var final_color := Color(0.961, 0.937, 1.0, 0.2)
111+
var start_color := Color(0.961, 0.937, 1.0, 0.0)
112+
shader.set_shader_parameter("color", start_color)
113+
god_rays_rect.visible = true
114+
var on_tween := func(value: Color):
115+
shader.set_shader_parameter("color", value)
116+
tween.tween_method(on_tween, start_color, final_color, 0.5)
117+
118+
119+
func _shader_shine_fade_in() -> void:
120+
var tween := create_tween()
121+
var shader := shine_rect.material as ShaderMaterial
122+
var final_alpha := 0.02
123+
var start_alpha := 0.0
124+
shader.set_shader_parameter("Alpha", start_alpha)
125+
shine_rect.visible = true
126+
var on_tween := func(value: float):
127+
shader.set_shader_parameter("Alpha", value)
128+
tween.tween_method(on_tween, start_alpha, final_alpha, 0.8)
101129

102130

103131
func _on_unfocus() -> void:
104132
unhighlighted.emit()
133+
_shader_godrays_fade_out()
134+
_shader_shine_fade_out()
135+
136+
137+
func _shader_godrays_fade_out() -> void:
138+
var tween := create_tween()
139+
var shader := god_rays_rect.material as ShaderMaterial
140+
var start_color := Color(0.961, 0.937, 1.0, 0.2)
141+
var final_color := Color(0.961, 0.937, 1.0, 0.0)
142+
shader.set_shader_parameter("color", start_color)
143+
var on_tween := func(value: Color):
144+
shader.set_shader_parameter("color", value)
145+
tween.tween_method(on_tween, start_color, final_color, 0.5)
146+
tween.tween_property(god_rays_rect, "visible", false, 0.0)
147+
148+
149+
func _shader_shine_fade_out() -> void:
150+
var tween := create_tween()
151+
var shader := shine_rect.material as ShaderMaterial
152+
var start_alpha := 0.02
153+
var final_alpha := 0.0
154+
shader.set_shader_parameter("Alpha", start_alpha)
155+
var on_tween := func(value: float):
156+
shader.set_shader_parameter("Alpha", value)
157+
tween.tween_method(on_tween, start_alpha, final_alpha, 0.1)
158+
tween.tween_property(shine_rect, "visible", false, 0.0)
105159

106160

107161
func _gui_input(event: InputEvent) -> void:

core/ui/components/card.tscn

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
[gd_scene load_steps=9 format=3 uid="uid://bkhrcemal7uxo"]
1+
[gd_scene load_steps=13 format=3 uid="uid://bkhrcemal7uxo"]
22

33
[ext_resource type="Script" path="res://core/ui/components/card.gd" id="1_aiin0"]
44
[ext_resource type="Texture2D" uid="uid://blc0qyvt1qhci" path="res://assets/images/placeholder-grid-portrait.png" id="2_2hlyj"]
55
[ext_resource type="PackedScene" uid="uid://c5sfkhrfbao71" path="res://core/systems/effects/play_audio_effect.tscn" id="2_701dj"]
66
[ext_resource type="PackedScene" uid="uid://bui0u88oe8jr" path="res://core/systems/effects/raise_effect.tscn" id="3_gyi80"]
7+
[ext_resource type="Shader" path="res://assets/shaders/highlight_shine.gdshader" id="5_0n631"]
8+
[ext_resource type="Shader" path="res://assets/shaders/god_rays.gdshader" id="7_8n7dp"]
79

810
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ygsnb"]
911
corner_radius_top_left = 26
@@ -21,6 +23,37 @@ corner_radius_top_right = 5
2123
corner_radius_bottom_right = 5
2224
corner_radius_bottom_left = 5
2325

26+
[sub_resource type="ShaderMaterial" id="ShaderMaterial_1bdvx"]
27+
resource_local_to_scene = true
28+
shader = ExtResource("5_0n631")
29+
shader_parameter/Line_Smoothness = 0.045
30+
shader_parameter/Line_Width = 0.075
31+
shader_parameter/Brightness = 0.81
32+
shader_parameter/Rotation_deg = 35.0
33+
shader_parameter/Distortion = 1.67
34+
shader_parameter/Speed = 0.31
35+
shader_parameter/Position = 0.0
36+
shader_parameter/Position_Min = 0.25
37+
shader_parameter/Position_Max = 0.5
38+
shader_parameter/Alpha = 0.02
39+
40+
[sub_resource type="ShaderMaterial" id="ShaderMaterial_1nde2"]
41+
resource_local_to_scene = true
42+
shader = ExtResource("7_8n7dp")
43+
shader_parameter/angle = 0.0
44+
shader_parameter/position = 0.0
45+
shader_parameter/spread = 1.0
46+
shader_parameter/cutoff = -1.0
47+
shader_parameter/falloff = 1.0
48+
shader_parameter/edge_fade = 0.904
49+
shader_parameter/speed = 20.0
50+
shader_parameter/ray1_density = 8.0
51+
shader_parameter/ray2_density = 30.0
52+
shader_parameter/ray2_intensity = 0.3
53+
shader_parameter/color = Color(0.960784, 0.937255, 1, 0.117647)
54+
shader_parameter/hdr = false
55+
shader_parameter/seed = 5.96
56+
2457
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_st1t5"]
2558
resource_local_to_scene = true
2659
bg_color = Color(0, 0, 0, 0)
@@ -63,8 +96,8 @@ on_signal = "highlighted"
6396
[node name="PanelContainer" type="PanelContainer" parent="."]
6497
clip_children = 1
6598
layout_mode = 0
66-
offset_right = 40.0
67-
offset_bottom = 40.0
99+
offset_right = 200.0
100+
offset_bottom = 300.0
68101
mouse_filter = 1
69102
theme_override_styles/panel = SubResource("StyleBoxFlat_ygsnb")
70103

@@ -94,6 +127,7 @@ layout_mode = 2
94127
theme_override_styles/panel = SubResource("StyleBoxFlat_gtppc")
95128

96129
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/TextureRect/NameMargin/NamePanel"]
130+
visible = false
97131
layout_mode = 2
98132
theme_override_constants/margin_left = 10
99133
theme_override_constants/margin_right = 10
@@ -120,6 +154,18 @@ theme_override_styles/fill = SubResource("StyleBoxFlat_up8ek")
120154
value = 50.0
121155
rounded = true
122156

157+
[node name="ShineShader" type="ColorRect" parent="PanelContainer"]
158+
unique_name_in_owner = true
159+
visible = false
160+
material = SubResource("ShaderMaterial_1bdvx")
161+
layout_mode = 2
162+
163+
[node name="GodRaysShader" type="ColorRect" parent="PanelContainer"]
164+
unique_name_in_owner = true
165+
visible = false
166+
material = SubResource("ShaderMaterial_1nde2")
167+
layout_mode = 2
168+
123169
[node name="MarginContainer" type="MarginContainer" parent="."]
124170
show_behind_parent = true
125171
custom_minimum_size = Vector2(200, 300)

0 commit comments

Comments
 (0)