2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
17 #include <dali-toolkit/public-api/shader-effects/distance-field-effect.h>
19 #define STRINGIFY(...) #__VA_ARGS__
30 const std::string COLOR_PROPERTY_NAME( "uColor" );
31 const std::string SMOOTHING_PROPERTY_NAME( "uSmoothing" );
34 const std::string OUTLINE_ENABLE_PROPERTY_NAME( "uDoOutline" );
35 const std::string OUTLINECOLOR_PROPERTY_NAME( "uOutlineColor" );
36 const std::string OUTLINE_SIZE_PROPERTY_NAME( "uOutlineParams" );
39 const std::string GLOW_ENABLE_PROPERTY_NAME( "uDoGlow" );
40 const std::string GLOW_COLOR_PROPERTY_NAME( "uGlowColor" );
41 const std::string GLOW_BOUNDARY_PROPERTY_NAME( "uGlowBoundary" );
44 const std::string SHADOW_ENABLE_PROPERTY_NAME( "uDoShadow" );
45 const std::string SHADOW_COLOR_PROPERTY_NAME( "uShadowColor" );
46 const std::string SHADOW_OFFSET_PROPERTY_NAME( "uShadowOffset" );
49 DistanceFieldEffect::DistanceFieldEffect()
53 //Call the Parent copy constructor to add reference to the implementation for this object
54 DistanceFieldEffect::DistanceFieldEffect(ShaderEffect handle)
59 DistanceFieldEffect::~DistanceFieldEffect()
63 DistanceFieldEffect DistanceFieldEffect::New()
65 std::string fragmentShaderPrefix(
66 "#extension GL_OES_standard_derivatives : enable\n"
70 std::string fragmentShader(
71 "uniform mediump float uSmoothing;\n"
72 "uniform mediump float uGlowBoundary;\n"
73 "uniform mediump vec2 uOutlineParams;\n"
74 "uniform lowp vec4 uOutlineColor;\n"
75 "uniform lowp vec4 uShadowColor;\n"
76 "uniform mediump vec2 uShadowOffset;\n"
77 "uniform lowp vec4 uGlowColor;\n"
78 "uniform lowp float uDoOutline;\n"
79 "uniform lowp float uDoShadow;\n"
80 "uniform lowp float uDoGlow;\n"
84 " // sample distance field\n"
85 " mediump float distance = texture2D(sTexture, vTexCoord).a;\n"
86 " mediump float smoothWidth = fwidth(distance);\n"
87 " mediump float alphaFactor = smoothstep(uSmoothing - smoothWidth, uSmoothing + smoothWidth, distance);\n"
89 " if (uDoShadow == 0.0)\n"
91 " mediump float alpha = uColor.a * alphaFactor;\n"
92 " lowp vec4 rgb = uColor;\n"
94 " if (uDoOutline > 0.0)\n"
96 " mediump float outlineWidth = uOutlineParams[1] + smoothWidth;\n"
97 " mediump float outlineBlend = smoothstep(uOutlineParams[0] - outlineWidth, uOutlineParams[0] + outlineWidth, distance);\n"
98 " alpha = smoothstep(uSmoothing - smoothWidth, uSmoothing + smoothWidth, distance);\n"
99 " rgb = mix(uOutlineColor, uColor, outlineBlend);\n"
102 " if (uDoGlow > 0.0)\n"
104 " rgb = mix(uGlowColor, rgb, alphaFactor);\n"
105 " alpha = smoothstep(uGlowBoundary, uSmoothing, distance);\n"
108 " // set fragment color\n"
109 " color = vec4(rgb.rgb, alpha);\n"
112 " else // (uDoShadow > 0.0)\n"
114 " float shadowDistance = texture2D(sTexture, vTexCoord - uShadowOffset).a;\n"
115 " mediump float inText = alphaFactor;\n"
116 " mediump float inShadow = smoothstep(uSmoothing - smoothWidth, uSmoothing + smoothWidth, shadowDistance);\n"
118 " // inside object, outside shadow\n"
119 " if (inText == 1.0)\n"
123 " // inside object, outside shadow\n"
124 " else if ((inText != 0.0) && (inShadow == 0.0))\n"
127 " color.a *= inText;\n"
129 " // outside object, completely inside shadow\n"
130 " else if ((inText == 0.0) && (inShadow == 1.0))\n"
132 " color = uShadowColor;\n"
134 " // inside object, completely inside shadow\n"
135 " else if ((inText != 0.0) && (inShadow == 1.0))\n"
137 " color = mix(uShadowColor, uColor, inText);\n"
138 " color.a = uShadowColor.a;\n"
140 " // inside object, inside shadow's border\n"
141 " else if ((inText != 0.0) && (inShadow != 0.0))\n"
143 " color = mix(uShadowColor, uColor, inText);\n"
144 " color.a *= max(inText, inShadow);\n"
146 " // inside shadow's border\n"
147 " else if (inShadow != 0.0)\n"
149 " color = uShadowColor;\n"
150 " color.a *= inShadow;\n"
152 " // outside shadow and object\n"
160 " gl_FragColor = color;\n"
165 // Create the implementation, temporarily owned on stack
166 Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::NewWithPrefix("", "",
167 fragmentShaderPrefix, fragmentShader,
168 Dali::GeometryType( GEOMETRY_TYPE_IMAGE ),
169 ShaderEffect::GeometryHints( ShaderEffect::HINT_BLENDING));
171 /* Pass ownership to DistanceFieldEffect through overloaded constructor, So that it now has access to the
172 Dali::ShaderEffect implementation */
174 // TODO: move default values to... Constants?
175 Dali::Toolkit::DistanceFieldEffect handle( shaderEffect );
177 handle.SetSmoothingEdge(0.5f);
178 handle.SetOutlineColor(Color::BLACK);
179 handle.SetOutlineParams(Vector2(0.51f, 0.0f));
180 handle.SetGlowBoundary(0.4f);
181 handle.SetGlowColor(Color::GREEN);
182 handle.SetShadowColor(Vector4(0.0f, 0.0f, 0.0f, 0.4f));
184 // TODO: find a way to set the shadow offset in texel coordinates instead of UVs.
185 handle.SetShadowOffset(Vector2(0.05f, 0.05f));
188 handle.SetOutline(false);
189 handle.SetGlow(false);
190 handle.SetShadow(false);
196 void DistanceFieldEffect::SetGlowColor(const Vector4& color)
198 SetUniform(GLOW_COLOR_PROPERTY_NAME, color);
201 void DistanceFieldEffect::SetGlow(bool glowEnable)
203 const float a = glowEnable ? 1.0f : 0.0f;
204 SetUniform(GLOW_ENABLE_PROPERTY_NAME, a);
207 void DistanceFieldEffect::SetGlowBoundary(float glowBoundary)
209 SetUniform(GLOW_BOUNDARY_PROPERTY_NAME, glowBoundary);
212 void DistanceFieldEffect::SetOutline(bool outlineEnable)
214 const float a = outlineEnable ? 1.0f : 0.0f;
215 SetUniform(OUTLINE_ENABLE_PROPERTY_NAME, a);
218 void DistanceFieldEffect::SetOutlineColor(const Vector4& color)
220 SetUniform(OUTLINECOLOR_PROPERTY_NAME, color);
223 void DistanceFieldEffect::SetOutlineParams(const Vector2& outlineParams)
225 SetUniform(OUTLINE_SIZE_PROPERTY_NAME, outlineParams);
228 void DistanceFieldEffect::SetShadow(bool shadowEnable)
236 const float a = shadowEnable ? 1.0f : 0.0f;
237 SetUniform(SHADOW_ENABLE_PROPERTY_NAME, a);
240 void DistanceFieldEffect::SetShadowColor(const Vector4& color)
242 SetUniform(SHADOW_COLOR_PROPERTY_NAME, color);
245 void DistanceFieldEffect::SetShadowOffset(const Vector2& offset)
247 SetUniform(SHADOW_OFFSET_PROPERTY_NAME, offset);
250 void DistanceFieldEffect::SetSmoothingEdge(const float smoothing)
252 SetUniform(SMOOTHING_PROPERTY_NAME, smoothing);
255 const std::string& DistanceFieldEffect::GetColorPropertyName() const
257 return COLOR_PROPERTY_NAME;
260 const std::string& DistanceFieldEffect::GetOutlineColorPropertyName() const
262 return OUTLINECOLOR_PROPERTY_NAME;
265 const std::string& DistanceFieldEffect::GetShadowColorPropertyName() const
267 return SHADOW_COLOR_PROPERTY_NAME;
270 const std::string& DistanceFieldEffect::GetShadowOffsetPropertyName() const
272 return SHADOW_OFFSET_PROPERTY_NAME;
275 const std::string& DistanceFieldEffect::GetGlowColorPropertyName() const
277 return GLOW_COLOR_PROPERTY_NAME;
280 const std::string& DistanceFieldEffect::GetGlowBoundaryPropertyName() const
282 return GLOW_BOUNDARY_PROPERTY_NAME;
285 const std::string& DistanceFieldEffect::GetOutlineSizePropertyName() const
287 return OUTLINE_SIZE_PROPERTY_NAME;
290 const std::string& DistanceFieldEffect::GetOutlineEnablePropertyName() const
292 return OUTLINE_ENABLE_PROPERTY_NAME;
295 const std::string& DistanceFieldEffect::GetGlowEnablePropertyName() const
297 return GLOW_ENABLE_PROPERTY_NAME;
300 const std::string& DistanceFieldEffect::GetShadowEnablePropertyName() const
302 return SHADOW_ENABLE_PROPERTY_NAME;
305 const std::string& DistanceFieldEffect::GetSmoothingPropertyName() const
307 return SMOOTHING_PROPERTY_NAME;
310 } // namespace Toolkit