Merge "Added PathConstraint support to Javascript API" into tizen
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / docs / content / shader-effect.js
1 /**
2  *
3
4 ## Shader Effects API
5
6 Shader effects provide a visual effect for actors.
7
8 You can create a type-registered shader effect by its type name.
9 ```
10 // create a new shader effect
11 var shader = new dali.ShaderEffect("BlindEffect");
12 ```
13
14 Alternatively you can create a Custom shader by providing the vertex and fragment shader code as strings.
15 Each shader is provided with default uniforms and attributes.
16 For a vertex shader this part contains the following code:
17 ```
18 precision highp float;
19 attribute vec3  aPosition;
20 attribute vec2  aTexCoord;
21 uniform   mat4  uMvpMatrix;
22 uniform   mat4  uModelMatrix;
23 uniform   mat4  uViewMatrix;
24 uniform   mat4  uModelView;
25 uniform   mat3  uNormalMatrix;
26 uniform   mat4  uProjection;
27 uniform   vec4  uColor;
28 varying   vec2  vTexCoord;
29 ```
30 The custom shader part is expected to output the vertex position and texture coordinate.
31 A basic custom vertex shader would contain the following code:
32 ```
33 void main()
34 {
35     gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
36     vTexCoord = aTexCoord;
37 }
38 ```
39 For an Image fragment shader the default attributes and uniforms are:
40 ```
41 precision mediump float;
42 uniform   sampler2D sTexture;
43 uniform   sampler2D sEffect;
44 uniform   vec4      uColor;
45 varying   vec2      vTexCoord;
46 ```
47 The custom shader is expected to output the fragment color.
48 The basic fragment shader for images would contain:
49 ```
50 void main()
51 {
52   gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;
53 }
54 ```
55 The API supports functionality such as:
56
57 + new dali.{{#crossLink "ShaderEffect/ShaderEffect:method"}}{{/crossLink}}
58 + {{#crossLink "ShaderEffect/setUniform:method"}}{{/crossLink}}
59
60 ### Example of using a custom uniform to brighten an Image (Fragment Shader)
61
62 <img src="../assets/img/fragment-shader-color.png">
63 ```
64 createColorEffect = function()
65 {
66   
67   // add uColorShift to the pixel color
68   
69   var fragShader =
70     "uniform lowp vec4 uColorShift; \
71     \
72     void main()             \
73     {                  \
74       gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor + uColorShift; \
75     }"
76   
77     var shaderOptions = {
78         geometryType: "image",
79         fragmentShader: fragShader
80     };
81   
82   // create a new shader effect
83     var shader = new dali.ShaderEffect(shaderOptions);
84   
85   // add the color shift uniform so we can modify and animate it
86     shader.setUniform("uColorShift", [0.0, 0.0, 0.0, 0]);
87     return shader;
88 }
89 // create an image actor and add an image to it
90 var image = new dali.ResourceImage( { url: getImageDirectory() +"gallery-medium-50.jpg"});
91 var imageActor = new dali.ImageActor( image );
92 imageActor.parentOrigin = dali.CENTER;
93 dali.stage.add( imageActor );
94   
95 var colorShift = createColorEffect();
96   
97 colorShift.setUniform( "uColorShift", [0.5,0.5,0.5,0.0] );  // increase RGB by 50%
98   
99 imageActor.setShaderEffect( colorShift );
100 ```
101
102 For an example of animating we can just do:
103 ```
104 var shaderAnim = new dali.Animation(10);
105   
106 var animOptions = {
107     alpha: "doubleEaseInOutSine60",
108 };
109   
110 // animate the color uniform to full white
111 shaderAnim.animateTo( colorShift, "uColorShift", dali.COLOR_WHITE, animOptions);
112   
113 shaderAnim.play();
114 ```
115 Like all animatable properties we can also use keyframes to animate the value.
116 * * *
117
118 ### Example of animating a custom uniform to perform a mask operation (Fragment Shader)
119
120 In this example we are using the OpenGL discard function to draw an image with a circular mask.
121
122 <img src="../assets/img/fragment-shader-reveal.png">
123 ```
124 createRevealEffect = function()
125 {
126 // texture co-ordinate is from 0..1
127 // we shift the texture co-ordinate to -0.5 to 0.5 to center it
128 // then work out the radius from the centre, using ( a^2 + b^2) = c^2
129 // we use the dot product to perform the a^2 + b^2
130 // then just perform uRadius * uRadius to workout c^2
131   
132     var fragShader =
133       " uniform lowp float uRadius; \
134       \
135        void main()             \
136        {                  \
137          lowp vec2 pos= vec2(vTexCoord.x-0.5,vTexCoord.y-0.5);    \
138          lowp float radius = dot(pos, pos ) ; \
139          if( radius > (uRadius*uRadius) )\
140            discard; \
141          gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor ; \
142        }"
143
144       var shaderOptions = {
145           geometryType: "image",
146           fragmentShader: fragShader
147       };
148   
149     // create a new shader effect
150       var shader = new dali.ShaderEffect(shaderOptions);
151   
152       // set the uniform
153       shader.setUniform("uRadius",0.0);
154       return shader;
155 }
156 // create an image actor and add an image to it
157 var filename = getImageDirectory() +"gallery-medium-50.jpg;
158 var image = new dali.ResourceImage( {url: filename });
159 var imageActor = new dali.ImageActor( image );
160 imageActor.parentOrigin = dali.CENTER;
161 dali.stage.add( imageActor );
162   
163 var revealEffect = createRevealEffect();
164   
165 imageActor.setShaderEffect( revealEffect );
166   
167 var shaderAnim = new dali.Animation(5);
168   
169 var animOptions = {
170           alpha: "easeInOutSine",
171       };
172   
173 // animate up to radius = 0.5 ( a full circle )
174 // if we go to 1.0 then it will go to a full box
175 shaderAnim.animateTo( revealEffect, "uRadius", 0.5,animOptions);
176 shaderAnim.play();
177 ```
178 * * *
179 ### Example of paper twisting in the wind with color (Vertex + Fragment Shader)
180
181 <img src="../assets/img/vertex-shader.png"><br>
182
183 The example does the following:
184
185 + Creates a varying variable called vColor in the vertex shader.
186  + The vColor is set to the position of the vertex, so the color changes depending on its position
187 + Create a uniform called uOffset which modifies the xPosition of each vertex, creating a twist effect
188
189 An ImageActor normally only has 4 vertices ( quad ). To allow the image to twist and bend we need it to have more
190 vertices. To do this we can break the image into a grid using the gridX and gridY geometry hints.
191
192 <img src="../assets/img/shader-grid-hint.png">
193
194 ```
195 createTwistEffect = function()
196 {
197
198     // do some maths on the x-position to move it based on y,z pos + uOffset
199     var vertexShader =
200     " \
201       varying lowp vec4  vColor; \
202       uniform lowp float uOffset; \
203       \
204       void main() \
205       {   \
206         vec4 pos = uProjection * uModelView * vec4(aPosition, 1.0); \
207         pos.x= 3*pos.z*(sin(1.57+uOffset+pos.y/1000.0)); \
208         gl_Position =pos; \
209           vColor = pos/500.0;\
210           vTexCoord = aTexCoord; \
211     }"
212   
213     // add the vColor to the pixel color to tint it
214     var fragShader =
215       " \
216        varying lowp vec4 vColor; \
217        void main()               \
218        {                         \
219          gl_FragColor = texture2D( sTexture, vTexCoord ) *uColor + vColor*0.2;  \
220        }"
221   
222     var shaderOptions = {
223           geometryType: "image",
224           vertexShader: vertexShader,
225           fragmentShader: fragShader,
226           geometryHints: ["grid"]
227     };
228   
229     // create a new shader effect
230     var shader = new dali.ShaderEffect(shaderOptions);
231   
232     // set the uniform
233     shader.setUniform("uOffset",0.0);
234     return shader;
235 }
236   
237
238 dali.stage.setBackgroundColor( dali.COLOR_WHITE);
239
240 var image = new dali.ResourceImage( { url:getImageDirectory() +"gallery-medium-50.jpg"});
241 var imageActor = new dali.ImageActor( image );
242 imageActor.parentOrigin = dali.CENTER;
243 imageActor.setCullFace( dali.CULL_FACE_DISABLE ); // disable face culling so we can see both sides
244 dali.stage.add( imageActor );
245   
246 // start it of tilted around the y-axis
247 imageActor.orientation=new dali.Rotation(90, 0, 1, 0);
248   
249 var twistEffect = createTwistEffect();
250 imageActor.setShaderEffect( twistEffect );
251   
252 var shaderAnim = new dali.Animation(1);
253 var animOptions = {
254           alpha: "bounce",
255           duration:20
256       };
257 shaderAnim.animateTo( twistEffect, "uOffset",20,animOptions);
258   
259 shaderAnim.play();
260 ```
261 Note: In order for fade and color animations to work, the fragment shader needs to multiply the fragment color
262 with the uniform color "uColor" of the node
263
264 @class ShaderEffect
265 */