2 * Copyright (c) 2016 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.
19 #include "blur-two-pass-filter.h"
23 #include <dali/public-api/animation/constraints.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/object/property-map.h>
26 #include <dali/public-api/render-tasks/render-task-list.h>
27 #include <dali/public-api/rendering/renderer.h>
28 #include <dali/devel-api/images/texture-set-image.h>
42 const float DEFAULT_KERNEL0[] = { 12.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f };
44 const float DEFAULT_KERNEL1[] = { 8.0f/16.0f, 2.75f/16.0f, 2.75f/16.0f, 1.25f/16.0f,
47 const float DEFAULT_KERNEL2[] = { 5.0f/16.0f, 2.75f/16.0f, 2.75f/16.0f, 1.75f/16.0f,
48 1.75f/16.0f, 1.5f/16.0f, 1.5f/16.0f };
50 const float DEFAULT_KERNEL3[] = { 3.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f,
51 2.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f, 0.5f/16.0f,
54 const float DEFAULT_KERNEL4[] = { 2.0f/16.0f, 1.5f/16.0f, 1.5f/16.0f, 1.5f/16.0f,
55 1.5f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f,
56 1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 0.5f/16.0f,
57 0.5f/16.0f, 0.5f/16.0f, 0.5f/16.0f };
59 const char* BLUR_TWO_PASS_FRAGMENT_SOURCE =
61 "precision highp float;\n"
62 "varying mediump vec2 vTexCoord;\n"
63 "uniform sampler2D sTexture;\n"
64 "uniform vec2 uSampleOffsets[NUM_SAMPLES];\n"
65 "uniform float uSampleWeights[NUM_SAMPLES];\n"
68 " vec4 color = vec4(0.0);\n"
69 " for( int i = 0; i < NUM_SAMPLES; ++i )\n"
71 " color += texture2D( sTexture, vTexCoord + uSampleOffsets[i] ) * uSampleWeights[i];\n"
73 " gl_FragColor = color;\n"
77 std::string GetOffsetUniformName( int index )
79 std::ostringstream oss;
80 oss << "uSampleOffsets[" << index << "]";
84 std::string GetWeightUniformName( int index )
86 std::ostringstream oss;
87 oss << "uSampleWeights[" << index << "]";
91 const char* BLEND_TWO_IMAGES_FRAGMENT_SOURCE =
93 "precision highp float;\n"
94 "uniform float uBlurStrength;\n "
95 "uniform sampler2D sTexture;\n"
96 "uniform sampler2D sEffect;\n"
97 "varying mediump vec2 vTexCoord;\n"
100 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uBlurStrength"
101 " + texture2D( sEffect, vTexCoord )*(1.0-uBlurStrength); \n"
105 const char* const BLUR_STRENGTH_UNIFORM_NAME( "uBlurStrength" );
106 const char* const EFFECT_IMAGE_NAME( "sEffect" );
111 BlurTwoPassFilter::BlurTwoPassFilter()
114 // create blending actor and register the property in constructor
115 // to make sure that GetBlurStrengthPropertyIndex() always returns a valid index
116 mActorForBlending = Toolkit::ImageView::New();
117 mBlurStrengthPropertyIndex = mActorForBlending.RegisterProperty( BLUR_STRENGTH_UNIFORM_NAME, 1.f );
120 BlurTwoPassFilter::~BlurTwoPassFilter()
124 void BlurTwoPassFilter::Enable()
126 // create actor to render input with applied emboss effect
127 mActorForInput = Toolkit::ImageView::New( mInputImage );
128 mActorForInput.SetParentOrigin( ParentOrigin::CENTER );
129 mActorForInput.SetSize( mTargetSize );
131 // create internal offscreen for result of horizontal pass
132 mImageForHorz = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
133 // create an actor to render mImageForHorz for vertical blur pass
134 mActorForHorz = Toolkit::ImageView::New( mImageForHorz );
135 mActorForHorz.SetParentOrigin( ParentOrigin::CENTER );
136 mActorForHorz.SetSize( mTargetSize );
138 // create internal offscreen for result of the two pass blurred image
139 mBlurredImage = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED);
140 // create an actor to blend the blurred image and the input image with the given blur strength
141 mActorForBlending.SetImage( mBlurredImage );
142 mActorForBlending.SetParentOrigin( ParentOrigin::CENTER );
143 mActorForBlending.SetSize( mTargetSize );
145 // create custom shader effect
146 if( !GetKernelSize() )
148 CreateKernel( DEFAULT_KERNEL4, sizeof(DEFAULT_KERNEL4)/sizeof(DEFAULT_KERNEL4[0]) );
150 int kernelSize( static_cast< int >(GetKernelSize()) );
152 for( int i = 0; i < kernelSize; ++i )
154 const std::string offsetUniform( GetOffsetUniformName( i ) );
155 const std::string weightUniform( GetWeightUniformName( i ) );
157 mActorForInput.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::XAXIS );
158 mActorForInput.RegisterProperty( weightUniform, mKernel[i].z );
160 mActorForHorz.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::YAXIS );
161 mActorForHorz.RegisterProperty( weightUniform, mKernel[i].z );
164 // Set up blur-two-pass custom shader
165 std::ostringstream fragmentSource;
166 fragmentSource << "#define NUM_SAMPLES " << kernelSize << "\n";
167 fragmentSource << BLUR_TWO_PASS_FRAGMENT_SOURCE;
169 Property::Map customShader;
170 customShader[ "fragmentShader" ] = fragmentSource.str();
171 Property::Map rendererMap;
172 rendererMap.Insert( "shader", customShader );
173 mActorForInput.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
174 mActorForHorz.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
176 // Set up blend-two-image custom shader
177 customShader[ "fragmentShader" ] = BLEND_TWO_IMAGES_FRAGMENT_SOURCE;
178 rendererMap[ "shader"] = customShader;
179 mActorForBlending.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
181 mRootActor.Add( mActorForInput );
182 mRootActor.Add( mActorForHorz );
183 mRootActor.Add( mActorForBlending );
185 // Add effect texture to blend-two-image custom shader
186 TextureSet textureSet = mActorForBlending.GetRendererAt(0).GetTextures();
187 TextureSetImage( textureSet, 1u, mInputImage );
193 void BlurTwoPassFilter::Disable()
199 mRootActor.Remove( mCameraActor );
200 mCameraActor.Reset();
205 mRootActor.Remove( mActorForInput );
206 mActorForInput.Reset();
211 mRootActor.Remove( mActorForHorz );
212 mActorForHorz.Reset();
215 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
217 if( mRenderTaskForHorz )
219 taskList.RemoveTask(mRenderTaskForHorz);
221 if( mRenderTaskForVert )
223 taskList.RemoveTask(mRenderTaskForVert);
225 if( mRenderTaskForBlending )
227 taskList.RemoveTask(mRenderTaskForBlending);
234 void BlurTwoPassFilter::Refresh()
236 if( mRenderTaskForHorz )
238 mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
241 if( mRenderTaskForVert )
243 mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
246 if( mRenderTaskForBlending )
248 mRenderTaskForBlending.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
252 void BlurTwoPassFilter::SetSize( const Vector2& size )
257 mActorForInput.SetSize(mTargetSize);
261 mActorForHorz.SetSize(mTargetSize);
263 if( mActorForBlending )
265 mActorForBlending.SetSize(mTargetSize);
269 Handle BlurTwoPassFilter::GetHandleForAnimateBlurStrength()
271 return mActorForBlending;
274 void BlurTwoPassFilter::CreateRenderTasks()
276 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
278 // perform a horizontal blur targeting the internal buffer
279 mRenderTaskForHorz = taskList.CreateTask();
280 mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
281 mRenderTaskForHorz.SetSourceActor( mActorForInput );
282 mRenderTaskForHorz.SetExclusive(true);
283 mRenderTaskForHorz.SetInputEnabled( false );
284 mRenderTaskForHorz.SetClearEnabled( true );
285 mRenderTaskForHorz.SetClearColor( mBackgroundColor );
286 mRenderTaskForHorz.SetTargetFrameBuffer( mImageForHorz );
287 mRenderTaskForHorz.SetCameraActor( mCameraActor );
289 // use the internal buffer and perform a horizontal blur targeting the output buffer
290 mRenderTaskForVert = taskList.CreateTask();
291 mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
292 mRenderTaskForVert.SetSourceActor( mActorForHorz );
293 mRenderTaskForVert.SetExclusive(true);
294 mRenderTaskForVert.SetInputEnabled( false );
295 mRenderTaskForVert.SetClearEnabled( true );
296 mRenderTaskForVert.SetClearColor( mBackgroundColor );
297 mRenderTaskForVert.SetTargetFrameBuffer( mBlurredImage );
298 mRenderTaskForVert.SetCameraActor( mCameraActor );
300 //Perform a blending between the blurred image and the input image
301 mRenderTaskForBlending = taskList.CreateTask();
302 mRenderTaskForBlending.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
303 mRenderTaskForBlending.SetSourceActor( mActorForBlending );
304 mRenderTaskForBlending.SetExclusive(true);
305 mRenderTaskForBlending.SetInputEnabled( false );
306 mRenderTaskForBlending.SetClearEnabled( true );
307 mRenderTaskForBlending.SetClearColor( mBackgroundColor );
308 mRenderTaskForBlending.SetTargetFrameBuffer( mOutputImage );
309 mRenderTaskForBlending.SetCameraActor( mCameraActor );
312 } // namespace Internal
314 } // namespace Toolkit