shader_type canvas_item; uniform float flip_param : hint_range(0.0, 1.0); // Parameter to control the flipping effect uniform float dim_color_scale : hint_range(0.0, 1.0) = 0.4; // Control the dim of the back of the flipped texture uniform float x_buffer = 2.0;//Increase these if you need your flip to stretch further uniform float y_buffer = 2.0; const vec2 scale = vec2(1, 1); // Scale of the texture const vec2 start_flip_pos = vec2(1.0, 0.0); // Starting position of the flip const vec2 end_flip_pos = vec2(0, 1); // Ending position of the flip uniform vec2 atlas_offset = vec2(0.0); // Offset dans l'atlas uniform vec2 atlas_size = vec2(1.0); // Taille de la région dans l'atlas // Function to calculate the vector from a line to a point vec2 Line2point(vec2 linePoint, vec2 lineDire, vec2 point) { lineDire = normalize(lineDire); // Normalize the direction of the line return -linePoint - dot(-linePoint, lineDire) * lineDire - (-point - dot(-point, lineDire) * lineDire); } void vertex() { //This increases the size of the uv so the sprite can be drawn 'out of bounds' VERTEX.x *= x_buffer; VERTEX.y *= y_buffer; } // Main fragment shader function void fragment() { // Resize the texture coordinates before the buffer vec2 uv = vec2((UV.x - 0.5) * x_buffer + 0.5, (UV.y - 0.5) * y_buffer + 0.5); uv = UV * atlas_size + atlas_offset; // Interpolate flip position based on flip_param vec2 flip_pos = mix(start_flip_pos, end_flip_pos, flip_param); // Get the UV coordinates of the fragment vec4 finalColor = vec4(0.0); // Initialize final color with transparent float scale_min = scale.x / scale.y; vec2 uv_max = vec2(scale_min, 1.0); float trueScale; // Adjust UV coordinates based on the scale if (scale.y < scale.x) { scale_min = scale.y / scale.x; uv.y *= scale_min; uv_max = vec2(1.0, scale_min); trueScale = scale.x; } else { uv.x *= scale_min; trueScale = scale.y; } // Sample the color from the texture at the given UV coordinates COLOR = texture(TEXTURE, uv); // Calculate the position in texture space vec2 pPos = uv / trueScale; // If the flip position is valid, can't be 0 if (flip_pos.x > -0.00001) { vec2 left_bottom = vec2(0.0, uv_max.y / trueScale); vec2 midpoint = (flip_pos - left_bottom) / 2.5 + left_bottom; vec2 midDirect = normalize(vec2(-(flip_pos - left_bottom).y, (flip_pos - left_bottom).x)); // Calculate sharp point and direction vectors vec2 sharpPoint = vec2(0.0, midpoint.y - midDirect.y / midDirect.x * midpoint.x); vec2 flipEdgeDire = normalize(sharpPoint - flip_pos); vec2 sharpPointB = vec2(midpoint.x - midDirect.x / midDirect.y * (midpoint - left_bottom).y, left_bottom.y); vec2 flipEdgeDireB = normalize(sharpPointB - flip_pos); float cyOriOff = min(length(flip_pos - left_bottom), 100.0); float cyR = cyOriOff * 2.05 / PI; vec2 midlineToP = Line2point(midpoint, midDirect, pPos); vec2 cyOriToP = midlineToP - normalize(flip_pos - left_bottom) * cyOriOff; vec2 cyEdgeToP = midlineToP - normalize(flip_pos - left_bottom) * (cyOriOff - cyR); // Determine the location of the fragment relative to the flip bool atBG = (cyOriToP.x <= -0.001); bool atCy = (cyEdgeToP.x >= 0.0) && (cyOriToP.x <= 0.0); bool atCyPage = false; vec2 uvCy; vec2 uvCyB; // If the fragment is within the curvature area if (atCy) { vec2 cyOri = pPos - cyOriToP; vec2 trueDis = cyR * asin(length(cyOriToP) / cyR) * normalize(cyOriToP); vec2 truePos = cyOri + trueDis; vec2 sideEdgeToTP = Line2point(flip_pos, flipEdgeDire, truePos); vec2 BottomEdgeToTP = Line2point(flip_pos, flipEdgeDireB, truePos); uvCyB = truePos * trueScale; if ((BottomEdgeToTP.x < 0.0) && (sideEdgeToTP.y > 0.0)) { atCyPage = true; uvCy = vec2(length(sideEdgeToTP), left_bottom.y - length(BottomEdgeToTP)) * trueScale; } if ((uvCyB.x > uv_max.x) || (uvCyB.y > uv_max.y) || (uvCyB.x <= 0.0) || (uvCyB.y <= 0.0)) { atCy = false; } } // If the fragment is not within the background or curvature area, sample the color from the texture if (!atBG && !atCy) { finalColor = texture(TEXTURE, uv); } // If the fragment is within the curvature area, sample the color with curvature effect if (atCy) { finalColor = texture(TEXTURE, uvCyB); } // If the fragment is on the flipped page, adjust the color for the back of the page if (atCyPage) { vec4 cyPageColor = texture(TEXTURE, uvCy); cyPageColor.rgb *= dim_color_scale; // Dim the color slightly finalColor = mix(finalColor, cyPageColor, cyPageColor.a); } // Set the final color COLOR = finalColor; } }