Balatro card tilt
I did not make the tilt, simply the main script.
the original creator here: https://godotshaders.com/shader/2d-perspective/
!THIS WAS MADE ON THE WEB VERSION!
this may have bugs, but they will be minor.
!THIS WAS MADE ON THE WEB VERSION!
put this as a TextureRect, nothing else neededed
Script:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extends TextureRect
var ROTACTIVE = false
var YROT = 0.0
var XROT = 0.0
# Called when the node enters the scene tree for the first time.
func _ready():
pass
func _Update_X(value: float):
# This function will be called repeatedly during the tween with the interpolated ‘value’
set_instance_shader_parameter(“x_rot”, value)
func _Update_Y(value: float):
# This function will be called repeatedly during the tween with the interpolated ‘value’
set_instance_shader_parameter(“y_rot”, value)
func _process(delta: float) -> void:
XROT = (((global_position.x + size.x/2) – get_viewport().get_mouse_position().x)/(size.x/50))
YROT = -(((global_position.y + size.y/2) – get_viewport().get_mouse_position().y) / (size.y/50))
if ROTACTIVE:
set_instance_shader_parameter(“x_rot”, YROT)
set_instance_shader_parameter(“y_rot”, XROT)
else:
pass
func _on_mouse_entered() -> void:
ROTACTIVE = true
func _on_mouse_exited() -> void:
ROTACTIVE = false
_Tween_X_To_Base()
_Tween_Y_To_Base()
func _Tween_X_To_Base():
var tween = create_tween()
tween.tween_method(Callable(self, “_Update_X”), get_instance_shader_parameter(“x_rot”), 0.0, 0.1) \
.set_trans(Tween.TRANS_QUAD) \
.set_ease(Tween.EASE_OUT)
func _Tween_Y_To_Base():
var tween = create_tween()
tween.tween_method(Callable(self, “_Update_Y”), get_instance_shader_parameter(“y_rot”), 0.0, 0.1) \
.set_trans(Tween.TRANS_QUAD) \
.set_ease(Tween.EASE_OUT)
Shader code
// Hey this is Hei! This shader "fakes" a 3D-camera perspective on CanvasItems.
// License: MIT
shader_type canvas_item;
// Camera FOV
uniform float fov : hint_range(1, 179) = 90;
uniform bool cull_back = true;
instance uniform float y_rot : hint_range(-180, 180) = 0.0;
instance uniform float x_rot : hint_range(-180, 180) = 0.0;
// At 0, the image retains its size when unrotated.
// At 1, the image is resized so that it can do a full
// rotation without clipping inside its rect.
uniform float inset : hint_range(0, 1) = 0.0;
// Consider changing this to a uniform and changing it from code
varying flat vec2 o;
varying vec3 p;
// Creates rotation matrix
void vertex(){
float sin_b = sin(y_rot / 180.0 * PI);
float cos_b = cos(y_rot / 180.0 * PI);
float sin_c = sin(x_rot / 180.0 * PI);
float cos_c = cos(x_rot / 180.0 * PI);
mat3 inv_rot_mat;
inv_rot_mat[0][0] = cos_b;
inv_rot_mat[0][1] = 0.0;
inv_rot_mat[0][2] = -sin_b;
inv_rot_mat[1][0] = sin_b * sin_c;
inv_rot_mat[1][1] = cos_c;
inv_rot_mat[1][2] = cos_b * sin_c;
inv_rot_mat[2][0] = sin_b * cos_c;
inv_rot_mat[2][1] = -sin_c;
inv_rot_mat[2][2] = cos_b * cos_c;
float t = tan(fov / 360.0 * PI);
p = inv_rot_mat * vec3((UV - 0.5), 0.5 / t);
float v = (0.5 / t) + 0.5;
p.xy *= v * inv_rot_mat[2].z;
o = v * inv_rot_mat[2].xy;
VERTEX += (UV - 0.5) / TEXTURE_PIXEL_SIZE * t * (1.0 - inset);
}
void fragment(){
if (cull_back && p.z <= 0.0) discard;
vec2 uv = (p.xy / p.z).xy - o;
COLOR = texture(TEXTURE, uv + 0.5);
COLOR.a *= step(max(abs(uv.x), abs(uv.y)), 0.5);
}

