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 {"text", GEOMETRY_TYPE_TEXT },
51 {"mesh", GEOMETRY_TYPE_UNTEXTURED_MESH },
52 {"textured-mesh", GEOMETRY_TYPE_TEXTURED_MESH },
55 const unsigned int GeometryTypeTableCount = sizeof(GeometryTypeTable)/sizeof(GeometryTypeTable[0]);
57 struct GeometryHintPair
60 ShaderEffect::GeometryHints hint;
63 const GeometryHintPair GeometryHintTable[]=
65 {"gridX", ShaderEffect::HINT_GRID_X },
66 {"gridY", ShaderEffect::HINT_GRID_Y },
67 {"grid", ShaderEffect::HINT_GRID },
68 {"depthBuffer", ShaderEffect::HINT_DEPTH_BUFFER },
69 {"blending", ShaderEffect::HINT_BLENDING },
70 {"doesntModifyGeometry", ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY }
73 const unsigned int GeometryHintTableCount = sizeof(GeometryHintTable)/sizeof(GeometryHintTable[0]);
78 struct ShaderParameters
81 : mType( GEOMETRY_TYPE_IMAGE),
82 mHints( ShaderEffect::HINT_NONE )
86 void SetGeometryType( v8::Isolate* isolate, const std::string& typeName )
88 for( unsigned int i = 0; i < GeometryTypeTableCount; ++i )
90 if( typeName == GeometryTypeTable[i].name )
92 mType = GeometryTypeTable[i].type;
96 DALI_SCRIPT_EXCEPTION( isolate, "Geometry type not found\n");
99 ShaderEffect::GeometryHints GetGeometryHint( const std::string& hint )
101 for( unsigned int i = 0 ; i < GeometryHintTableCount; ++i )
103 if( hint == GeometryHintTable[i].name )
105 return GeometryHintTable[i].hint;
108 return ShaderEffect::HINT_NONE;
111 void ProcessHintsArray( const HintsArray& hintsArray )
113 for( HintsArray::const_iterator iter = hintsArray.begin(); iter != hintsArray.end() ; ++iter )
115 mHints= static_cast<ShaderEffect::GeometryHints>( mHints | GetGeometryHint( *iter ) );
121 ShaderEffect NewShader()
123 return ShaderEffect::NewWithPrefix( mVertexPrefix ,
130 std::string mVertexPrefix;
132 std::string mFragmentPrefix;
133 std::string mFragment;
135 ShaderEffect::GeometryHints mHints;
138 ShaderEffect GetShaderEffect( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
140 v8::HandleScope handleScope( isolate );
142 v8::Local<v8::Object> object = args.This();
143 v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
144 void* ptr = field->Value();
146 ShaderEffectWrapper* wrapper = static_cast< ShaderEffectWrapper *>(ptr);
147 return wrapper->GetShaderEffect();
153 * Create a new ShaderEffect
156 * @method ShaderEffect
157 * @param {Object} shaderOptions
158 * @param {String} [shaderOptions.geometryType] Type of geometry to be rendered with the effect. "image", "text", "mesh", "textured-mesh", default is image.
159 * @param {String} [shaderOptions.vertexShaderPrefix] This string will be inserted before the default uniforms for the vertex shader(ideal for #defines)
160 * @param {String} [shaderOptions.vertexShader] VertexShader code for the effect. If not defined, the default version will be used
161 * @param {String} [shaderOptions.fragmentShaderPrefix] This string will be inserted before the default uniforms for the fragment shader(ideal for #defines)
162 * @param {String} [shaderOptions.fragmentShader] FragmentShader code for the effect. If not defined, the default version will be used
163 * @param {Array} [shaderOptions.geometryHints] Hints for rendering the geometry, e.g. [ "gridX", "gridY", "grid","depthBuffer","blending","doesntModifyGeometry" ]
164 * @return {Object} ShaderEffect
167 // this will match the default shaders for image
168 var vertexShader = " void main() \
170 gl_Position = uProjection * uModelView * vec4(aPosition, 1.0); \
171 vTexCoord = aTexCoord; \
173 var fragShader = " void main() \
175 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\
177 var shaderOptions = {
178 geometryType: "image",
179 vertexShader: vertexShader,
180 fragmentShader: fragShader
183 var shader = new dali.ShaderEffect(shaderOptions);
185 imageActor.setShaderEffect( shader );
191 ShaderEffect ShaderEffectApi::New( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
193 v8::HandleScope handleScope( isolate );
195 if( args[0]->IsObject() )
197 ShaderParameters shaderParams;
199 v8::Local<v8::Object > obj = args[0]->ToObject();
201 v8::Local<v8::Value> geometryTypeValue = obj->Get(v8::String::NewFromUtf8( isolate, "geometryType"));
202 if( geometryTypeValue->IsString() )
204 std::string geometryTypeName = V8Utils::v8StringToStdString( geometryTypeValue );
205 // printf(" geometry type found %s \n", geometryTypeName.c_str() );
206 shaderParams.SetGeometryType( isolate, geometryTypeName );
209 v8::Local<v8::Value> vertexPrefixValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShaderPrefix"));
210 if( vertexPrefixValue->IsString() )
212 shaderParams.mVertexPrefix = V8Utils::v8StringToStdString( vertexPrefixValue );
215 v8::Local<v8::Value> fragmentPrefixValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShaderPrefix"));
216 if( fragmentPrefixValue->IsString() )
218 shaderParams.mFragmentPrefix = V8Utils::v8StringToStdString( fragmentPrefixValue );
221 v8::Local<v8::Value> vertexValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShader"));
222 if( vertexValue->IsString() )
224 shaderParams.mVertex = V8Utils::v8StringToStdString( vertexValue );
227 v8::Local<v8::Value> fragmentValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShader"));
228 if( fragmentValue->IsString() )
230 shaderParams.mFragment = V8Utils::v8StringToStdString( fragmentValue );
233 v8::Local<v8::Value> hints = obj->Get(v8::String::NewFromUtf8( isolate, "geometryHints"));
234 if( hints->IsArray() )
236 HintsArray hintsArray;
237 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( hints );
238 for( uint32_t i=0; i < array->Length(); ++i)
240 v8::Handle<v8::Value> entry = array->Get( v8::Integer::New( isolate, i) );
241 if( entry->IsString() )
243 std::string entryString = V8Utils::v8StringToStdString( entry );
244 hintsArray.push_back( entryString );
247 shaderParams.ProcessHintsArray( hintsArray );
250 return shaderParams.NewShader();
257 std::string typeName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
260 DALI_SCRIPT_EXCEPTION( isolate, "string parameter missing" );
264 // create a new shader effect based on type, using the type registry.
265 Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( typeName );
266 if( typeInfo ) // handle, check if it has a value
268 Dali::BaseHandle handle = typeInfo.CreateInstance();
271 effect = ShaderEffect::DownCast( handle );
276 DALI_SCRIPT_EXCEPTION(isolate,"Unknown shader effect type");
284 ShaderEffect ShaderEffectApi::GetShaderEffectFromParams( int paramIndex,
286 v8::Isolate* isolate,
287 const v8::FunctionCallbackInfo< v8::Value >& args )
291 v8::HandleScope handleScope( isolate );
292 BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::SHADER_EFFECT, isolate, args );
296 ShaderEffectWrapper* wrapper = static_cast< ShaderEffectWrapper *>(wrappedObject);
297 return wrapper->GetShaderEffect();
301 return ShaderEffect();
306 * Set a shader effect image.
307 * This image texture will be bound to the "sEffect" sampler
308 * so it can be used in fragment shader for effects
309 * @method setEffectImage
311 * @param {Object} image
314 * shader.setEffectImage( image );
316 * // example of a fragment shader than can use the effect image (sEffect and main texture sTexture)
320 * vec4 v4Color = (texture2D(sTexture, vTexCoord) * uColor); \
321 * v4Color = v4Color* texture2D(sEffect, vTexCoord);\
322 * gl_FragColor = v4Color; \"
325 void ShaderEffectApi::SetEffectImage( const v8::FunctionCallbackInfo< v8::Value >& args )
327 v8::Isolate* isolate = args.GetIsolate();
328 v8::HandleScope handleScope( isolate );
331 Image image = V8Utils::GetImageParameter( PARAMETER_0, found, isolate, args );
334 DALI_SCRIPT_EXCEPTION( isolate, " Image::SetEffectImage invalid params");
337 ShaderEffect effect = GetShaderEffect( isolate, args );
338 effect.SetEffectImage( image );
343 * Sets and registers a uniform property.
344 * If name matches a uniform in the shader source, this value will be uploaded when rendering.
345 * This uniform can then be animated / modified and the change will be made to the shader.
348 * @param {String} name
349 * @param {Object} value must be a: float, vector2 vector3, vector4, matrix
350 * @param {String} [uniformCoordinateType] The coordinate type of the uniform.
351 * either "viewPortPosition" or "viewPortDirection"
355 " uniform lowp vec4 uColorShift; \
360 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor + uColorShift; \
363 var shaderOptions = {
364 geometryType: "image",
365 fragmentShader: fragShader
368 // create a new shader effect
369 var shader = new dali.ShaderEffect(shaderOptions);
371 // add the color shift uniform so we can animate it
372 // default the color shift to zero, so it has no effect
373 shader.setUniform("uColorShift", [0.0, 0.0, 0.0, 0]);
375 void ShaderEffectApi::SetUniform( const v8::FunctionCallbackInfo< v8::Value >& args )
378 v8::Isolate* isolate = args.GetIsolate();
379 v8::HandleScope handleScope( isolate );
380 ShaderEffect effect = GetShaderEffect( isolate, args );
383 std::string uniformName = V8Utils::GetStringParameter( PARAMETER_0 , found, isolate, args );
386 DALI_SCRIPT_EXCEPTION( isolate, "SetUniform: uniform name not found\n");
390 Property::Value propValue = V8Utils::GetPropertyValueParameter( PARAMETER_1 , found, isolate, args );
393 DALI_SCRIPT_EXCEPTION( isolate, "SetUniform: value not found\n");
397 std::string coordinateType = V8Utils::GetStringParameter( PARAMETER_2, found, isolate, args );
398 ShaderEffect::UniformCoordinateType uniformCoordinateType( ShaderEffect::COORDINATE_TYPE_DEFAULT );
401 if( coordinateType == "viewPortPosition")
403 uniformCoordinateType = ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION;
405 else if ( coordinateType == "viewPortDirection ")
407 uniformCoordinateType = ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION;
411 switch( propValue.GetType() )
413 case Property::FLOAT:
415 effect.SetUniform( uniformName, propValue.Get<float>(), uniformCoordinateType );
418 case Property::VECTOR2:
420 effect.SetUniform( uniformName, propValue.Get<Vector2>(), uniformCoordinateType );
423 case Property::VECTOR3:
425 effect.SetUniform( uniformName, propValue.Get<Vector3>(), uniformCoordinateType );
428 case Property::VECTOR4:
430 effect.SetUniform( uniformName, propValue.Get<Vector4>(), uniformCoordinateType );
433 case Property::MATRIX:
435 effect.SetUniform( uniformName, propValue.Get<Matrix>(), uniformCoordinateType );
438 case Property::MATRIX3:
440 effect.SetUniform( uniformName, propValue.Get<Matrix3>(), uniformCoordinateType );
445 DALI_SCRIPT_EXCEPTION( isolate, "value type not recognised \n");
452 } // namespace V8Plugin