2 * Copyright (c) 2020 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/devel-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/rendering/geometry.h>
30 #include <dali/public-api/rendering/renderer.h>
31 #include <dali/public-api/rendering/shader.h>
32 #include <dali/public-api/render-tasks/render-task-list.h>
33 #include <dali/integration-api/debug.h>
34 #include <dali/devel-api/actors/actor-devel.h>
37 #include <dali-toolkit/public-api/visuals/visual-properties.h>
38 #include <dali-toolkit/internal/controls/control/control-renderers.h>
39 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
42 // pixel format / size - set from JSON
43 // 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
44 // default near clip value
45 // Manager object - re-use render targets if there are multiple GaussianBlurViews created
48 /////////////////////////////////////////////////////////
49 // IMPLEMENTATION NOTES
51 // As the GaussianBlurView actor changes size, the amount of pixels we need to blur changes. Therefore we need some way of doing this. However:-
52 // OnSetSize() does not get called when GaussianBlurView object size is modified using a Constraint.
53 // 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
54 // OnSizeAnimation() to alter render target sizes.
55 // 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
56 // 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
57 // by using constraints relative to the GaussianBlurView actor size.
61 // 1st mode, this control has a tree of actors (use Add() to add children) that are rendered and blurred.
62 // mRenderChildrenTask renders children to FB mRenderTargetForRenderingChildren
63 // mHorizBlurTask renders mHorizBlurActor Actor showing FB mRenderTargetForRenderingChildren into FB mRenderTarget2
64 // mVertBlurTask renders mVertBlurActor Actor showing FB mRenderTarget2 into FB mRenderTarget1
65 // mCompositeTask renders mCompositingActor Actor showing FB mRenderTarget1 into FB mRenderTargetForRenderingChildren
67 // 2nd mode, an image is blurred and rendered to a supplied target framebuffer
68 // mHorizBlurTask renders mHorizBlurActor Actor showing mUserInputImage into FB mRenderTarget2
69 // mVertBlurTask renders mVertBlurActor Actor showing mRenderTarget2 into FB mUserOutputRenderTarget
71 // Only this 2nd mode handles ActivateOnce
89 return Toolkit::GaussianBlurView::New();
92 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::GaussianBlurView, Toolkit::Control, Create )
93 DALI_TYPE_REGISTRATION_END()
95 const unsigned int GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES = 5;
96 const float GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH = 1.5f;
97 const Pixel::Format GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
98 const float GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH = 1.0f; // default, fully blurred
99 const char* const GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME = "GaussianBlurStrengthPropertyName";
100 const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
101 const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
103 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
105 const char* const GAUSSIAN_BLUR_FRAGMENT_SOURCE = DALI_COMPOSE_SHADER(
106 varying mediump vec2 vTexCoord;\n
107 uniform sampler2D sTexture;\n
108 uniform lowp vec4 uColor;\n
109 uniform mediump vec2 uSampleOffsets[NUM_SAMPLES];\n
110 uniform mediump float uSampleWeights[NUM_SAMPLES];\n
114 mediump vec4 col = texture2D(sTexture, vTexCoord + uSampleOffsets[0]) * uSampleWeights[0];\n
115 for (int i=1; i<NUM_SAMPLES; ++i)\n
117 col += texture2D(sTexture, vTexCoord + uSampleOffsets[i]) * uSampleWeights[i];\n
119 gl_FragColor = col;\n
126 GaussianBlurView::GaussianBlurView()
127 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS ) ),
128 mNumSamples(GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES),
129 mBlurBellCurveWidth( 0.001f ),
130 mPixelFormat(GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT),
131 mDownsampleWidthScale(GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE),
132 mDownsampleHeightScale(GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE),
133 mDownsampledWidth( 0.0f ),
134 mDownsampledHeight( 0.0f ),
135 mBlurUserImage( false ),
136 mRenderOnce( false ),
137 mBackgroundColor( Color::BLACK ),
138 mTargetSize(Vector2::ZERO),
139 mLastSize(Vector2::ZERO),
140 mChildrenRoot(Actor::New()),
141 mInternalRoot(Actor::New()),
142 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
145 SetBlurBellCurveWidth(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH);
146 DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
147 return std::unique_ptr< Dali::Accessibility::Accessible >(
148 new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::FILLER ) );
152 GaussianBlurView::GaussianBlurView( const unsigned int numSamples,
153 const float blurBellCurveWidth,
154 const Pixel::Format renderTargetPixelFormat,
155 const float downsampleWidthScale,
156 const float downsampleHeightScale,
158 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS ) ),
159 mNumSamples(numSamples),
160 mBlurBellCurveWidth( 0.001f ),
161 mPixelFormat(renderTargetPixelFormat),
162 mDownsampleWidthScale(downsampleWidthScale),
163 mDownsampleHeightScale(downsampleHeightScale),
164 mDownsampledWidth( 0.0f ),
165 mDownsampledHeight( 0.0f ),
166 mBlurUserImage( blurUserImage ),
167 mRenderOnce( false ),
168 mBackgroundColor( Color::BLACK ),
169 mTargetSize(Vector2::ZERO),
170 mLastSize(Vector2::ZERO),
171 mChildrenRoot(Actor::New()),
172 mInternalRoot(Actor::New()),
173 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
176 SetBlurBellCurveWidth(blurBellCurveWidth);
179 GaussianBlurView::~GaussianBlurView()
184 Toolkit::GaussianBlurView GaussianBlurView::New()
186 GaussianBlurView* impl = new GaussianBlurView();
188 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
190 // Second-phase init of the implementation
191 // This can only be done after the CustomActor connection has been made...
197 Toolkit::GaussianBlurView GaussianBlurView::New(const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
198 const float downsampleWidthScale, const float downsampleHeightScale,
201 GaussianBlurView* impl = new GaussianBlurView( numSamples, blurBellCurveWidth, renderTargetPixelFormat,
202 downsampleWidthScale, downsampleHeightScale,
205 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
207 // Second-phase init of the implementation
208 // This can only be done after the CustomActor connection has been made...
214 void GaussianBlurView::SetUserImageAndOutputRenderTarget(Texture inputImage, FrameBuffer outputRenderTarget)
216 // can only do this if the GaussianBlurView object was created with this parameter set
217 DALI_ASSERT_ALWAYS(mBlurUserImage);
219 mUserInputImage = inputImage;
221 SetRendererTexture( mHorizBlurActor.GetRendererAt(0), inputImage );
223 mUserOutputRenderTarget = outputRenderTarget;
226 FrameBuffer GaussianBlurView::GetBlurredRenderTarget() const
228 if(!mUserOutputRenderTarget)
230 return mRenderTargetForRenderingChildren;
233 return mUserOutputRenderTarget;
236 void GaussianBlurView::SetBackgroundColor( const Vector4& color )
238 mBackgroundColor = color;
241 Vector4 GaussianBlurView::GetBackgroundColor() const
243 return mBackgroundColor;
246 ///////////////////////////////////////////////////////////
251 void GaussianBlurView::OnInitialize()
253 // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
254 mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
255 mInternalRoot.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
257 //////////////////////////////////////////////////////
260 std::ostringstream fragmentStringStream;
261 fragmentStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
262 fragmentStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
263 std::string fragmentSource(fragmentStringStream.str());
265 //////////////////////////////////////////////////////
268 // Create an actor for performing a horizontal blur on the texture
269 mHorizBlurActor = Actor::New();
270 mHorizBlurActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
271 Renderer renderer = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
272 mHorizBlurActor.AddRenderer( renderer );
274 // Create an actor for performing a vertical blur on the texture
275 mVertBlurActor = Actor::New();
276 mVertBlurActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
277 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
278 mVertBlurActor.AddRenderer( renderer );
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 mCompositingActor = Actor::New();
288 mCompositingActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
289 mCompositingActor.SetProperty( Actor::Property::OPACITY,GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
290 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
291 mCompositingActor.AddRenderer( renderer );
293 Constraint blurStrengthConstraint = Constraint::New<float>( mCompositingActor, Actor::Property::COLOR_ALPHA, EqualToConstraint());
294 blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) );
295 blurStrengthConstraint.Apply();
297 // 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
298 mTargetActor = Actor::New();
299 mTargetActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
300 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
301 mTargetActor.AddRenderer( renderer );
303 //////////////////////////////////////////////////////
304 // Create cameras for the renders corresponding to the view size
305 mRenderFullSizeCamera = CameraActor::New();
306 mRenderFullSizeCamera.SetInvertYAxis( true );
307 mRenderFullSizeCamera.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
309 //////////////////////////////////////////////////////
310 // Connect to actor tree
311 mInternalRoot.Add( mCompositingActor );
312 mInternalRoot.Add( mTargetActor );
313 mInternalRoot.Add( mRenderFullSizeCamera );
316 //////////////////////////////////////////////////////
317 // Create camera for the renders corresponding to the (potentially downsampled) render targets' size
318 mRenderDownsampledCamera = CameraActor::New();
319 mRenderDownsampledCamera.SetInvertYAxis( true );
320 mRenderDownsampledCamera.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
322 //////////////////////////////////////////////////////
323 // Connect to actor tree
324 Self().Add( mChildrenRoot );
325 mInternalRoot.Add( mHorizBlurActor );
326 mInternalRoot.Add( mVertBlurActor );
327 mInternalRoot.Add( mRenderDownsampledCamera );
331 void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
333 mTargetSize = Vector2(targetSize);
335 mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize);
337 if( !mBlurUserImage )
339 mCompositingActor.SetProperty( Actor::Property::SIZE, targetSize);
340 mTargetActor.SetProperty( Actor::Property::SIZE, targetSize);
342 // 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
343 // 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
344 // size, this is the trade off for not being able to modify render target size
345 // Change camera z position based on GaussianBlurView actor height
346 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
347 mRenderFullSizeCamera.SetProperty( Actor::Property::POSITION_Z, mTargetSize.height * cameraPosConstraintScale);
351 // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
358 Control::OnSizeSet( targetSize );
361 void GaussianBlurView::OnChildAdd( Actor& child )
363 if( child != mChildrenRoot && child != mInternalRoot)
365 mChildrenRoot.Add( child );
368 Control::OnChildAdd( child );
371 void GaussianBlurView::OnChildRemove( Actor& child )
373 mChildrenRoot.Remove( child );
375 Control::OnChildRemove( child );
378 void GaussianBlurView::AllocateResources()
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.SetProperty( Actor::Property::POSITION, Vector3(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.SetProperty( Actor::Property::POSITION, Vector3(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale));
408 // create offscreen buffer of new size to render our child actors to
409 mRenderTargetForRenderingChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
410 Texture texture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
411 mRenderTargetForRenderingChildren.AttachColorTexture( texture );
413 // Set actor for performing a horizontal blur
414 SetRendererTexture( mHorizBlurActor.GetRendererAt(0), mRenderTargetForRenderingChildren );
416 // Create offscreen buffer for vert blur pass
417 mRenderTarget1 = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
418 texture = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight));
419 mRenderTarget1.AttachColorTexture( texture );
421 // use the completed blur in the first buffer and composite with the original child actors render
422 SetRendererTexture( mCompositingActor.GetRendererAt(0), mRenderTarget1 );
424 // set up target actor for rendering result, i.e. the blurred image
425 SetRendererTexture( mTargetActor.GetRendererAt(0), mRenderTargetForRenderingChildren );
428 // Create offscreen buffer for horiz blur pass
429 mRenderTarget2 = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
430 Texture texture = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight));
431 mRenderTarget2.AttachColorTexture( texture );
433 // size needs to match render target
434 mHorizBlurActor.SetProperty( Actor::Property::SIZE, Vector2(mDownsampledWidth, mDownsampledHeight) );
436 // size needs to match render target
437 mVertBlurActor.SetProperty( Actor::Property::SIZE, Vector2(mDownsampledWidth, mDownsampledHeight) );
438 SetRendererTexture( mVertBlurActor.GetRendererAt(0), mRenderTarget2 );
440 // set gaussian blur up for new sized render targets
441 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.SetFrameBuffer( mRenderTargetForRenderingChildren );
463 mRenderChildrenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
467 // perform a horizontal blur targeting the second buffer
468 mHorizBlurTask = taskList.CreateTask();
469 mHorizBlurTask.SetSourceActor( mHorizBlurActor );
470 mHorizBlurTask.SetExclusive(true);
471 mHorizBlurTask.SetInputEnabled( false );
472 mHorizBlurTask.SetClearEnabled( true );
473 mHorizBlurTask.SetClearColor( mBackgroundColor );
474 mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
475 mHorizBlurTask.SetFrameBuffer( mRenderTarget2 );
476 if( mRenderOnce || ( mRenderOnce && mBlurUserImage ) )
478 mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
481 // use the second buffer and perform a horizontal blur targeting the first buffer
482 mVertBlurTask = taskList.CreateTask();
483 mVertBlurTask.SetSourceActor( mVertBlurActor );
484 mVertBlurTask.SetExclusive(true);
485 mVertBlurTask.SetInputEnabled( false );
486 mVertBlurTask.SetClearEnabled( true );
487 mVertBlurTask.SetClearColor( mBackgroundColor );
488 mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
489 if(mUserOutputRenderTarget)
491 mVertBlurTask.SetFrameBuffer( mUserOutputRenderTarget );
495 mVertBlurTask.SetFrameBuffer( mRenderTarget1 );
497 if( mRenderOnce || ( mRenderOnce && mBlurUserImage ) )
499 mVertBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
500 mVertBlurTask.FinishedSignal().Connect( this, &GaussianBlurView::OnRenderTaskFinished );
503 // use the completed blur in the first buffer and composite with the original child actors render
506 mCompositeTask = taskList.CreateTask();
507 mCompositeTask.SetSourceActor( mCompositingActor );
508 mCompositeTask.SetExclusive(true);
509 mCompositeTask.SetInputEnabled( false );
511 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
512 mCompositeTask.SetFrameBuffer( mRenderTargetForRenderingChildren );
516 mCompositeTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
521 void GaussianBlurView::RemoveRenderTasks()
523 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
525 taskList.RemoveTask(mRenderChildrenTask);
526 taskList.RemoveTask(mHorizBlurTask);
527 taskList.RemoveTask(mVertBlurTask);
528 taskList.RemoveTask(mCompositeTask);
531 void GaussianBlurView::Activate()
535 // make sure resources are allocated and start the render tasks processing
536 Self().Add( mInternalRoot );
543 void GaussianBlurView::ActivateOnce()
550 void GaussianBlurView::Deactivate()
554 // stop render tasks processing
555 // Note: render target resources are automatically freed since we set the Image::Unused flag
556 mInternalRoot.Unparent();
557 mRenderTargetForRenderingChildren.Reset();
558 mRenderTarget1.Reset();
559 mRenderTarget2.Reset();
566 void GaussianBlurView::SetBlurBellCurveWidth(float blurBellCurveWidth)
568 // a value of zero leads to undefined Gaussian weights, do not allow user to do this
569 mBlurBellCurveWidth = std::max( blurBellCurveWidth, 0.001f );
572 float GaussianBlurView::CalcGaussianWeight(float x)
574 return (1.0f / sqrt(2.0f * Math::PI * mBlurBellCurveWidth)) * exp(-(x * x) / (2.0f * mBlurBellCurveWidth * mBlurBellCurveWidth));
577 void GaussianBlurView::SetShaderConstants()
582 float w, totalWeights;
585 uvOffsets = new Vector2[mNumSamples + 1];
586 weights = new float[mNumSamples + 1];
588 totalWeights = weights[0] = CalcGaussianWeight(0);
589 uvOffsets[0].x = 0.0f;
590 uvOffsets[0].y = 0.0f;
592 for(i=0; i<mNumSamples >> 1; i++)
594 w = CalcGaussianWeight((float)(i + 1));
595 weights[(i << 1) + 1] = w;
596 weights[(i << 1) + 2] = w;
597 totalWeights += w * 2.0f;
599 // offset texture lookup to between texels, that way the bilinear filter in the texture hardware will average two samples with one lookup
600 ofs = ((float)(i << 1)) + 1.5f;
602 // get offsets from units of pixels into uv coordinates in [0..1]
603 float ofsX = ofs / mDownsampledWidth;
604 float ofsY = ofs / mDownsampledHeight;
605 uvOffsets[(i << 1) + 1].x = ofsX;
606 uvOffsets[(i << 1) + 1].y = ofsY;
608 uvOffsets[(i << 1) + 2].x = -ofsX;
609 uvOffsets[(i << 1) + 2].y = -ofsY;
612 for(i=0; i<mNumSamples; i++)
614 weights[i] /= totalWeights;
617 // set shader constants
618 Vector2 xAxis(1.0f, 0.0f);
619 Vector2 yAxis(0.0f, 1.0f);
620 for (i = 0; i < mNumSamples; ++i )
622 mHorizBlurActor.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
623 mHorizBlurActor.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
625 mVertBlurActor.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
626 mVertBlurActor.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
633 std::string GaussianBlurView::GetSampleOffsetsPropertyName( unsigned int index ) const
635 DALI_ASSERT_ALWAYS( index < mNumSamples );
637 std::ostringstream oss;
638 oss << "uSampleOffsets[" << index << "]";
642 std::string GaussianBlurView::GetSampleWeightsPropertyName( unsigned int index ) const
644 DALI_ASSERT_ALWAYS( index < mNumSamples );
646 std::ostringstream oss;
647 oss << "uSampleWeights[" << index << "]";
651 Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal& GaussianBlurView::FinishedSignal()
653 return mFinishedSignal;
656 void GaussianBlurView::OnRenderTaskFinished(Dali::RenderTask& renderTask)
658 Toolkit::GaussianBlurView handle( GetOwner() );
659 mFinishedSignal.Emit( handle );
662 } // namespace Internal
663 } // namespace Toolkit