shader_type canvas_item; uniform sampler2D front_texture : source_color, filter_linear_mipmap; uniform sampler2D back_texture : source_color, filter_linear_mipmap; uniform sampler2D spine_shadow_gradient : source_color, filter_linear, repeat_disable; uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.0; uniform float max_shadow_spread : hint_range(0.0, 1.0) = 0.35; uniform bool debug_mode = false; uniform bool is_backward = false; void fragment() { vec2 uv_dx = dFdx(UV); vec2 uv_dy = dFdy(UV); float face_dir = uv_dx.x * uv_dy.y - uv_dx.y * uv_dy.x; bool is_front = face_dir > 0.0; vec4 base_color; if (is_front) { if (is_backward) { // Let's try flipping Y just in case they meant upside down! // And keep X normal, since UV goes 0 to 1. base_color = texture(front_texture, UV); } else { base_color = texture(front_texture, UV); } } else { if (is_backward) { base_color = texture(back_texture, vec2(1.0 - UV.x, UV.y)); } else { base_color = texture(back_texture, vec2(1.0 - UV.x, UV.y)); } } float current_spread = max_shadow_spread * (shadow_intensity + 0.001); float sample_x = UV.x / current_spread; float shadow_alpha = texture(spine_shadow_gradient, vec2(sample_x, 0.0)).a; if (sample_x > 1.0) { shadow_alpha = 0.0; } shadow_alpha *= shadow_intensity; vec3 final_rgb = mix(base_color.rgb, vec3(0.0, 0.0, 0.0), shadow_alpha); COLOR = vec4(final_rgb, base_color.a); }