[dali_2.3.19] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / graphics / shaders / page-turn-effect.vert
1 /*
2  * The common parameters for all the vertices, calculate in CPU then pass into the shader as uniforms
3  *
4  * first part of the page, (outside the the line passing through original center and vertical to curve direction)
5  * no Z change, only 2D rotation and translation
6  * ([0][0],[0][1],[1][0],[1][1]) mat2 rotateMatrix
7  * ([2][0],[2][1]) vec2 translationVector
8  *
9  * ([0][2],[0][3]) vec2 originalCenter: Typically the press down position of the Pan Gesture
10  * ([1][2],[1][3]) vec2 currentCenter: Typically the current position of the Pan Gesture
11  * ([3][0],[3][1]) vec2 curveDirection: The normalized vector pointing from original center to current center
12  * ([2][2]) float vanishingPointY: The Y coordinate of the intersection of the spine
13  *   and the line which goes through the original center and is vertical to the curveDirection
14  * ([2][3]) float curveEndY: The Y coordinate of intersection of the spine and the line through both original and current center
15  * ([3][2]) float curveHeight: The height of the interpolated hermite curve.
16  * ([3][3]) float currentLength: The length from the current center to the curveEnd.
17  */
18
19 precision mediump float;
20
21 attribute mediump vec2 aPosition;
22
23 uniform mediump mat4 uMvpMatrix;
24 uniform mediump mat3 uNormalMatrix;
25 uniform mediump mat4 uModelView;
26
27 uniform mat4 uCommonParameters;
28
29 uniform vec3 uSize;
30 uniform float uIsTurningBack;
31 uniform float uTextureWidth;
32 varying vec3 vNormal;
33 varying vec4 vPosition;
34 varying mediump vec2 vTexCoord;
35
36 void main()
37 {
38   vec4 position = vec4( aPosition*uSize.xy, 0.0, 1.0);
39   vec2 currentCenter = vec2( uCommonParameters[1][2], uCommonParameters[1][3]);
40   vec2 originalCenter = vec2( uCommonParameters[0][2], uCommonParameters[0][3]);
41   vec3 normal = vec3(0.0,0.0,1.0);
42
43   if(currentCenter.x < originalCenter.x)
44   {
45     // change the coordinate origin from the center of the page to its top-left
46     position.xy += uSize.xy * 0.5;
47     vec2 curveDirection = vec2( uCommonParameters[3]);
48     vec3 vanishingPoint = vec3(0.0, uCommonParameters[2][2], 0.0);
49     // first part of the page, (outside the the line passing through original center and vertical to curve direction)
50     //no Z change, only 2D rotation and translation
51     if( dot(curveDirection, position.xy - originalCenter) < 0.0 )
52     {
53       position.y -= vanishingPoint.y;
54       position.xy = mat2(uCommonParameters)*position.xy + vec2( uCommonParameters[2]);
55     }
56     // second part of the page, bent as a ruled surface
57     else
58     {
59       // calculate on the flat plane, between
60       // the first line passing through current vertex and vanishing point
61       // the second line passing through original center and current center
62       vec2 curveEnd = vec2( 0.0, uCommonParameters[2][3] );
63       vec2 curFlatDirection = vec2(0.0,1.0);
64       float lengthFromCurve = position.y - originalCenter.y;
65       float lengthOnCurve = position.x;
66       if(currentCenter.y != originalCenter.y)
67       {
68         curFlatDirection = normalize(position.xy - vanishingPoint.xy);
69         lengthFromCurve = (curveEnd.x*curveDirection.y-curveEnd.y*curveDirection.x-position.x*curveDirection.y+position.y*curveDirection.x)
70         / (curFlatDirection.x*curveDirection.y-curFlatDirection.y*curveDirection.x);
71         lengthOnCurve = length(position.xy+lengthFromCurve*curFlatDirection-curveEnd);
72       }
73
74       // define the control points of hermite curve, composed with two segments
75       // calculation is carried out on the 2D plane which is passing through both current and original center and vertical to the image plane
76       float currentLength = uCommonParameters[3][3];
77       float originalLength =  abs(originalCenter.x/curveDirection.x);
78       float height = uCommonParameters[3][2];
79       float percentage = currentLength/originalLength;
80       //vec2 SegmentOneControlPoint0 = vec2(0.0, 0.0);
81       vec2 SegmentOneControlPoint1 = vec2((0.65*percentage - 0.15)*originalLength, (0.8 + 0.2 * percentage)*height);
82       vec2 SegmentTwoControlPoint0 = SegmentOneControlPoint1;
83       vec2 SegmentTwoControlPoint1 = vec2(currentLength, 0.0);
84       vec2 SegmentOneTangentVector0 = SegmentOneControlPoint1;
85       vec2 SegmentOneTangentVector1 = vec2(0.5*originalLength,0.0);
86       vec2 SegmentTwoTangentVector0 = SegmentOneTangentVector1;
87       vec2 SegmentTwoTangentVector1 = SegmentOneTangentVector1;
88
89       // calculate the corresponding curve point position and its tangent vector
90       // it is a linear mapping onto nonlinear curves, might cause some unwanted deformation
91       // but as there are no analytical method to calculate the curve length on arbitrary segment
92       // no efficient way to solve this nonlinear mapping, Numerical approximation would cost too much computation in shader
93       vec2 curvePoint2D;
94       vec2 tangent;
95       float t0 = lengthOnCurve / originalLength;
96       if(t0<=0.5)
97       {
98         float t = 2.0*t0;
99         float t_2 = t*t;
100         float t_3 = t*t_2;
101         curvePoint2D = (-2.0*t_3+3.0*t_2)*SegmentOneControlPoint1
102         + (t_3-2.0*t_2+t)*SegmentOneTangentVector0 + (t_3-t_2)*SegmentOneTangentVector1;
103         tangent = (-6.0*t_2+6.0*t)*SegmentOneControlPoint1
104         + (3.0*t_2-4.0*t+1.0)*SegmentOneTangentVector0 + (3.0*t_2-2.0*t)*SegmentOneTangentVector1;
105       }
106       else
107       {
108         float t = 2.0*t0-1.0;
109         float t_2 = t*t;
110         float t_3 = t*t_2;
111         curvePoint2D = (2.0*t_3-3.0*t_2+1.0)*SegmentTwoControlPoint0 + (-2.0*t_3+3.0*t_2)*SegmentTwoControlPoint1
112         + (t_3-2.0*t_2+t)*SegmentTwoTangentVector0 + (t_3-t_2)*SegmentTwoTangentVector1;
113         tangent = (6.0*t_2-6.0*t)*SegmentTwoControlPoint0 + (-6.0*t_2+6.0*t)*SegmentTwoControlPoint1
114         + (3.0*t_2-4.0*t+1.0)*SegmentTwoTangentVector0 + (3.0*t_2-2.0*t)*SegmentTwoTangentVector1;
115         // a trick to eliminate some optical illusion caused by the gradient matter of normal in per-fragment shading
116         // which is caused by linear interpolation of normal vs. nonlinear lighting
117         // will notice some artifact in the areas with dramatically normal changes, so compress the normal differences here
118         tangent.y *=  min(1.0, length(position.xyz - vanishingPoint) / uSize.y );
119       }
120       vec3 curvePoint = vec3(curveEnd - curvePoint2D.x*curveDirection,max(0.0,curvePoint2D.y));
121       vec3 tangentVector = vec3(-tangent.x*curveDirection,tangent.y);
122
123       // locate the new vertex position on the line passing through both vanishing point and the calculated curve point position
124       vec3 curLiftDirection = vec3(0.0,-1.0,0.0);
125       if(currentCenter.y != originalCenter.y)
126       {
127         curLiftDirection = normalize(curvePoint - vanishingPoint);
128         tangentVector *= (curveDirection.y > 0.0) ? -1.0 : 1.0;
129         // an heuristic adjustment here, to compensate the linear parameter mapping onto the nonlinear curve
130         float Y0 = position.y - curveDirection.y * (position.x/curveDirection.x);
131         float proportion;
132         float refLength;
133         if(abs(Y0-vanishingPoint.y) > abs(curveEnd.y-vanishingPoint.y))
134         {
135           proportion = abs(curveEnd.y - Y0) / (abs(curveEnd.y-Y0)+abs(curveEnd.y - vanishingPoint.y));
136           refLength = proportion*length(originalCenter-vanishingPoint.xy) / (proportion-1.0);
137         }
138         else
139         {
140           proportion = abs(curveEnd.y - Y0) / abs(curveEnd.y - vanishingPoint.y);
141           refLength = proportion*length(originalCenter-vanishingPoint.xy);
142         }
143         float Y1 = currentCenter.y - (normalize(currentCenter-vanishingPoint.xy)).y * refLength;
144         position.y = mix(Y0, Y1, t0);
145       }
146       position.xz = curvePoint.xz - lengthFromCurve*curLiftDirection.xz;
147       // calculate the normal vector, will be used for lighting
148       normal = cross(curLiftDirection, normalize(tangentVector));
149       // the signature of Z is decided by the page turning direction:
150       // from left to right(negative); from right to left (positive)
151       position.z *= -uIsTurningBack;
152       normal.xy *= -uIsTurningBack;
153     }
154     // change the coordinate origin from the top-left of the page to its center
155     position.xy -= uSize.xy * 0.5;
156   }
157   vNormal =  uNormalMatrix * normal;
158   gl_Position = uMvpMatrix * position;
159   // varying parameters for fragment shader
160   vTexCoord = aPosition + vec2(0.5);
161   vTexCoord.x /= uTextureWidth;
162   vPosition = uModelView * position;
163 }