2 * Copyright (c) 2014 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 "gaussian-blur-view-impl.h"
24 #include <dali/public-api/animation/constraint.h>
25 #include <dali/public-api/animation/constraints.h>
26 #include <dali/public-api/common/stage.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/public-api/render-tasks/render-task-list.h>
30 #include <dali/integration-api/debug.h>
33 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
36 // pixel format / size - set from JSON
37 // aspect ratio property needs to be able to be constrained also for cameras, not possible currently. Therefore changing aspect ratio of GaussianBlurView won't currently work
38 // default near clip value
39 // Manager object - re-use render targets if there are multiple GaussianBlurViews created
42 /////////////////////////////////////////////////////////
43 // IMPLEMENTATION NOTES
45 // As the GaussianBlurView actor changes size, the amount of pixels we need to blur changes. Therefore we need some way of doing this. However:-
46 // OnSetSize() does not get called when GaussianBlurView object size is modified using a Constraint.
47 // OnSizeAnimation() only gets called once per AnimateTo/By() and if an Animation has N such calls then only the final one will end up being used. Therefore we can't use
48 // OnSizeAnimation() to alter render target sizes.
49 // To get around the above problems, we use fixed sized render targets, from the last SetSize() call (which calls OnSetSize()), then we adjust the internal cameras / actors
50 // to take account of the changed GaussianBlurView object size, projecting to the unchanged render target sizes. This is done relative to the fixed render target / actor sizes
51 // by using constraints relative to the GaussianBlurView actor size.
55 // 1st mode, this control has a tree of actors (use Add() to add children) that are rendered and blurred.
56 // mRenderChildrenTask renders children to FB mRenderTargetForRenderingChildren
57 // mHorizBlurTask renders mImageViewHorizBlur Actor showing FB mRenderTargetForRenderingChildren into FB mRenderTarget2
58 // mVertBlurTask renders mImageViewVertBlur Actor showing FB mRenderTarget2 into FB mRenderTarget1
59 // mCompositeTask renders mImageViewComposite Actor showing FB mRenderTarget1 into FB mRenderTargetForRenderingChildren
61 // 2nd mode, an image is blurred and rendered to a supplied target framebuffer
62 // mHorizBlurTask renders mImageViewHorizBlur Actor showing mUserInputImage into FB mRenderTarget2
63 // mVertBlurTask renders mImageViewVertBlur Actor showing mRenderTarget2 into FB mUserOutputRenderTarget
65 // Only this 2nd mode handles ActivateOnce
83 return Toolkit::GaussianBlurView::New();
86 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::GaussianBlurView, Toolkit::Control, Create )
87 DALI_TYPE_REGISTRATION_END()
89 const unsigned int GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES = 5;
90 const float GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH = 1.5f;
91 const Pixel::Format GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
92 const float GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH = 1.0f; // default, fully blurred
93 const char* const GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME = "GaussianBlurStrengthPropertyName";
94 const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
95 const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
97 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
99 const char* const GAUSSIAN_BLUR_FRAGMENT_SOURCE =
100 "varying mediump vec2 vTexCoord;\n"
101 "uniform sampler2D sTexture;\n"
102 "uniform lowp vec4 uColor;\n"
103 "uniform mediump vec2 uSampleOffsets[NUM_SAMPLES];\n"
104 "uniform mediump float uSampleWeights[NUM_SAMPLES];\n"
108 " mediump vec4 col = texture2D(sTexture, vTexCoord + uSampleOffsets[0]) * uSampleWeights[0];\n"
109 " for (int i=1; i<NUM_SAMPLES; ++i)\n"
111 " col += texture2D(sTexture, vTexCoord + uSampleOffsets[i]) * uSampleWeights[i];\n"
113 " gl_FragColor = col;\n"
119 GaussianBlurView::GaussianBlurView()
120 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION ) )
121 , mNumSamples(GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES)
122 , mBlurBellCurveWidth( 0.001f )
123 , mPixelFormat(GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT)
124 , mDownsampleWidthScale(GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE)
125 , mDownsampleHeightScale(GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE)
126 , mDownsampledWidth( 0.0f )
127 , mDownsampledHeight( 0.0f )
128 , mBlurUserImage( false )
129 , mRenderOnce( false )
130 , mBackgroundColor( Color::BLACK )
131 , mTargetSize(Vector2::ZERO)
132 , mLastSize(Vector2::ZERO)
133 , mChildrenRoot(Actor::New())
134 , mInternalRoot(Actor::New())
135 , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
136 , mActivated( false )
138 SetBlurBellCurveWidth(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH);
141 GaussianBlurView::GaussianBlurView( const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
142 const float downsampleWidthScale, const float downsampleHeightScale,
144 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION ) )
145 , mNumSamples(numSamples)
146 , mBlurBellCurveWidth( 0.001f )
147 , mPixelFormat(renderTargetPixelFormat)
148 , mDownsampleWidthScale(downsampleWidthScale)
149 , mDownsampleHeightScale(downsampleHeightScale)
150 , mDownsampledWidth( 0.0f )
151 , mDownsampledHeight( 0.0f )
152 , mBlurUserImage( blurUserImage )
153 , mRenderOnce( false )
154 , mBackgroundColor( Color::BLACK )
155 , mTargetSize(Vector2::ZERO)
156 , mLastSize(Vector2::ZERO)
157 , mChildrenRoot(Actor::New())
158 , mInternalRoot(Actor::New())
159 , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
160 , mActivated( false )
162 SetBlurBellCurveWidth(blurBellCurveWidth);
165 GaussianBlurView::~GaussianBlurView()
170 Toolkit::GaussianBlurView GaussianBlurView::New()
172 GaussianBlurView* impl = new GaussianBlurView();
174 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
176 // Second-phase init of the implementation
177 // This can only be done after the CustomActor connection has been made...
183 Toolkit::GaussianBlurView GaussianBlurView::New(const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
184 const float downsampleWidthScale, const float downsampleHeightScale,
187 GaussianBlurView* impl = new GaussianBlurView( numSamples, blurBellCurveWidth, renderTargetPixelFormat,
188 downsampleWidthScale, downsampleHeightScale,
191 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
193 // Second-phase init of the implementation
194 // This can only be done after the CustomActor connection has been made...
200 /////////////////////////////////////////////////////////////
201 // for creating a subtree for all user added child actors, so that we can have them exclusive to the mRenderChildrenTask and our other actors exclusive to our other tasks
202 // DEPRECATED: overloading Actor::Add()/Remove() not nice since breaks polymorphism. Need another method to pass ownership of added child actors to our internal actor root.
203 void GaussianBlurView::Add(Actor child)
205 mChildrenRoot.Add(child);
208 void GaussianBlurView::Remove(Actor child)
210 mChildrenRoot.Remove(child);
213 void GaussianBlurView::SetUserImageAndOutputRenderTarget(Image inputImage, FrameBufferImage outputRenderTarget)
215 // can only do this if the GaussianBlurView object was created with this parameter set
216 DALI_ASSERT_ALWAYS(mBlurUserImage);
218 mUserInputImage = inputImage;
219 mImageViewHorizBlur.SetImage( mUserInputImage );
220 mImageViewHorizBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, mCustomShader );
222 mUserOutputRenderTarget = outputRenderTarget;
225 FrameBufferImage GaussianBlurView::GetBlurredRenderTarget() const
227 if(!mUserOutputRenderTarget)
229 return mRenderTargetForRenderingChildren;
232 return mUserOutputRenderTarget;
235 void GaussianBlurView::SetBackgroundColor( const Vector4& color )
237 mBackgroundColor = color;
240 Vector4 GaussianBlurView::GetBackgroundColor() const
242 return mBackgroundColor;
245 ///////////////////////////////////////////////////////////
250 void GaussianBlurView::OnInitialize()
252 // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
253 mChildrenRoot.SetParentOrigin(ParentOrigin::CENTER);
254 mInternalRoot.SetParentOrigin(ParentOrigin::CENTER);
256 //////////////////////////////////////////////////////
259 std::ostringstream horizFragmentShaderStringStream;
260 horizFragmentShaderStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
261 horizFragmentShaderStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
262 Property::Map source;
263 source[ "fragmentShader" ] = horizFragmentShaderStringStream.str();
264 mCustomShader["shader"] = source;
266 //////////////////////////////////////////////////////
269 // Create an image view for performing a horizontal blur on the texture
270 mImageViewHorizBlur = Toolkit::ImageView::New();
271 mImageViewHorizBlur.SetParentOrigin(ParentOrigin::CENTER);
273 // Create an image view for performing a vertical blur on the texture
274 mImageViewVertBlur = Toolkit::ImageView::New();
275 mImageViewVertBlur.SetParentOrigin(ParentOrigin::CENTER);
277 // Register a property that the user can control to fade the blur in / out via the GaussianBlurView object
279 mBlurStrengthPropertyIndex = self.RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
281 // Create an image view for compositing the blur and the original child actors render
284 mImageViewComposite = Toolkit::ImageView::New();
285 mImageViewComposite.SetParentOrigin(ParentOrigin::CENTER);
286 mImageViewComposite.SetOpacity(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
288 Constraint blurStrengthConstraint = Constraint::New<float>( mImageViewComposite, Actor::Property::COLOR_ALPHA, EqualToConstraint());
289 blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) );
290 blurStrengthConstraint.Apply();
292 // Create an image view for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
293 mTargetActor = Toolkit::ImageView::New();
294 mTargetActor.SetParentOrigin(ParentOrigin::CENTER);
296 //////////////////////////////////////////////////////
297 // Create cameras for the renders corresponding to the view size
298 mRenderFullSizeCamera = CameraActor::New();
299 mRenderFullSizeCamera.SetInvertYAxis( true );
300 mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
303 //////////////////////////////////////////////////////
304 // Connect to actor tree
305 mInternalRoot.Add( mImageViewComposite );
306 mInternalRoot.Add( mTargetActor );
307 mInternalRoot.Add( mRenderFullSizeCamera );
311 //////////////////////////////////////////////////////
312 // Create camera for the renders corresponding to the (potentially downsampled) render targets' size
313 mRenderDownsampledCamera = CameraActor::New();
314 mRenderDownsampledCamera.SetInvertYAxis( true );
315 mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
318 //////////////////////////////////////////////////////
319 // Connect to actor tree
320 Self().Add( mChildrenRoot );
321 Self().Add( mInternalRoot );
322 mInternalRoot.Add( mImageViewHorizBlur );
323 mInternalRoot.Add( mImageViewVertBlur );
324 mInternalRoot.Add( mRenderDownsampledCamera );
328 void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
330 Control::OnSizeSet( targetSize );
332 mTargetSize = Vector2(targetSize);
334 mChildrenRoot.SetSize(targetSize);
336 if( !mBlurUserImage )
338 mImageViewComposite.SetSize(targetSize);
339 mTargetActor.SetSize(targetSize);
341 // Children render camera must move when GaussianBlurView object is resized. This is since we cannot change render target size - so we need to remap the child actors' rendering
342 // accordingly so they still exactly fill the render target. Note that this means the effective resolution of the child render changes as the GaussianBlurView object changes
343 // size, this is the trade off for not being able to modify render target size
344 // Change camera z position based on GaussianBlurView actor height
345 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
346 mRenderFullSizeCamera.SetZ(mTargetSize.height * cameraPosConstraintScale);
350 // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
358 void GaussianBlurView::OnChildAdd( Actor& child )
360 Control::OnChildAdd( child );
362 if( child != mChildrenRoot && child != mInternalRoot)
364 mChildrenRoot.Add( child );
368 void GaussianBlurView::OnChildRemove( Actor& child )
370 mChildrenRoot.Remove( child );
372 Control::OnChildRemove( child );
375 void GaussianBlurView::AllocateResources()
377 // size of render targets etc is based on the size of this actor, ignoring z
378 if(mTargetSize != mLastSize)
380 mLastSize = mTargetSize;
382 // get size of downsampled render targets
383 mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
384 mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
386 // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
387 mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
388 // TODO: how do we pick a reasonable value for near clip? Needs to relate to normal camera the user renders with, but we don't have a handle on it
389 mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
390 mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
391 mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
393 mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
395 // setup for normal operation
398 // Create and place a camera for the children render, corresponding to its render target size
399 mRenderFullSizeCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
400 // TODO: how do we pick a reasonable value for near clip? Needs to relate to normal camera the user renders with, but we don't have a handle on it
401 mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
402 mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
403 mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
405 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
406 mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
408 // create offscreen buffer of new size to render our child actors to
409 mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
411 // Set image view for performing a horizontal blur on the texture
412 mImageViewHorizBlur.SetImage( mRenderTargetForRenderingChildren );
413 mImageViewHorizBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, mCustomShader );
415 // Create offscreen buffer for vert blur pass
416 mRenderTarget1 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat );
418 // use the completed blur in the first buffer and composite with the original child actors render
419 mImageViewComposite.SetImage( mRenderTarget1 );
421 // set up target actor for rendering result, i.e. the blurred image
422 mTargetActor.SetImage(mRenderTargetForRenderingChildren);
425 // Create offscreen buffer for horiz blur pass
426 mRenderTarget2 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat );
428 // size needs to match render target
429 mImageViewHorizBlur.SetSize(mDownsampledWidth, mDownsampledHeight);
431 // size needs to match render target
432 mImageViewVertBlur.SetImage( mRenderTarget2 );
433 mImageViewVertBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, mCustomShader );
434 mImageViewVertBlur.SetSize(mDownsampledWidth, mDownsampledHeight);
436 // set gaussian blur up for new sized render targets
437 SetShaderConstants();
441 void GaussianBlurView::CreateRenderTasks()
443 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
447 // create render task to render our child actors to offscreen buffer
448 mRenderChildrenTask = taskList.CreateTask();
449 mRenderChildrenTask.SetSourceActor( mChildrenRoot );
450 mRenderChildrenTask.SetExclusive(true);
451 mRenderChildrenTask.SetInputEnabled( false );
452 mRenderChildrenTask.SetClearEnabled( true );
453 mRenderChildrenTask.SetClearColor( mBackgroundColor );
455 mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera);
456 mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
459 // perform a horizontal blur targeting the second buffer
460 mHorizBlurTask = taskList.CreateTask();
461 mHorizBlurTask.SetSourceActor( mImageViewHorizBlur );
462 mHorizBlurTask.SetExclusive(true);
463 mHorizBlurTask.SetInputEnabled( false );
464 mHorizBlurTask.SetClearEnabled( true );
465 mHorizBlurTask.SetClearColor( mBackgroundColor );
466 mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
467 mHorizBlurTask.SetTargetFrameBuffer( mRenderTarget2 );
468 if( mRenderOnce && mBlurUserImage )
470 mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
473 // use the second buffer and perform a horizontal blur targeting the first buffer
474 mVertBlurTask = taskList.CreateTask();
475 mVertBlurTask.SetSourceActor( mImageViewVertBlur );
476 mVertBlurTask.SetExclusive(true);
477 mVertBlurTask.SetInputEnabled( false );
478 mVertBlurTask.SetClearEnabled( true );
479 mVertBlurTask.SetClearColor( mBackgroundColor );
480 mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
481 if(mUserOutputRenderTarget)
483 mVertBlurTask.SetTargetFrameBuffer( mUserOutputRenderTarget );
487 mVertBlurTask.SetTargetFrameBuffer( mRenderTarget1 );
489 if( mRenderOnce && mBlurUserImage )
491 mVertBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
492 mVertBlurTask.FinishedSignal().Connect( this, &GaussianBlurView::OnRenderTaskFinished );
495 // use the completed blur in the first buffer and composite with the original child actors render
498 mCompositeTask = taskList.CreateTask();
499 mCompositeTask.SetSourceActor( mImageViewComposite );
500 mCompositeTask.SetExclusive(true);
501 mCompositeTask.SetInputEnabled( false );
503 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
504 mCompositeTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
508 void GaussianBlurView::RemoveRenderTasks()
510 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
512 taskList.RemoveTask(mRenderChildrenTask);
513 taskList.RemoveTask(mHorizBlurTask);
514 taskList.RemoveTask(mVertBlurTask);
515 taskList.RemoveTask(mCompositeTask);
518 void GaussianBlurView::Activate()
520 // make sure resources are allocated and start the render tasks processing
526 void GaussianBlurView::ActivateOnce()
528 DALI_ASSERT_ALWAYS(mBlurUserImage); // Only works with blurring image mode.
533 void GaussianBlurView::Deactivate()
535 // stop render tasks processing
536 // Note: render target resources are automatically freed since we set the Image::Unused flag
538 mRenderTargetForRenderingChildren.Reset();
539 mRenderTarget1.Reset();
540 mRenderTarget2.Reset();
545 void GaussianBlurView::SetBlurBellCurveWidth(float blurBellCurveWidth)
547 // a value of zero leads to undefined Gaussian weights, do not allow user to do this
548 mBlurBellCurveWidth = std::max( blurBellCurveWidth, 0.001f );
551 float GaussianBlurView::CalcGaussianWeight(float x)
553 return (1.0f / sqrt(2.0f * Math::PI * mBlurBellCurveWidth)) * exp(-(x * x) / (2.0f * mBlurBellCurveWidth * mBlurBellCurveWidth));
556 void GaussianBlurView::SetShaderConstants()
561 float w, totalWeights;
564 uvOffsets = new Vector2[mNumSamples + 1];
565 weights = new float[mNumSamples + 1];
567 totalWeights = weights[0] = CalcGaussianWeight(0);
568 uvOffsets[0].x = 0.0f;
569 uvOffsets[0].y = 0.0f;
571 for(i=0; i<mNumSamples >> 1; i++)
573 w = CalcGaussianWeight((float)(i + 1));
574 weights[(i << 1) + 1] = w;
575 weights[(i << 1) + 2] = w;
576 totalWeights += w * 2.0f;
578 // offset texture lookup to between texels, that way the bilinear filter in the texture hardware will average two samples with one lookup
579 ofs = ((float)(i << 1)) + 1.5f;
581 // get offsets from units of pixels into uv coordinates in [0..1]
582 float ofsX = ofs / mDownsampledWidth;
583 float ofsY = ofs / mDownsampledHeight;
584 uvOffsets[(i << 1) + 1].x = ofsX;
585 uvOffsets[(i << 1) + 1].y = ofsY;
587 uvOffsets[(i << 1) + 2].x = -ofsX;
588 uvOffsets[(i << 1) + 2].y = -ofsY;
591 for(i=0; i<mNumSamples; i++)
593 weights[i] /= totalWeights;
596 // set shader constants
597 Vector2 xAxis(1.0f, 0.0f);
598 Vector2 yAxis(0.0f, 1.0f);
599 for (i = 0; i < mNumSamples; ++i )
601 mImageViewHorizBlur.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
602 mImageViewHorizBlur.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
604 mImageViewVertBlur.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
605 mImageViewVertBlur.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
612 std::string GaussianBlurView::GetSampleOffsetsPropertyName( unsigned int index ) const
614 DALI_ASSERT_ALWAYS( index < mNumSamples );
616 std::ostringstream oss;
617 oss << "uSampleOffsets[" << index << "]";
621 std::string GaussianBlurView::GetSampleWeightsPropertyName( unsigned int index ) const
623 DALI_ASSERT_ALWAYS( index < mNumSamples );
625 std::ostringstream oss;
626 oss << "uSampleWeights[" << index << "]";
630 Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal& GaussianBlurView::FinishedSignal()
632 return mFinishedSignal;
635 void GaussianBlurView::OnRenderTaskFinished(Dali::RenderTask& renderTask)
637 Toolkit::GaussianBlurView handle( GetOwner() );
638 mFinishedSignal.Emit( handle );
641 } // namespace Internal
642 } // namespace Toolkit