Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / shader-effects / shader-effect-api.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18
19 // CLASS HEADER
20 #include "shader-effect-api.h"
21
22 // INTERNAL INCLUDES
23 #include <v8-utils.h>
24 #include <shader-effects/shader-effect-wrapper.h>
25
26 namespace Dali
27 {
28
29 namespace V8Plugin
30 {
31
32 namespace // un named namespace
33 {
34
35 typedef  std::vector< std::string > HintsArray;
36
37
38 struct GeometryTypePair
39 {
40   const char* name;
41   GeometryType type;
42 };
43
44 const GeometryTypePair GeometryTypeTable[]=
45 {
46     {"image",         GEOMETRY_TYPE_IMAGE },
47     {"mesh",          GEOMETRY_TYPE_UNTEXTURED_MESH  },
48     {"textured-mesh", GEOMETRY_TYPE_TEXTURED_MESH },
49 };
50
51 const unsigned int GeometryTypeTableCount = sizeof(GeometryTypeTable)/sizeof(GeometryTypeTable[0]);
52
53 struct GeometryHintPair
54 {
55   const char* name;
56   ShaderEffect::GeometryHints hint;
57 };
58
59 const GeometryHintPair GeometryHintTable[]=
60 {
61     {"gridX",        ShaderEffect::HINT_GRID_X },
62     {"gridY",        ShaderEffect::HINT_GRID_Y },
63     {"grid",         ShaderEffect::HINT_GRID   },
64     {"depthBuffer",  ShaderEffect::HINT_DEPTH_BUFFER },
65     {"blending",     ShaderEffect::HINT_BLENDING },
66     {"doesntModifyGeometry", ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY }
67 };
68
69 const unsigned int GeometryHintTableCount = sizeof(GeometryHintTable)/sizeof(GeometryHintTable[0]);
70
71
72
73
74 struct ShaderParameters
75 {
76   ShaderParameters()
77       : mType( GEOMETRY_TYPE_IMAGE),
78         mHints( ShaderEffect::HINT_NONE )
79   {
80   }
81
82   void SetGeometryType( v8::Isolate* isolate, const std::string& typeName )
83   {
84      for( unsigned int i = 0; i < GeometryTypeTableCount; ++i )
85      {
86        if( typeName == GeometryTypeTable[i].name )
87        {
88          mType = GeometryTypeTable[i].type;
89          return;
90        }
91      }
92      DALI_SCRIPT_EXCEPTION( isolate, "Geometry type not found\n");
93   }
94
95   ShaderEffect::GeometryHints GetGeometryHint( const std::string& hint )
96   {
97     for( unsigned int i = 0 ; i < GeometryHintTableCount; ++i )
98     {
99       if( hint == GeometryHintTable[i].name )
100       {
101         return GeometryHintTable[i].hint;
102       }
103     }
104     return ShaderEffect::HINT_NONE;
105   }
106
107   void ProcessHintsArray( const HintsArray& hintsArray )
108   {
109     for( HintsArray::const_iterator iter  = hintsArray.begin(); iter != hintsArray.end() ; ++iter )
110     {
111       mHints= static_cast<ShaderEffect::GeometryHints>( mHints | GetGeometryHint( *iter ) );
112     }
113   }
114
115
116
117   ShaderEffect NewShader()
118   {
119     return ShaderEffect::NewWithPrefix( mVertexPrefix ,
120                               mVertex,
121                               mFragmentPrefix,
122                               mFragment,
123                               mType,
124                               mHints);
125   }
126   std::string mVertexPrefix;
127   std::string mVertex;
128   std::string mFragmentPrefix;
129   std::string mFragment;
130   GeometryType mType;
131   ShaderEffect::GeometryHints mHints;
132 };
133
134 ShaderEffect GetShaderEffect( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
135 {
136   v8::HandleScope handleScope( isolate );
137
138   v8::Local<v8::Object> object = args.This();
139   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
140   void* ptr = field->Value();
141
142   ShaderEffectWrapper* wrapper = static_cast< ShaderEffectWrapper *>(ptr);
143   return wrapper->GetShaderEffect();
144 }
145
146 } // unnamed space
147
148 /**
149  * Create a new ShaderEffect
150  * @constructor
151  * @for ShaderEffect
152  * @method ShaderEffect
153  * @param {Object} shaderOptions
154  * @param {String} [shaderOptions.geometryType] Type of geometry to be rendered with the effect. "image", "text", "mesh", "textured-mesh", default is image.
155  * @param {String} [shaderOptions.vertexShaderPrefix] This string will be inserted before the default uniforms for the vertex shader(ideal for #defines)
156  * @param {String} [shaderOptions.vertexShader] VertexShader code for the effect. If not defined, the default version will be used
157  * @param {String} [shaderOptions.fragmentShaderPrefix] This string will be inserted before the default uniforms for the fragment shader(ideal for #defines)
158  * @param {String} [shaderOptions.fragmentShader] FragmentShader code for the effect. If not defined, the default version will be used
159  * @param {Array}  [shaderOptions.geometryHints] Hints for rendering the geometry, e.g.  [ "gridX", "gridY", "grid","depthBuffer","blending","doesntModifyGeometry" ]
160  * @return {Object} ShaderEffect
161  * @example
162
163       // this will match the default shaders for image
164       var vertexShader = " void main() \
165       { \
166         gl_Position = uProjection * uModelView * vec4(aPosition, 1.0); \
167         vTexCoord = aTexCoord; \
168       }; "
169      var fragShader = " void main() \
170       { \
171        gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\
172       }; "
173       var shaderOptions = {
174             geometryType: "image",
175             vertexShader: vertexShader,
176             fragmentShader: fragShader
177       };
178
179       var shader = new dali.ShaderEffect(shaderOptions);
180
181       imageActor.setShaderEffect( shader );
182
183  *
184  *
185  *
186  */
187 ShaderEffect ShaderEffectApi::New(  v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
188 {
189
190
191   v8::HandleScope handleScope( isolate );
192
193   ShaderParameters shaderParams;
194
195   if( args[0]->IsObject() )
196   {
197     v8::Local<v8::Object > obj = args[0]->ToObject();
198
199     v8::Local<v8::Value> geometryTypeValue = obj->Get(v8::String::NewFromUtf8( isolate, "geometryType"));
200     if( geometryTypeValue->IsString() )
201     {
202       std::string geometryTypeName = V8Utils::v8StringToStdString( geometryTypeValue );
203      // printf(" geometry type found %s \n", geometryTypeName.c_str() );
204       shaderParams.SetGeometryType( isolate, geometryTypeName );
205     }
206
207     v8::Local<v8::Value> vertexPrefixValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShaderPrefix"));
208     if( vertexPrefixValue->IsString() )
209     {
210       shaderParams.mVertexPrefix = V8Utils::v8StringToStdString( vertexPrefixValue );
211     }
212
213     v8::Local<v8::Value> fragmentPrefixValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShaderPrefix"));
214     if( fragmentPrefixValue->IsString() )
215     {
216       shaderParams.mFragmentPrefix = V8Utils::v8StringToStdString( fragmentPrefixValue );
217     }
218
219     v8::Local<v8::Value> vertexValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShader"));
220     if( vertexValue->IsString() )
221     {
222       shaderParams.mVertex = V8Utils::v8StringToStdString( vertexValue );
223     }
224
225     v8::Local<v8::Value> fragmentValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShader"));
226     if( fragmentValue->IsString() )
227     {
228       shaderParams.mFragment = V8Utils::v8StringToStdString( fragmentValue );
229     }
230     // Get any hints
231     v8::Local<v8::Value> hints = obj->Get(v8::String::NewFromUtf8( isolate, "geometryHints"));
232     if( hints->IsArray() )
233     {
234       HintsArray hintsArray;
235       v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( hints );
236       for( uint32_t i=0; i <  array->Length(); ++i)
237       {
238         v8::Handle<v8::Value> entry = array->Get(  v8::Integer::New( isolate, i) );
239         if( entry->IsString() )
240         {
241           std::string entryString = V8Utils::v8StringToStdString( entry );
242           hintsArray.push_back( entryString );
243         }
244       }
245       shaderParams.ProcessHintsArray( hintsArray );
246     }
247   }
248   return shaderParams.NewShader();
249
250 }
251
252 ShaderEffect ShaderEffectApi::GetShaderEffectFromParams( int paramIndex,
253                           bool& found,
254                           v8::Isolate* isolate,
255                           const v8::FunctionCallbackInfo< v8::Value >& args )
256 {
257   found = false;
258
259   v8::HandleScope handleScope( isolate );
260   BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::SHADER_EFFECT, isolate, args );
261   if( wrappedObject )
262   {
263     found = true;
264     ShaderEffectWrapper* wrapper = static_cast< ShaderEffectWrapper *>(wrappedObject);
265     return wrapper->GetShaderEffect();
266   }
267   else
268   {
269     return ShaderEffect();
270   }
271 }
272
273 /**
274  * Set a shader effect image.
275  * This image texture will be bound to the "sEffect" sampler
276  * so it can be used in fragment shader for effects
277  * @method setEffectImage
278  * @for ShaderEffect
279  * @param {Object} image
280  * @example
281  *
282  *      shader.setEffectImage( image );
283  *
284  *      // example of a fragment shader than can use the effect image (sEffect and main texture sTexture)
285  *
286  *      "void main() \
287  *       { \
288  *        vec4 v4Color  = (texture2D(sTexture, vTexCoord) * uColor); \
289  *        v4Color = v4Color*  texture2D(sEffect, vTexCoord);\
290  *        gl_FragColor = v4Color; \"
291  *      }";
292  */
293 void ShaderEffectApi::SetEffectImage( const v8::FunctionCallbackInfo< v8::Value >& args )
294 {
295   v8::Isolate* isolate = args.GetIsolate();
296   v8::HandleScope handleScope( isolate );
297
298   bool found( false );
299   Image image = V8Utils::GetImageParameter( PARAMETER_0, found, isolate, args );
300   if( !found )
301   {
302     DALI_SCRIPT_EXCEPTION( isolate, " Image::SetEffectImage invalid params");
303     return;
304   }
305   ShaderEffect effect =  GetShaderEffect( isolate, args );
306   effect.SetEffectImage( image );
307 }
308
309
310 /**
311  * Sets and registers a uniform property.
312  * If name matches a uniform in the shader source, this value will be uploaded when rendering.
313  * This uniform can then be animated / modified and the change will be made to the shader.
314  * @method setUniform
315  * @for ShaderEffect
316  * @param {String} name
317  * @param {Object} value must be a: float, vector2 vector3, vector4, matrix
318  * @param {String} [uniformCoordinateType] The coordinate type of the uniform.
319  * either "viewPortPosition" or "viewPortDirection"
320  * @example
321
322       var fragShader =
323       " uniform lowp vec4 uColorShift; \
324       \
325        void main()             \
326        {                  \
327
328          gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor + uColorShift; \
329        }"
330
331       var shaderOptions = {
332           geometryType: "image",
333           fragmentShader: fragShader
334       };
335
336       // create a new shader effect
337       var shader = new dali.ShaderEffect(shaderOptions);
338
339       // add the color shift uniform so we can animate it
340       // default the color shift to zero, so it has no effect
341       shader.setUniform("uColorShift", [0.0, 0.0, 0.0, 0]);
342  */
343 void ShaderEffectApi::SetUniform( const v8::FunctionCallbackInfo< v8::Value >& args )
344 {
345
346   v8::Isolate* isolate = args.GetIsolate();
347   v8::HandleScope handleScope( isolate );
348   ShaderEffect effect =  GetShaderEffect( isolate, args );
349
350   bool found(false);
351   std::string uniformName = V8Utils::GetStringParameter( PARAMETER_0 , found, isolate, args );
352   if( !found )
353   {
354     DALI_SCRIPT_EXCEPTION( isolate, "SetUniform: uniform name not found\n");
355     return;
356   }
357
358   Property::Value propValue = V8Utils::GetPropertyValueParameter( PARAMETER_1 , found, isolate, args );
359   if( !found )
360   {
361     DALI_SCRIPT_EXCEPTION( isolate, "SetUniform: value not found\n");
362     return;
363   }
364
365   std::string coordinateType = V8Utils::GetStringParameter( PARAMETER_2, found, isolate, args );
366   ShaderEffect::UniformCoordinateType uniformCoordinateType( ShaderEffect::COORDINATE_TYPE_DEFAULT );
367   if( found )
368   {
369     if( coordinateType == "viewPortPosition")
370     {
371       uniformCoordinateType = ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION;
372     }
373     else if ( coordinateType == "viewPortDirection ")
374     {
375       uniformCoordinateType = ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION;
376     }
377   }
378
379   switch( propValue.GetType() )
380   {
381     case Property::FLOAT:
382     {
383       effect.SetUniform( uniformName, propValue.Get<float>(), uniformCoordinateType );
384       break;
385     }
386     case Property::VECTOR2:
387     {
388       effect.SetUniform( uniformName, propValue.Get<Vector2>(), uniformCoordinateType );
389       break;
390     }
391     case Property::VECTOR3:
392     {
393       effect.SetUniform( uniformName, propValue.Get<Vector3>(), uniformCoordinateType );
394       break;
395     }
396     case Property::VECTOR4:
397     {
398       effect.SetUniform( uniformName, propValue.Get<Vector4>(), uniformCoordinateType );
399       break;
400     }
401     case Property::MATRIX:
402     {
403       effect.SetUniform( uniformName, propValue.Get<Matrix>(), uniformCoordinateType );
404       break;
405     }
406     case Property::MATRIX3:
407     {
408       effect.SetUniform( uniformName, propValue.Get<Matrix3>(), uniformCoordinateType );
409       break;
410     }
411     default:
412     {
413       DALI_SCRIPT_EXCEPTION( isolate, "value type not recognised \n");
414       break;
415     }
416   }
417 }
418
419
420 } // namespace V8Plugin
421
422 } // namespace Dali