d4ea4cef130ca298df8ee8f36f0cd9dbdcdc5b85
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / filters / emboss-filter.cpp
1 /*
2  * Copyright (c) 2014 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 // CLASS HEADER
19 #include "emboss-filter.h"
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <dali/public-api/animation/constraints.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/render-tasks/render-task-list.h>
26 #include <dali/public-api/shader-effects/shader-effect.h>
27
28 // INTERNAL INCLUDES
29
30 namespace Dali
31 {
32
33 namespace Toolkit
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
43
44 const char* EMBOSS_FRAGMENT_SOURCE1 =
45 {
46  "precision highp float;\n"
47  "uniform vec2 uTexScale;\n"
48  "\n"
49  "void main()\n"
50  "{\n"
51  "  vec4 color;\n"
52  "# ifdef DEBUG_RENDER\n"
53  "  if( vTexCoord.s < 0.495 )\n"
54  "  {\n"
55  "# endif //def DEBUG_RENDER\n"
56  "    color  =  2.0 * texture2D( sTexture, vTexCoord + vec2(0.0, -uTexScale.y) );\n"
57  "    color += -1.0 * texture2D( sTexture, vTexCoord );\n"
58  "    color += -1.0 * texture2D( sTexture, vTexCoord + vec2(0.0, uTexScale.y) );\n"
59  "# ifdef DEBUG_RENDER\n"
60  "  }\n"
61  "  else if( vTexCoord.s > 0.505 )\n"
62  "  {\n"
63  "    color = texture2D( sTexture, vTexCoord );\n"
64  "  }\n"
65  "  else\n"
66  "  {\n"
67  "    color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
68  "  }\n"
69  "# endif //def DEBUG_RENDER\n"
70  "  gl_FragColor = uColor * color;\n"
71  "}\n"
72 };
73
74 const char* EMBOSS_FRAGMENT_SOURCE2 =
75 {
76  "precision highp float;\n"
77  "uniform vec2 uTexScale;\n"
78  "\n"
79  "void main()\n"
80  "{\n"
81  "  vec4 color;\n"
82  "# ifdef DEBUG_RENDER\n"
83  "  if( vTexCoord.s < 0.495 )\n"
84  "  {\n"
85  "# endif //def DEBUG_RENDER\n"
86  "    color  = -1.0 * texture2D( sTexture, vTexCoord + vec2(0.0, -uTexScale.y) );\n"
87  "    color += -1.0 * texture2D( sTexture, vTexCoord );\n"
88  "    color +=  2.0 * texture2D( sTexture, vTexCoord + vec2(0.0, uTexScale.y) );\n"
89  "# ifdef DEBUG_RENDER\n"
90  "  }\n"
91  "  else if( vTexCoord.s > 0.505 )\n"
92  "  {\n"
93  "    color = texture2D( sTexture, vTexCoord );\n"
94  "  }\n"
95  "  else\n"
96  "  {\n"
97  "    color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
98  "  }\n"
99  "# endif //def DEBUG_RENDER\n"
100  "  gl_FragColor = uColor * color;\n"
101  "}\n"
102 };
103
104 const char* const COMPOSITE_FRAGMENT_SOURCE =
105     "void main()\n"
106     "{\n"
107     "  gl_FragColor = uColor;\n"
108     "  gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n"
109     "}\n";
110
111 } // namespace
112
113 EmbossFilter::EmbossFilter()
114 : ImageFilter()
115 {
116 }
117
118 EmbossFilter::~EmbossFilter()
119 {
120 }
121
122 void EmbossFilter::Enable()
123 {
124   // Create camera
125   mCameraActor = CameraActor::New();
126   mCameraActor.SetParentOrigin(ParentOrigin::CENTER);
127
128   mImageForEmboss1 = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
129   mImageForEmboss2 = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
130
131   // create actor to render input with applied emboss effect
132   mActorForInput1 = ImageActor::New( mInputImage );
133   mActorForInput1.SetParentOrigin( ParentOrigin::CENTER );
134   mActorForInput1.SetSize(mTargetSize);
135   mActorForInput1.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
136   mActorForInput1.SetColor( Color::WHITE );
137
138   mActorForInput2 = ImageActor::New( mInputImage );
139   mActorForInput2.SetParentOrigin( ParentOrigin::CENTER );
140   mActorForInput2.SetSize(mTargetSize);
141   mActorForInput2.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
142   mActorForInput2.SetColor( Color::WHITE );
143
144   mActorForEmboss1 = ImageActor::New( mImageForEmboss1 );
145   mActorForEmboss1.SetParentOrigin( ParentOrigin::CENTER );
146   mActorForEmboss1.SetSize(mTargetSize);
147   mActorForEmboss1.SetColor( Color::BLACK );
148   mActorForEmboss1.SetShaderEffect( ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE ) );
149
150   mActorForEmboss2 = ImageActor::New( mImageForEmboss2 );
151   mActorForEmboss2.SetParentOrigin( ParentOrigin::CENTER );
152   mActorForEmboss2.SetSize(mTargetSize);
153   mActorForEmboss2.SetColor( Color::WHITE );
154   mActorForEmboss2.SetShaderEffect( ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE ) );
155
156   mActorForComposite = Actor::New();
157   mActorForComposite.SetParentOrigin( ParentOrigin::CENTER );
158   mActorForComposite.SetSize(mTargetSize);
159   mActorForComposite.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
160
161   // create custom shader effect
162   std::ostringstream embossFragmentSource1;
163   if( mDebugRender )
164   {
165     embossFragmentSource1 << "#define DEBUG_RENDER\n";
166   }
167   embossFragmentSource1 << EMBOSS_FRAGMENT_SOURCE1;
168   ShaderEffect effect1 = ShaderEffect::New( "", embossFragmentSource1.str() );
169   mActorForInput1.SetShaderEffect( effect1 );
170   effect1.SetUniform( "uTexScale", Vector2( 1.0f/mTargetSize.width, 1.0f/mTargetSize.height) * 1.5f );
171
172   std::ostringstream embossFragmentSource2;
173   if( mDebugRender )
174   {
175     embossFragmentSource2 << "#define DEBUG_RENDER\n";
176   }
177   embossFragmentSource2 << EMBOSS_FRAGMENT_SOURCE2;
178   ShaderEffect effect2 = ShaderEffect::New( "", embossFragmentSource2.str() );
179   mActorForInput2.SetShaderEffect( effect2 );
180   effect2.SetUniform( "uTexScale", Vector2( 1.0f/mTargetSize.width, 1.0f/mTargetSize.height) * 1.5f );
181
182   SetupCamera();
183   CreateRenderTasks();
184
185   mRootActor.Add( mActorForInput1 );
186   mRootActor.Add( mActorForInput2 );
187   mRootActor.Add( mActorForComposite );
188   mActorForComposite.Add( mActorForEmboss1 );
189   mActorForComposite.Add( mActorForEmboss2 );
190   mRootActor.Add( mCameraActor );
191 }
192
193 void EmbossFilter::Disable()
194 {
195   if( mRootActor )
196   {
197     if( mCameraActor )
198     {
199       mRootActor.Remove( mCameraActor );
200       mCameraActor.Reset();
201     }
202
203     if( mActorForInput1 )
204     {
205       mRootActor.Remove( mActorForInput1 );
206       mActorForInput1.Reset();
207     }
208
209     if( mActorForInput2 )
210     {
211       mRootActor.Remove( mActorForInput2 );
212       mActorForInput2.Reset();
213     }
214
215     if( mActorForComposite )
216     {
217       mRootActor.Remove( mActorForComposite );
218       mActorForComposite.Reset();
219       mActorForEmboss1.Reset();
220       mActorForEmboss2.Reset();
221     }
222
223     RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
224     if( mRenderTaskForEmboss1 )
225     {
226       taskList.RemoveTask(mRenderTaskForEmboss1);
227     }
228
229     if( mRenderTaskForEmboss2 )
230     {
231       taskList.RemoveTask(mRenderTaskForEmboss2);
232     }
233
234     mRootActor.Reset();
235   }
236 }
237
238 void EmbossFilter::Refresh()
239 {
240   if( mRenderTaskForEmboss1 )
241   {
242     mRenderTaskForEmboss1.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
243   }
244   if( mRenderTaskForEmboss2 )
245   {
246     mRenderTaskForEmboss2.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
247   }
248 }
249
250 void EmbossFilter::SetSize( const Vector2& size )
251 {
252   mTargetSize = size;
253   if( mActorForInput1 )
254   {
255     mActorForInput1.SetSize(mTargetSize);
256   }
257   if( mActorForInput2 )
258   {
259     mActorForInput2.SetSize(mTargetSize);
260   }
261   if( mActorForEmboss1 )
262   {
263     mActorForEmboss1.SetSize(mTargetSize);
264   }
265   if( mActorForEmboss2 )
266   {
267     mActorForEmboss2.SetSize(mTargetSize);
268   }
269   if( mActorForComposite )
270   {
271     mActorForComposite.SetSize(mTargetSize);
272   }
273 }
274
275 void EmbossFilter::SetupCamera()
276 {
277   // Create and place a camera for the embossing render, corresponding to its render target size
278   mCameraActor.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
279   mCameraActor.SetNearClippingPlane(1.0f);
280   mCameraActor.SetAspectRatio(mTargetSize.width / mTargetSize.height);
281   mCameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
282   mCameraActor.SetOrientation(Quaternion(M_PI, Vector3::YAXIS));
283   mCameraActor.SetPosition(0.0f, 0.0f, ((mTargetSize.height * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
284 }
285
286 void EmbossFilter::CreateRenderTasks()
287 {
288   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
289
290   mRenderTaskForEmboss1 = taskList.CreateTask();
291   mRenderTaskForEmboss1.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
292   mRenderTaskForEmboss1.SetSourceActor( mActorForInput1 );
293   mRenderTaskForEmboss1.SetExclusive(true);
294   mRenderTaskForEmboss1.SetInputEnabled( false );
295   mRenderTaskForEmboss1.SetClearColor( Vector4( 0.0f, 0.0f, 0.0f, 0.0f ) );
296   mRenderTaskForEmboss1.SetClearEnabled( true );
297   mRenderTaskForEmboss1.SetTargetFrameBuffer( mImageForEmboss1 );
298   mRenderTaskForEmboss1.SetCameraActor( mCameraActor );
299
300   mRenderTaskForEmboss2 = taskList.CreateTask();
301   mRenderTaskForEmboss2.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
302   mRenderTaskForEmboss2.SetSourceActor( mActorForInput2 );
303   mRenderTaskForEmboss2.SetExclusive(true);
304   mRenderTaskForEmboss2.SetInputEnabled( false );
305   mRenderTaskForEmboss2.SetClearColor( Vector4( 1.0f, 1.0f, 1.0f, 0.0f ) );
306   mRenderTaskForEmboss2.SetClearEnabled( true );
307   mRenderTaskForEmboss2.SetTargetFrameBuffer( mImageForEmboss2 );
308   mRenderTaskForEmboss2.SetCameraActor( mCameraActor );
309
310   mRenderTaskForOutput = taskList.CreateTask();
311   mRenderTaskForOutput.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
312   mRenderTaskForOutput.SetSourceActor( mActorForComposite );
313   mRenderTaskForOutput.SetExclusive(true);
314   mRenderTaskForOutput.SetInputEnabled( false );
315   mRenderTaskForOutput.SetClearColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0f ) );
316   mRenderTaskForOutput.SetClearEnabled( true );
317   mRenderTaskForOutput.SetTargetFrameBuffer( mOutputImage );
318   mRenderTaskForOutput.SetCameraActor( mCameraActor );
319 }
320
321 } // namespace Internal
322
323 } // namespace Toolkit
324
325 } // namespace Dali