2 * Copyright (c) 2017 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>
31 #include <dali-toolkit/public-api/visuals/visual-properties.h>
45 const float DEFAULT_KERNEL0[] = { 12.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f };
47 const float DEFAULT_KERNEL1[] = { 8.0f/16.0f, 2.75f/16.0f, 2.75f/16.0f, 1.25f/16.0f,
50 const float DEFAULT_KERNEL2[] = { 5.0f/16.0f, 2.75f/16.0f, 2.75f/16.0f, 1.75f/16.0f,
51 1.75f/16.0f, 1.5f/16.0f, 1.5f/16.0f };
53 const float DEFAULT_KERNEL3[] = { 3.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f,
54 2.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f, 0.5f/16.0f,
57 const float DEFAULT_KERNEL4[] = { 2.0f/16.0f, 1.5f/16.0f, 1.5f/16.0f, 1.5f/16.0f,
58 1.5f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f,
59 1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 0.5f/16.0f,
60 0.5f/16.0f, 0.5f/16.0f, 0.5f/16.0f };
62 const char* BLUR_TWO_PASS_FRAGMENT_SOURCE =
64 "precision highp float;\n"
65 "varying mediump vec2 vTexCoord;\n"
66 "uniform sampler2D sTexture;\n"
67 "uniform vec2 uSampleOffsets[NUM_SAMPLES];\n"
68 "uniform float uSampleWeights[NUM_SAMPLES];\n"
71 " vec4 color = vec4(0.0);\n"
72 " for( int i = 0; i < NUM_SAMPLES; ++i )\n"
74 " color += texture2D( sTexture, vTexCoord + uSampleOffsets[i] ) * uSampleWeights[i];\n"
76 " gl_FragColor = color;\n"
80 std::string GetOffsetUniformName( int index )
82 std::ostringstream oss;
83 oss << "uSampleOffsets[" << index << "]";
87 std::string GetWeightUniformName( int index )
89 std::ostringstream oss;
90 oss << "uSampleWeights[" << index << "]";
94 const char* BLEND_TWO_IMAGES_FRAGMENT_SOURCE =
96 "precision highp float;\n"
97 "uniform float uBlurStrength;\n "
98 "uniform sampler2D sTexture;\n"
99 "uniform sampler2D sEffect;\n"
100 "varying mediump vec2 vTexCoord;\n"
103 " gl_FragColor = texture2D( sTexture, vTexCoord ) * uBlurStrength"
104 " + texture2D( sEffect, vTexCoord )*(1.0-uBlurStrength); \n"
108 const char* const BLUR_STRENGTH_UNIFORM_NAME( "uBlurStrength" );
109 const char* const EFFECT_IMAGE_NAME( "sEffect" );
114 BlurTwoPassFilter::BlurTwoPassFilter()
117 // create blending actor and register the property in constructor
118 // to make sure that GetBlurStrengthPropertyIndex() always returns a valid index
119 mActorForBlending = Toolkit::ImageView::New();
120 mBlurStrengthPropertyIndex = mActorForBlending.RegisterProperty( BLUR_STRENGTH_UNIFORM_NAME, 1.f );
123 BlurTwoPassFilter::~BlurTwoPassFilter()
127 void BlurTwoPassFilter::Enable()
129 // create actor to render input with applied emboss effect
130 mActorForInput = Toolkit::ImageView::New( mInputImage );
131 mActorForInput.SetParentOrigin( ParentOrigin::CENTER );
132 mActorForInput.SetSize( mTargetSize );
134 // create internal offscreen for result of horizontal pass
135 mImageForHorz = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
136 // create an actor to render mImageForHorz for vertical blur pass
137 mActorForHorz = Toolkit::ImageView::New( mImageForHorz );
138 mActorForHorz.SetParentOrigin( ParentOrigin::CENTER );
139 mActorForHorz.SetSize( mTargetSize );
141 // create internal offscreen for result of the two pass blurred image
142 mBlurredImage = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
143 // create an actor to blend the blurred image and the input image with the given blur strength
144 mActorForBlending.SetImage( mBlurredImage );
145 mActorForBlending.SetParentOrigin( ParentOrigin::CENTER );
146 mActorForBlending.SetSize( mTargetSize );
148 // create custom shader effect
149 if( !GetKernelSize() )
151 CreateKernel( DEFAULT_KERNEL4, sizeof(DEFAULT_KERNEL4)/sizeof(DEFAULT_KERNEL4[0]) );
153 int kernelSize( static_cast< int >(GetKernelSize()) );
155 for( int i = 0; i < kernelSize; ++i )
157 const std::string offsetUniform( GetOffsetUniformName( i ) );
158 const std::string weightUniform( GetWeightUniformName( i ) );
160 mActorForInput.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::XAXIS );
161 mActorForInput.RegisterProperty( weightUniform, mKernel[i].z );
163 mActorForHorz.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::YAXIS );
164 mActorForHorz.RegisterProperty( weightUniform, mKernel[i].z );
167 // Set up blur-two-pass custom shader
168 std::ostringstream fragmentSource;
169 fragmentSource << "#define NUM_SAMPLES " << kernelSize << "\n";
170 fragmentSource << BLUR_TWO_PASS_FRAGMENT_SOURCE;
172 Property::Map customShader;
173 customShader[ Toolkit::Visual::Shader::Property::FRAGMENT_SHADER ] = fragmentSource.str();
174 Property::Map visualMap;
175 visualMap.Insert( Toolkit::Visual::Property::SHADER, customShader );
176 mActorForInput.SetProperty( Toolkit::ImageView::Property::IMAGE, visualMap );
177 mActorForHorz.SetProperty( Toolkit::ImageView::Property::IMAGE, visualMap );
179 // Set up blend-two-image custom shader
180 customShader[ Toolkit::Visual::Shader::Property::FRAGMENT_SHADER ] = BLEND_TWO_IMAGES_FRAGMENT_SOURCE;
181 visualMap[ Toolkit::Visual::Property::SHADER ] = customShader;
182 mActorForBlending.SetProperty( Toolkit::ImageView::Property::IMAGE, visualMap );
184 mRootActor.Add( mActorForInput );
185 mRootActor.Add( mActorForHorz );
186 mRootActor.Add( mActorForBlending );
188 // Add effect texture to blend-two-image custom shader
189 TextureSet textureSet = mActorForBlending.GetRendererAt(0).GetTextures();
192 TextureSetImage( textureSet, 1u, mInputImage );
199 void BlurTwoPassFilter::Disable()
205 mRootActor.Remove( mCameraActor );
206 mCameraActor.Reset();
211 mRootActor.Remove( mActorForInput );
212 mActorForInput.Reset();
217 mRootActor.Remove( mActorForHorz );
218 mActorForHorz.Reset();
221 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
223 if( mRenderTaskForHorz )
225 taskList.RemoveTask(mRenderTaskForHorz);
227 if( mRenderTaskForVert )
229 taskList.RemoveTask(mRenderTaskForVert);
231 if( mRenderTaskForBlending )
233 taskList.RemoveTask(mRenderTaskForBlending);
240 void BlurTwoPassFilter::Refresh()
242 if( mRenderTaskForHorz )
244 mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
247 if( mRenderTaskForVert )
249 mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
252 if( mRenderTaskForBlending )
254 mRenderTaskForBlending.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
258 void BlurTwoPassFilter::SetSize( const Vector2& size )
263 mActorForInput.SetSize(mTargetSize);
267 mActorForHorz.SetSize(mTargetSize);
269 if( mActorForBlending )
271 mActorForBlending.SetSize(mTargetSize);
275 Handle BlurTwoPassFilter::GetHandleForAnimateBlurStrength()
277 return mActorForBlending;
280 void BlurTwoPassFilter::CreateRenderTasks()
282 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
284 // perform a horizontal blur targeting the internal buffer
285 mRenderTaskForHorz = taskList.CreateTask();
286 mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
287 mRenderTaskForHorz.SetSourceActor( mActorForInput );
288 mRenderTaskForHorz.SetExclusive(true);
289 mRenderTaskForHorz.SetInputEnabled( false );
290 mRenderTaskForHorz.SetClearEnabled( true );
291 mRenderTaskForHorz.SetClearColor( mBackgroundColor );
292 mRenderTaskForHorz.SetTargetFrameBuffer( mImageForHorz );
293 mRenderTaskForHorz.SetCameraActor( mCameraActor );
295 // use the internal buffer and perform a horizontal blur targeting the output buffer
296 mRenderTaskForVert = taskList.CreateTask();
297 mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
298 mRenderTaskForVert.SetSourceActor( mActorForHorz );
299 mRenderTaskForVert.SetExclusive(true);
300 mRenderTaskForVert.SetInputEnabled( false );
301 mRenderTaskForVert.SetClearEnabled( true );
302 mRenderTaskForVert.SetClearColor( mBackgroundColor );
303 mRenderTaskForVert.SetTargetFrameBuffer( mBlurredImage );
304 mRenderTaskForVert.SetCameraActor( mCameraActor );
306 //Perform a blending between the blurred image and the input image
307 mRenderTaskForBlending = taskList.CreateTask();
308 mRenderTaskForBlending.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
309 mRenderTaskForBlending.SetSourceActor( mActorForBlending );
310 mRenderTaskForBlending.SetExclusive(true);
311 mRenderTaskForBlending.SetInputEnabled( false );
312 mRenderTaskForBlending.SetClearEnabled( true );
313 mRenderTaskForBlending.SetClearColor( mBackgroundColor );
314 mRenderTaskForBlending.SetTargetFrameBuffer( mOutputImage );
315 mRenderTaskForBlending.SetCameraActor( mCameraActor );
318 } // namespace Internal
320 } // namespace Toolkit