2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "shader-effect-api.h"
23 #include <dali/public-api/object/type-registry.h>
27 #include <shader-effects/shader-effect-wrapper.h>
35 namespace // un named namespace
38 typedef std::vector< std::string > HintsArray;
41 struct GeometryTypePair
47 const GeometryTypePair GeometryTypeTable[]=
49 {"image", GEOMETRY_TYPE_IMAGE },
50 {"mesh", GEOMETRY_TYPE_UNTEXTURED_MESH },
51 {"textured-mesh", GEOMETRY_TYPE_TEXTURED_MESH },
54 const unsigned int GeometryTypeTableCount = sizeof(GeometryTypeTable)/sizeof(GeometryTypeTable[0]);
56 struct GeometryHintPair
59 ShaderEffect::GeometryHints hint;
62 const GeometryHintPair GeometryHintTable[]=
64 {"gridX", ShaderEffect::HINT_GRID_X },
65 {"gridY", ShaderEffect::HINT_GRID_Y },
66 {"grid", ShaderEffect::HINT_GRID },
67 {"depthBuffer", ShaderEffect::HINT_DEPTH_BUFFER },
68 {"blending", ShaderEffect::HINT_BLENDING },
69 {"doesntModifyGeometry", ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY }
72 const unsigned int GeometryHintTableCount = sizeof(GeometryHintTable)/sizeof(GeometryHintTable[0]);
77 struct ShaderParameters
80 : mType( GEOMETRY_TYPE_IMAGE),
81 mHints( ShaderEffect::HINT_NONE )
85 void SetGeometryType( v8::Isolate* isolate, const std::string& typeName )
87 for( unsigned int i = 0; i < GeometryTypeTableCount; ++i )
89 if( typeName == GeometryTypeTable[i].name )
91 mType = GeometryTypeTable[i].type;
95 DALI_SCRIPT_EXCEPTION( isolate, "Geometry type not found\n");
98 ShaderEffect::GeometryHints GetGeometryHint( const std::string& hint )
100 for( unsigned int i = 0 ; i < GeometryHintTableCount; ++i )
102 if( hint == GeometryHintTable[i].name )
104 return GeometryHintTable[i].hint;
107 return ShaderEffect::HINT_NONE;
110 void ProcessHintsArray( const HintsArray& hintsArray )
112 for( HintsArray::const_iterator iter = hintsArray.begin(); iter != hintsArray.end() ; ++iter )
114 mHints= static_cast<ShaderEffect::GeometryHints>( mHints | GetGeometryHint( *iter ) );
120 ShaderEffect NewShader()
122 return ShaderEffect::NewWithPrefix( mVertexPrefix ,
129 std::string mVertexPrefix;
131 std::string mFragmentPrefix;
132 std::string mFragment;
134 ShaderEffect::GeometryHints mHints;
137 ShaderEffect GetShaderEffect( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
139 v8::HandleScope handleScope( isolate );
141 v8::Local<v8::Object> object = args.This();
142 v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
143 void* ptr = field->Value();
145 ShaderEffectWrapper* wrapper = static_cast< ShaderEffectWrapper *>(ptr);
146 return wrapper->GetShaderEffect();
152 * Create a new ShaderEffect
155 * @method ShaderEffect
156 * @param {Object} shaderOptions
157 * @param {String} [shaderOptions.geometryType] Type of geometry to be rendered with the effect. "image", "text", "mesh", "textured-mesh", default is image.
158 * @param {String} [shaderOptions.vertexShaderPrefix] This string will be inserted before the default uniforms for the vertex shader(ideal for #defines)
159 * @param {String} [shaderOptions.vertexShader] VertexShader code for the effect. If not defined, the default version will be used
160 * @param {String} [shaderOptions.fragmentShaderPrefix] This string will be inserted before the default uniforms for the fragment shader(ideal for #defines)
161 * @param {String} [shaderOptions.fragmentShader] FragmentShader code for the effect. If not defined, the default version will be used
162 * @param {Array} [shaderOptions.geometryHints] Hints for rendering the geometry, e.g. [ "gridX", "gridY", "grid","depthBuffer","blending","doesntModifyGeometry" ]
163 * @return {Object} ShaderEffect
166 // this will match the default shaders for image
167 var vertexShader = " void main() \
169 gl_Position = uProjection * uModelView * vec4(aPosition, 1.0); \
170 vTexCoord = aTexCoord; \
172 var fragShader = " void main() \
174 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\
176 var shaderOptions = {
177 geometryType: "image",
178 vertexShader: vertexShader,
179 fragmentShader: fragShader
182 var shader = new dali.ShaderEffect(shaderOptions);
184 imageActor.setShaderEffect( shader );
190 ShaderEffect ShaderEffectApi::New( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
192 v8::HandleScope handleScope( isolate );
194 if( args[0]->IsObject() )
196 ShaderParameters shaderParams;
198 v8::Local<v8::Object > obj = args[0]->ToObject();
200 v8::Local<v8::Value> geometryTypeValue = obj->Get(v8::String::NewFromUtf8( isolate, "geometryType"));
201 if( geometryTypeValue->IsString() )
203 std::string geometryTypeName = V8Utils::v8StringToStdString( geometryTypeValue );
204 // printf(" geometry type found %s \n", geometryTypeName.c_str() );
205 shaderParams.SetGeometryType( isolate, geometryTypeName );
208 v8::Local<v8::Value> vertexPrefixValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShaderPrefix"));
209 if( vertexPrefixValue->IsString() )
211 shaderParams.mVertexPrefix = V8Utils::v8StringToStdString( vertexPrefixValue );
214 v8::Local<v8::Value> fragmentPrefixValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShaderPrefix"));
215 if( fragmentPrefixValue->IsString() )
217 shaderParams.mFragmentPrefix = V8Utils::v8StringToStdString( fragmentPrefixValue );
220 v8::Local<v8::Value> vertexValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShader"));
221 if( vertexValue->IsString() )
223 shaderParams.mVertex = V8Utils::v8StringToStdString( vertexValue );
226 v8::Local<v8::Value> fragmentValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShader"));
227 if( fragmentValue->IsString() )
229 shaderParams.mFragment = V8Utils::v8StringToStdString( fragmentValue );
232 v8::Local<v8::Value> hints = obj->Get(v8::String::NewFromUtf8( isolate, "geometryHints"));
233 if( hints->IsArray() )
235 HintsArray hintsArray;
236 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( hints );
237 for( uint32_t i=0; i < array->Length(); ++i)
239 v8::Handle<v8::Value> entry = array->Get( v8::Integer::New( isolate, i) );
240 if( entry->IsString() )
242 std::string entryString = V8Utils::v8StringToStdString( entry );
243 hintsArray.push_back( entryString );
246 shaderParams.ProcessHintsArray( hintsArray );
249 return shaderParams.NewShader();
256 std::string typeName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
259 DALI_SCRIPT_EXCEPTION( isolate, "string parameter missing" );
263 // create a new shader effect based on type, using the type registry.
264 Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( typeName );
265 if( typeInfo ) // handle, check if it has a value
267 Dali::BaseHandle handle = typeInfo.CreateInstance();
270 effect = ShaderEffect::DownCast( handle );
275 DALI_SCRIPT_EXCEPTION(isolate,"Unknown shader effect type");
283 ShaderEffect ShaderEffectApi::GetShaderEffectFromParams( int paramIndex,
285 v8::Isolate* isolate,
286 const v8::FunctionCallbackInfo< v8::Value >& args )
290 v8::HandleScope handleScope( isolate );
291 BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::SHADER_EFFECT, isolate, args );
295 ShaderEffectWrapper* wrapper = static_cast< ShaderEffectWrapper *>(wrappedObject);
296 return wrapper->GetShaderEffect();
300 return ShaderEffect();
305 * Set a shader effect image.
306 * This image texture will be bound to the "sEffect" sampler
307 * so it can be used in fragment shader for effects
308 * @method setEffectImage
310 * @param {Object} image
313 * shader.setEffectImage( image );
315 * // example of a fragment shader than can use the effect image (sEffect and main texture sTexture)
319 * vec4 v4Color = (texture2D(sTexture, vTexCoord) * uColor); \
320 * v4Color = v4Color* texture2D(sEffect, vTexCoord);\
321 * gl_FragColor = v4Color; \"
324 void ShaderEffectApi::SetEffectImage( const v8::FunctionCallbackInfo< v8::Value >& args )
326 v8::Isolate* isolate = args.GetIsolate();
327 v8::HandleScope handleScope( isolate );
330 Image image = V8Utils::GetImageParameter( PARAMETER_0, found, isolate, args );
333 DALI_SCRIPT_EXCEPTION( isolate, " Image::SetEffectImage invalid params");
336 ShaderEffect effect = GetShaderEffect( isolate, args );
337 effect.SetEffectImage( image );
342 * Sets and registers a uniform property.
343 * If name matches a uniform in the shader source, this value will be uploaded when rendering.
344 * This uniform can then be animated / modified and the change will be made to the shader.
347 * @param {String} name
348 * @param {Object} value must be a: float, vector2 vector3, vector4, matrix
349 * @param {String} [uniformCoordinateType] The coordinate type of the uniform.
350 * either "viewPortPosition" or "viewPortDirection"
354 " uniform lowp vec4 uColorShift; \
359 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor + uColorShift; \
362 var shaderOptions = {
363 geometryType: "image",
364 fragmentShader: fragShader
367 // create a new shader effect
368 var shader = new dali.ShaderEffect(shaderOptions);
370 // add the color shift uniform so we can animate it
371 // default the color shift to zero, so it has no effect
372 shader.setUniform("uColorShift", [0.0, 0.0, 0.0, 0]);
374 void ShaderEffectApi::SetUniform( const v8::FunctionCallbackInfo< v8::Value >& args )
377 v8::Isolate* isolate = args.GetIsolate();
378 v8::HandleScope handleScope( isolate );
379 ShaderEffect effect = GetShaderEffect( isolate, args );
382 std::string uniformName = V8Utils::GetStringParameter( PARAMETER_0 , found, isolate, args );
385 DALI_SCRIPT_EXCEPTION( isolate, "SetUniform: uniform name not found\n");
389 Property::Value propValue = V8Utils::GetPropertyValueParameter( PARAMETER_1 , found, isolate, args );
392 DALI_SCRIPT_EXCEPTION( isolate, "SetUniform: value not found\n");
396 std::string coordinateType = V8Utils::GetStringParameter( PARAMETER_2, found, isolate, args );
397 ShaderEffect::UniformCoordinateType uniformCoordinateType( ShaderEffect::COORDINATE_TYPE_DEFAULT );
400 if( coordinateType == "viewPortPosition")
402 uniformCoordinateType = ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION;
404 else if ( coordinateType == "viewPortDirection ")
406 uniformCoordinateType = ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION;
410 switch( propValue.GetType() )
412 case Property::FLOAT:
414 effect.SetUniform( uniformName, propValue.Get<float>(), uniformCoordinateType );
417 case Property::VECTOR2:
419 effect.SetUniform( uniformName, propValue.Get<Vector2>(), uniformCoordinateType );
422 case Property::VECTOR3:
424 effect.SetUniform( uniformName, propValue.Get<Vector3>(), uniformCoordinateType );
427 case Property::VECTOR4:
429 effect.SetUniform( uniformName, propValue.Get<Vector4>(), uniformCoordinateType );
432 case Property::MATRIX:
434 effect.SetUniform( uniformName, propValue.Get<Matrix>(), uniformCoordinateType );
437 case Property::MATRIX3:
439 effect.SetUniform( uniformName, propValue.Get<Matrix3>(), uniformCoordinateType );
444 DALI_SCRIPT_EXCEPTION( isolate, "value type not recognised \n");
451 } // namespace V8Plugin