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 "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/visuals/visual-properties.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 | DISABLE_STYLE_CHANGE_SIGNALS ) ),
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),
138 SetBlurBellCurveWidth(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH);
141 GaussianBlurView::GaussianBlurView( const unsigned int numSamples,
142 const float blurBellCurveWidth,
143 const Pixel::Format renderTargetPixelFormat,
144 const float downsampleWidthScale,
145 const float downsampleHeightScale,
147 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS ) ),
148 mNumSamples(numSamples),
149 mBlurBellCurveWidth( 0.001f ),
150 mPixelFormat(renderTargetPixelFormat),
151 mDownsampleWidthScale(downsampleWidthScale),
152 mDownsampleHeightScale(downsampleHeightScale),
153 mDownsampledWidth( 0.0f ),
154 mDownsampledHeight( 0.0f ),
155 mBlurUserImage( blurUserImage ),
156 mRenderOnce( false ),
157 mBackgroundColor( Color::BLACK ),
158 mTargetSize(Vector2::ZERO),
159 mLastSize(Vector2::ZERO),
160 mChildrenRoot(Actor::New()),
161 mInternalRoot(Actor::New()),
162 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
165 SetBlurBellCurveWidth(blurBellCurveWidth);
168 GaussianBlurView::~GaussianBlurView()
173 Toolkit::GaussianBlurView GaussianBlurView::New()
175 GaussianBlurView* impl = new GaussianBlurView();
177 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
179 // Second-phase init of the implementation
180 // This can only be done after the CustomActor connection has been made...
186 Toolkit::GaussianBlurView GaussianBlurView::New(const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
187 const float downsampleWidthScale, const float downsampleHeightScale,
190 GaussianBlurView* impl = new GaussianBlurView( numSamples, blurBellCurveWidth, renderTargetPixelFormat,
191 downsampleWidthScale, downsampleHeightScale,
194 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
196 // Second-phase init of the implementation
197 // This can only be done after the CustomActor connection has been made...
203 /////////////////////////////////////////////////////////////
204 // 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
205 // 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.
206 void GaussianBlurView::Add(Actor child)
208 mChildrenRoot.Add(child);
211 void GaussianBlurView::Remove(Actor child)
213 mChildrenRoot.Remove(child);
216 void GaussianBlurView::SetUserImageAndOutputRenderTarget(Image inputImage, FrameBufferImage outputRenderTarget)
218 // can only do this if the GaussianBlurView object was created with this parameter set
219 DALI_ASSERT_ALWAYS(mBlurUserImage);
221 mUserInputImage = inputImage;
222 mImageViewHorizBlur.SetImage( mUserInputImage );
223 mImageViewHorizBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, mCustomShader );
225 mUserOutputRenderTarget = outputRenderTarget;
228 FrameBufferImage GaussianBlurView::GetBlurredRenderTarget() const
230 if(!mUserOutputRenderTarget)
232 return mRenderTargetForRenderingChildren;
235 return mUserOutputRenderTarget;
238 void GaussianBlurView::SetBackgroundColor( const Vector4& color )
240 mBackgroundColor = color;
243 Vector4 GaussianBlurView::GetBackgroundColor() const
245 return mBackgroundColor;
248 ///////////////////////////////////////////////////////////
253 void GaussianBlurView::OnInitialize()
255 // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
256 mChildrenRoot.SetParentOrigin(ParentOrigin::CENTER);
257 mInternalRoot.SetParentOrigin(ParentOrigin::CENTER);
259 //////////////////////////////////////////////////////
262 std::ostringstream horizFragmentShaderStringStream;
263 horizFragmentShaderStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
264 horizFragmentShaderStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
265 Property::Map source;
266 source[ Toolkit::Visual::Shader::Property::FRAGMENT_SHADER ] = horizFragmentShaderStringStream.str();
267 mCustomShader[ Toolkit::Visual::Property::SHADER ] = source;
269 //////////////////////////////////////////////////////
272 // Create an image view for performing a horizontal blur on the texture
273 mImageViewHorizBlur = Toolkit::ImageView::New();
274 mImageViewHorizBlur.SetParentOrigin(ParentOrigin::CENTER);
276 // Create an image view for performing a vertical blur on the texture
277 mImageViewVertBlur = Toolkit::ImageView::New();
278 mImageViewVertBlur.SetParentOrigin(ParentOrigin::CENTER);
280 // Register a property that the user can control to fade the blur in / out via the GaussianBlurView object
282 mBlurStrengthPropertyIndex = self.RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
284 // Create an image view for compositing the blur and the original child actors render
287 mImageViewComposite = Toolkit::ImageView::New();
288 mImageViewComposite.SetParentOrigin(ParentOrigin::CENTER);
289 mImageViewComposite.SetOpacity(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
291 Constraint blurStrengthConstraint = Constraint::New<float>( mImageViewComposite, Actor::Property::COLOR_ALPHA, EqualToConstraint());
292 blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) );
293 blurStrengthConstraint.Apply();
295 // 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
296 mTargetActor = Toolkit::ImageView::New();
297 mTargetActor.SetParentOrigin(ParentOrigin::CENTER);
299 //////////////////////////////////////////////////////
300 // Create cameras for the renders corresponding to the view size
301 mRenderFullSizeCamera = CameraActor::New();
302 mRenderFullSizeCamera.SetInvertYAxis( true );
303 mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
306 //////////////////////////////////////////////////////
307 // Connect to actor tree
308 mInternalRoot.Add( mImageViewComposite );
309 mInternalRoot.Add( mTargetActor );
310 mInternalRoot.Add( mRenderFullSizeCamera );
314 //////////////////////////////////////////////////////
315 // Create camera for the renders corresponding to the (potentially downsampled) render targets' size
316 mRenderDownsampledCamera = CameraActor::New();
317 mRenderDownsampledCamera.SetInvertYAxis( true );
318 mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
321 //////////////////////////////////////////////////////
322 // Connect to actor tree
323 Self().Add( mChildrenRoot );
324 Self().Add( mInternalRoot );
325 mInternalRoot.Add( mImageViewHorizBlur );
326 mInternalRoot.Add( mImageViewVertBlur );
327 mInternalRoot.Add( mRenderDownsampledCamera );
331 void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
333 Control::OnSizeSet( targetSize );
335 mTargetSize = Vector2(targetSize);
337 mChildrenRoot.SetSize(targetSize);
339 if( !mBlurUserImage )
341 mImageViewComposite.SetSize(targetSize);
342 mTargetActor.SetSize(targetSize);
344 // 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
345 // 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
346 // size, this is the trade off for not being able to modify render target size
347 // Change camera z position based on GaussianBlurView actor height
348 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
349 mRenderFullSizeCamera.SetZ(mTargetSize.height * cameraPosConstraintScale);
353 // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
361 void GaussianBlurView::OnChildAdd( Actor& child )
363 Control::OnChildAdd( child );
365 if( child != mChildrenRoot && child != mInternalRoot)
367 mChildrenRoot.Add( child );
371 void GaussianBlurView::OnChildRemove( Actor& child )
373 mChildrenRoot.Remove( child );
375 Control::OnChildRemove( child );
378 void GaussianBlurView::AllocateResources()
380 // size of render targets etc is based on the size of this actor, ignoring z
381 if(mTargetSize != mLastSize)
383 mLastSize = mTargetSize;
385 // get size of downsampled render targets
386 mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
387 mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
389 // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
390 mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
391 // 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
392 mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
393 mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
394 mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
396 mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
398 // setup for normal operation
401 // Create and place a camera for the children render, corresponding to its render target size
402 mRenderFullSizeCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
403 // 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
404 mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
405 mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
406 mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
408 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
409 mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
411 // create offscreen buffer of new size to render our child actors to
412 mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
414 // Set image view for performing a horizontal blur on the texture
415 mImageViewHorizBlur.SetImage( mRenderTargetForRenderingChildren );
416 mImageViewHorizBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, mCustomShader );
418 // Create offscreen buffer for vert blur pass
419 mRenderTarget1 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat );
421 // use the completed blur in the first buffer and composite with the original child actors render
422 mImageViewComposite.SetImage( mRenderTarget1 );
424 // set up target actor for rendering result, i.e. the blurred image
425 mTargetActor.SetImage(mRenderTargetForRenderingChildren);
428 // Create offscreen buffer for horiz blur pass
429 mRenderTarget2 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat );
431 // size needs to match render target
432 mImageViewHorizBlur.SetSize(mDownsampledWidth, mDownsampledHeight);
434 // size needs to match render target
435 mImageViewVertBlur.SetImage( mRenderTarget2 );
436 mImageViewVertBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, mCustomShader );
437 mImageViewVertBlur.SetSize(mDownsampledWidth, mDownsampledHeight);
439 // set gaussian blur up for new sized render targets
440 SetShaderConstants();
444 void GaussianBlurView::CreateRenderTasks()
446 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
450 // create render task to render our child actors to offscreen buffer
451 mRenderChildrenTask = taskList.CreateTask();
452 mRenderChildrenTask.SetSourceActor( mChildrenRoot );
453 mRenderChildrenTask.SetExclusive(true);
454 mRenderChildrenTask.SetInputEnabled( false );
455 mRenderChildrenTask.SetClearEnabled( true );
456 mRenderChildrenTask.SetClearColor( mBackgroundColor );
458 mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera);
459 mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
462 // perform a horizontal blur targeting the second buffer
463 mHorizBlurTask = taskList.CreateTask();
464 mHorizBlurTask.SetSourceActor( mImageViewHorizBlur );
465 mHorizBlurTask.SetExclusive(true);
466 mHorizBlurTask.SetInputEnabled( false );
467 mHorizBlurTask.SetClearEnabled( true );
468 mHorizBlurTask.SetClearColor( mBackgroundColor );
469 mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
470 mHorizBlurTask.SetTargetFrameBuffer( mRenderTarget2 );
471 if( mRenderOnce && mBlurUserImage )
473 mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
476 // use the second buffer and perform a horizontal blur targeting the first buffer
477 mVertBlurTask = taskList.CreateTask();
478 mVertBlurTask.SetSourceActor( mImageViewVertBlur );
479 mVertBlurTask.SetExclusive(true);
480 mVertBlurTask.SetInputEnabled( false );
481 mVertBlurTask.SetClearEnabled( true );
482 mVertBlurTask.SetClearColor( mBackgroundColor );
483 mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
484 if(mUserOutputRenderTarget)
486 mVertBlurTask.SetTargetFrameBuffer( mUserOutputRenderTarget );
490 mVertBlurTask.SetTargetFrameBuffer( mRenderTarget1 );
492 if( mRenderOnce && mBlurUserImage )
494 mVertBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
495 mVertBlurTask.FinishedSignal().Connect( this, &GaussianBlurView::OnRenderTaskFinished );
498 // use the completed blur in the first buffer and composite with the original child actors render
501 mCompositeTask = taskList.CreateTask();
502 mCompositeTask.SetSourceActor( mImageViewComposite );
503 mCompositeTask.SetExclusive(true);
504 mCompositeTask.SetInputEnabled( false );
506 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
507 mCompositeTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
511 void GaussianBlurView::RemoveRenderTasks()
513 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
515 taskList.RemoveTask(mRenderChildrenTask);
516 taskList.RemoveTask(mHorizBlurTask);
517 taskList.RemoveTask(mVertBlurTask);
518 taskList.RemoveTask(mCompositeTask);
521 void GaussianBlurView::Activate()
523 // make sure resources are allocated and start the render tasks processing
529 void GaussianBlurView::ActivateOnce()
531 DALI_ASSERT_ALWAYS(mBlurUserImage); // Only works with blurring image mode.
536 void GaussianBlurView::Deactivate()
538 // stop render tasks processing
539 // Note: render target resources are automatically freed since we set the Image::Unused flag
541 mRenderTargetForRenderingChildren.Reset();
542 mRenderTarget1.Reset();
543 mRenderTarget2.Reset();
548 void GaussianBlurView::SetBlurBellCurveWidth(float blurBellCurveWidth)
550 // a value of zero leads to undefined Gaussian weights, do not allow user to do this
551 mBlurBellCurveWidth = std::max( blurBellCurveWidth, 0.001f );
554 float GaussianBlurView::CalcGaussianWeight(float x)
556 return (1.0f / sqrt(2.0f * Math::PI * mBlurBellCurveWidth)) * exp(-(x * x) / (2.0f * mBlurBellCurveWidth * mBlurBellCurveWidth));
559 void GaussianBlurView::SetShaderConstants()
564 float w, totalWeights;
567 uvOffsets = new Vector2[mNumSamples + 1];
568 weights = new float[mNumSamples + 1];
570 totalWeights = weights[0] = CalcGaussianWeight(0);
571 uvOffsets[0].x = 0.0f;
572 uvOffsets[0].y = 0.0f;
574 for(i=0; i<mNumSamples >> 1; i++)
576 w = CalcGaussianWeight((float)(i + 1));
577 weights[(i << 1) + 1] = w;
578 weights[(i << 1) + 2] = w;
579 totalWeights += w * 2.0f;
581 // offset texture lookup to between texels, that way the bilinear filter in the texture hardware will average two samples with one lookup
582 ofs = ((float)(i << 1)) + 1.5f;
584 // get offsets from units of pixels into uv coordinates in [0..1]
585 float ofsX = ofs / mDownsampledWidth;
586 float ofsY = ofs / mDownsampledHeight;
587 uvOffsets[(i << 1) + 1].x = ofsX;
588 uvOffsets[(i << 1) + 1].y = ofsY;
590 uvOffsets[(i << 1) + 2].x = -ofsX;
591 uvOffsets[(i << 1) + 2].y = -ofsY;
594 for(i=0; i<mNumSamples; i++)
596 weights[i] /= totalWeights;
599 // set shader constants
600 Vector2 xAxis(1.0f, 0.0f);
601 Vector2 yAxis(0.0f, 1.0f);
602 for (i = 0; i < mNumSamples; ++i )
604 mImageViewHorizBlur.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
605 mImageViewHorizBlur.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
607 mImageViewVertBlur.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
608 mImageViewVertBlur.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
615 std::string GaussianBlurView::GetSampleOffsetsPropertyName( unsigned int index ) const
617 DALI_ASSERT_ALWAYS( index < mNumSamples );
619 std::ostringstream oss;
620 oss << "uSampleOffsets[" << index << "]";
624 std::string GaussianBlurView::GetSampleWeightsPropertyName( unsigned int index ) const
626 DALI_ASSERT_ALWAYS( index < mNumSamples );
628 std::ostringstream oss;
629 oss << "uSampleWeights[" << index << "]";
633 Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal& GaussianBlurView::FinishedSignal()
635 return mFinishedSignal;
638 void GaussianBlurView::OnRenderTaskFinished(Dali::RenderTask& renderTask)
640 Toolkit::GaussianBlurView handle( GetOwner() );
641 mFinishedSignal.Emit( handle );
644 } // namespace Internal
645 } // namespace Toolkit