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