shader_type canvas_item; uniform vec2 scale = vec2(1,1); uniform float flip_param = 0.0; vec2 Line2point(vec2 linePoint,vec2 lineDire,vec2 point) { lineDire = normalize(lineDire); vec2 line2Ori = - linePoint - dot(-linePoint,lineDire)*lineDire; vec2 p2Ori = - point - dot(-point,lineDire)*lineDire; return line2Ori-p2Ori; } vec4 ColorWithA(vec4 oldCol,vec4 newCol){ vec4 finalCol; if((newCol.a + oldCol.a)>=1.) { finalCol.rgb = newCol.rgb; finalCol.a = 1.0; } else { finalCol.rgb = newCol.a/(newCol.a + oldCol.a)*newCol.rgb + oldCol.a/(newCol.a + oldCol.a)*oldCol.rgb; finalCol.a = oldCol.a + newCol.a; } return finalCol; } void fragment() { vec2 start_flip_pos = vec2(0.8, -0.2); vec2 end_flip_pos = vec2(0, 1); // Interpolate flip_pos based on flip_param vec2 flip_pos = mix(start_flip_pos, end_flip_pos, flip_param); vec2 uv = UV; vec4 finalColor = vec4(0.0); // Initialize with transparent color float scale_min = scale.x/scale.y; vec2 uv_max = vec2(scale_min,1.); float trueScale; if(scale.y < scale.x) { scale_min = scale.y/scale.x; uv.y = uv.y * scale_min; uv_max = vec2(1.,scale_min); trueScale = scale.x; } else { uv.x = uv.x * scale_min; trueScale = scale.y; } COLOR = texture(TEXTURE, uv); vec2 pPos = uv / TEXTURE_PIXEL_SIZE * trueScale; if (flip_pos.x > -0.0001) { vec2 left_bottom = vec2(0., uv_max.y / TEXTURE_PIXEL_SIZE.y * trueScale); vec2 midpoint = (flip_pos - left_bottom) / 2. + left_bottom; vec2 midDirect = normalize(vec2(-(flip_pos - left_bottom).y, (flip_pos - left_bottom).x)); vec2 sharpPoint = vec2(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 = length(flip_pos - left_bottom); if (cyOriOff > 100.) cyOriOff = 100.; float cyR = cyOriOff * 2. / PI; float pageHDire = PI / 6.; vec2 midlineToP = Line2point(midpoint, midDirect, pPos); vec2 sideEdgeToP = Line2point(flip_pos, flipEdgeDire, pPos); vec2 BottomEdgeToP = Line2point(flip_pos, flipEdgeDireB, pPos); vec2 cyOriToP = midlineToP - normalize(flip_pos - left_bottom) * cyOriOff; vec2 cyEdgeToP = midlineToP - normalize(flip_pos - left_bottom) * (cyOriOff - cyR); bool atBG = (cyOriToP).x <= -0.01; bool atPageBack = !atBG && (sideEdgeToP.y > 0.) && (BottomEdgeToP.x <= 0.); bool atCy = cyEdgeToP.x >= 0. && (cyOriToP).x <= 0.; bool atCyPage = false; vec2 uvCy; vec2 uvCyB; float shadow = 1.; 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 * TEXTURE_PIXEL_SIZE / trueScale; shadow *= 1. - pow(length(trueDis) / (cyR * PI / 2.), 3.); if ((BottomEdgeToTP.x < 0.) && (sideEdgeToTP.y > 0.)) { atCyPage = true; uvCy = vec2(length(sideEdgeToTP), left_bottom.y - length(BottomEdgeToTP)) * TEXTURE_PIXEL_SIZE / trueScale; } if ((uvCyB.x > uv_max.x) || (uvCyB.y > uv_max.y) || (uvCyB.x <= 0.) || (uvCyB.y <= 0.)) atCy = false; } COLOR = vec4(0.); if (!atBG && !atCy) { vec4 color = texture(TEXTURE, uv); finalColor = color; } if (atCy) { vec4 cyColor = texture(TEXTURE, uvCyB); finalColor = cyColor; } if (atCyPage) { vec4 cyPageColor = texture(TEXTURE, uvCy); cyPageColor.xyz *= 0.8; finalColor = mix(finalColor, cyPageColor, cyPageColor.a); } else if (atPageBack) { uv = vec2(length(sideEdgeToP), left_bottom.y - length(BottomEdgeToP)) * TEXTURE_PIXEL_SIZE / trueScale; vec4 pageBackColor = texture(TEXTURE, uv); pageBackColor.xyz *= 0.8; finalColor = mix(finalColor, pageBackColor, pageBackColor.a); } COLOR = finalColor; } }