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/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/rendering/geometry.h>
30 #include <dali/public-api/rendering/property-buffer.h>
31 #include <dali/public-api/rendering/renderer.h>
32 #include <dali/public-api/rendering/shader.h>
33 #include <dali/public-api/render-tasks/render-task-list.h>
34 #include <dali/integration-api/debug.h>
35 #include <dali/devel-api/actors/actor-devel.h>
38 #include <dali-toolkit/public-api/visuals/visual-properties.h>
39 #include <dali-toolkit/internal/controls/control/control-renderers.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);
148 GaussianBlurView::GaussianBlurView( const unsigned int numSamples,
149 const float blurBellCurveWidth,
150 const Pixel::Format renderTargetPixelFormat,
151 const float downsampleWidthScale,
152 const float downsampleHeightScale,
154 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS ) ),
155 mNumSamples(numSamples),
156 mBlurBellCurveWidth( 0.001f ),
157 mPixelFormat(renderTargetPixelFormat),
158 mDownsampleWidthScale(downsampleWidthScale),
159 mDownsampleHeightScale(downsampleHeightScale),
160 mDownsampledWidth( 0.0f ),
161 mDownsampledHeight( 0.0f ),
162 mBlurUserImage( blurUserImage ),
163 mRenderOnce( false ),
164 mBackgroundColor( Color::BLACK ),
165 mTargetSize(Vector2::ZERO),
166 mLastSize(Vector2::ZERO),
167 mChildrenRoot(Actor::New()),
168 mInternalRoot(Actor::New()),
169 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
172 SetBlurBellCurveWidth(blurBellCurveWidth);
175 GaussianBlurView::~GaussianBlurView()
180 Toolkit::GaussianBlurView GaussianBlurView::New()
182 GaussianBlurView* impl = new GaussianBlurView();
184 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
186 // Second-phase init of the implementation
187 // This can only be done after the CustomActor connection has been made...
193 Toolkit::GaussianBlurView GaussianBlurView::New(const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
194 const float downsampleWidthScale, const float downsampleHeightScale,
197 GaussianBlurView* impl = new GaussianBlurView( numSamples, blurBellCurveWidth, renderTargetPixelFormat,
198 downsampleWidthScale, downsampleHeightScale,
201 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
203 // Second-phase init of the implementation
204 // This can only be done after the CustomActor connection has been made...
210 /////////////////////////////////////////////////////////////
211 // 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
212 // 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.
213 void GaussianBlurView::Add(Actor child)
215 mChildrenRoot.Add(child);
218 void GaussianBlurView::Remove(Actor child)
220 mChildrenRoot.Remove(child);
223 void GaussianBlurView::SetUserImageAndOutputRenderTarget(Texture inputImage, FrameBuffer outputRenderTarget)
225 // can only do this if the GaussianBlurView object was created with this parameter set
226 DALI_ASSERT_ALWAYS(mBlurUserImage);
228 mUserInputImage = inputImage;
230 SetRendererTexture( mHorizBlurActor.GetRendererAt(0), inputImage );
232 mUserOutputRenderTarget = outputRenderTarget;
235 FrameBuffer GaussianBlurView::GetBlurredRenderTarget() const
237 if(!mUserOutputRenderTarget)
239 return mRenderTargetForRenderingChildren;
242 return mUserOutputRenderTarget;
245 void GaussianBlurView::SetBackgroundColor( const Vector4& color )
247 mBackgroundColor = color;
250 Vector4 GaussianBlurView::GetBackgroundColor() const
252 return mBackgroundColor;
255 ///////////////////////////////////////////////////////////
260 void GaussianBlurView::OnInitialize()
262 // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
263 mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
264 mInternalRoot.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
266 //////////////////////////////////////////////////////
269 std::ostringstream fragmentStringStream;
270 fragmentStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
271 fragmentStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
272 std::string fragmentSource(fragmentStringStream.str());
274 //////////////////////////////////////////////////////
277 // Create an actor for performing a horizontal blur on the texture
278 mHorizBlurActor = Actor::New();
279 mHorizBlurActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
280 Renderer renderer = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
281 mHorizBlurActor.AddRenderer( renderer );
283 // Create an actor for performing a vertical blur on the texture
284 mVertBlurActor = Actor::New();
285 mVertBlurActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
286 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
287 mVertBlurActor.AddRenderer( renderer );
289 // Register a property that the user can control to fade the blur in / out via the GaussianBlurView object
291 mBlurStrengthPropertyIndex = self.RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
293 // Create an image view for compositing the blur and the original child actors render
296 mCompositingActor = Actor::New();
297 mCompositingActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
298 mCompositingActor.SetProperty( Actor::Property::OPACITY,GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
299 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
300 mCompositingActor.AddRenderer( renderer );
302 Constraint blurStrengthConstraint = Constraint::New<float>( mCompositingActor, Actor::Property::COLOR_ALPHA, EqualToConstraint());
303 blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) );
304 blurStrengthConstraint.Apply();
306 // 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
307 mTargetActor = Actor::New();
308 mTargetActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
309 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
310 mTargetActor.AddRenderer( renderer );
312 //////////////////////////////////////////////////////
313 // Create cameras for the renders corresponding to the view size
314 mRenderFullSizeCamera = CameraActor::New();
315 mRenderFullSizeCamera.SetInvertYAxis( true );
316 mRenderFullSizeCamera.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
318 //////////////////////////////////////////////////////
319 // Connect to actor tree
320 mInternalRoot.Add( mCompositingActor );
321 mInternalRoot.Add( mTargetActor );
322 mInternalRoot.Add( mRenderFullSizeCamera );
325 //////////////////////////////////////////////////////
326 // Create camera for the renders corresponding to the (potentially downsampled) render targets' size
327 mRenderDownsampledCamera = CameraActor::New();
328 mRenderDownsampledCamera.SetInvertYAxis( true );
329 mRenderDownsampledCamera.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
331 //////////////////////////////////////////////////////
332 // Connect to actor tree
333 Self().Add( mChildrenRoot );
334 mInternalRoot.Add( mHorizBlurActor );
335 mInternalRoot.Add( mVertBlurActor );
336 mInternalRoot.Add( mRenderDownsampledCamera );
340 void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
342 mTargetSize = Vector2(targetSize);
344 mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize);
346 if( !mBlurUserImage )
348 mCompositingActor.SetProperty( Actor::Property::SIZE, targetSize);
349 mTargetActor.SetProperty( Actor::Property::SIZE, targetSize);
351 // 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
352 // 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
353 // size, this is the trade off for not being able to modify render target size
354 // Change camera z position based on GaussianBlurView actor height
355 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
356 mRenderFullSizeCamera.SetProperty( Actor::Property::POSITION_Z, mTargetSize.height * cameraPosConstraintScale);
360 // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
367 Control::OnSizeSet( targetSize );
370 void GaussianBlurView::OnChildAdd( Actor& child )
372 if( child != mChildrenRoot && child != mInternalRoot)
374 mChildrenRoot.Add( child );
377 Control::OnChildAdd( child );
380 void GaussianBlurView::OnChildRemove( Actor& child )
382 mChildrenRoot.Remove( child );
384 Control::OnChildRemove( child );
387 void GaussianBlurView::AllocateResources()
389 mLastSize = mTargetSize;
391 // get size of downsampled render targets
392 mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
393 mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
395 // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
396 mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
397 // 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
398 mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
399 mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
400 mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
402 mRenderDownsampledCamera.SetProperty( Actor::Property::POSITION, Vector3(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f))));
404 // setup for normal operation
407 // Create and place a camera for the children render, corresponding to its render target size
408 mRenderFullSizeCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
409 // 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
410 mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
411 mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
412 mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
414 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
415 mRenderFullSizeCamera.SetProperty( Actor::Property::POSITION, Vector3(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale));
417 // create offscreen buffer of new size to render our child actors to
418 mRenderTargetForRenderingChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
419 Texture texture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
420 mRenderTargetForRenderingChildren.AttachColorTexture( texture );
422 // Set actor for performing a horizontal blur
423 SetRendererTexture( mHorizBlurActor.GetRendererAt(0), mRenderTargetForRenderingChildren );
425 // Create offscreen buffer for vert blur pass
426 mRenderTarget1 = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
427 texture = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight));
428 mRenderTarget1.AttachColorTexture( texture );
430 // use the completed blur in the first buffer and composite with the original child actors render
431 SetRendererTexture( mCompositingActor.GetRendererAt(0), mRenderTarget1 );
433 // set up target actor for rendering result, i.e. the blurred image
434 SetRendererTexture( mTargetActor.GetRendererAt(0), mRenderTargetForRenderingChildren );
437 // Create offscreen buffer for horiz blur pass
438 mRenderTarget2 = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
439 Texture texture = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight));
440 mRenderTarget2.AttachColorTexture( texture );
442 // size needs to match render target
443 mHorizBlurActor.SetProperty( Actor::Property::SIZE, Vector2(mDownsampledWidth, mDownsampledHeight) );
445 // size needs to match render target
446 mVertBlurActor.SetProperty( Actor::Property::SIZE, Vector2(mDownsampledWidth, mDownsampledHeight) );
447 SetRendererTexture( mVertBlurActor.GetRendererAt(0), mRenderTarget2 );
449 // set gaussian blur up for new sized render targets
450 SetShaderConstants();
453 void GaussianBlurView::CreateRenderTasks()
455 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
459 // create render task to render our child actors to offscreen buffer
460 mRenderChildrenTask = taskList.CreateTask();
461 mRenderChildrenTask.SetSourceActor( mChildrenRoot );
462 mRenderChildrenTask.SetExclusive(true);
463 mRenderChildrenTask.SetInputEnabled( false );
464 mRenderChildrenTask.SetClearEnabled( true );
465 mRenderChildrenTask.SetClearColor( mBackgroundColor );
467 mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera);
468 mRenderChildrenTask.SetFrameBuffer( mRenderTargetForRenderingChildren );
472 mRenderChildrenTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
476 // perform a horizontal blur targeting the second buffer
477 mHorizBlurTask = taskList.CreateTask();
478 mHorizBlurTask.SetSourceActor( mHorizBlurActor );
479 mHorizBlurTask.SetExclusive(true);
480 mHorizBlurTask.SetInputEnabled( false );
481 mHorizBlurTask.SetClearEnabled( true );
482 mHorizBlurTask.SetClearColor( mBackgroundColor );
483 mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
484 mHorizBlurTask.SetFrameBuffer( mRenderTarget2 );
485 if( mRenderOnce || ( mRenderOnce && mBlurUserImage ) )
487 mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
490 // use the second buffer and perform a horizontal blur targeting the first buffer
491 mVertBlurTask = taskList.CreateTask();
492 mVertBlurTask.SetSourceActor( mVertBlurActor );
493 mVertBlurTask.SetExclusive(true);
494 mVertBlurTask.SetInputEnabled( false );
495 mVertBlurTask.SetClearEnabled( true );
496 mVertBlurTask.SetClearColor( mBackgroundColor );
497 mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
498 if(mUserOutputRenderTarget)
500 mVertBlurTask.SetFrameBuffer( mUserOutputRenderTarget );
504 mVertBlurTask.SetFrameBuffer( mRenderTarget1 );
506 if( mRenderOnce || ( mRenderOnce && mBlurUserImage ) )
508 mVertBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
509 mVertBlurTask.FinishedSignal().Connect( this, &GaussianBlurView::OnRenderTaskFinished );
512 // use the completed blur in the first buffer and composite with the original child actors render
515 mCompositeTask = taskList.CreateTask();
516 mCompositeTask.SetSourceActor( mCompositingActor );
517 mCompositeTask.SetExclusive(true);
518 mCompositeTask.SetInputEnabled( false );
520 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
521 mCompositeTask.SetFrameBuffer( mRenderTargetForRenderingChildren );
525 mCompositeTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
530 void GaussianBlurView::RemoveRenderTasks()
532 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
534 taskList.RemoveTask(mRenderChildrenTask);
535 taskList.RemoveTask(mHorizBlurTask);
536 taskList.RemoveTask(mVertBlurTask);
537 taskList.RemoveTask(mCompositeTask);
540 void GaussianBlurView::Activate()
544 // make sure resources are allocated and start the render tasks processing
545 Self().Add( mInternalRoot );
552 void GaussianBlurView::ActivateOnce()
559 void GaussianBlurView::Deactivate()
563 // stop render tasks processing
564 // Note: render target resources are automatically freed since we set the Image::Unused flag
565 mInternalRoot.Unparent();
566 mRenderTargetForRenderingChildren.Reset();
567 mRenderTarget1.Reset();
568 mRenderTarget2.Reset();
575 void GaussianBlurView::SetBlurBellCurveWidth(float blurBellCurveWidth)
577 // a value of zero leads to undefined Gaussian weights, do not allow user to do this
578 mBlurBellCurveWidth = std::max( blurBellCurveWidth, 0.001f );
581 float GaussianBlurView::CalcGaussianWeight(float x)
583 return (1.0f / sqrt(2.0f * Math::PI * mBlurBellCurveWidth)) * exp(-(x * x) / (2.0f * mBlurBellCurveWidth * mBlurBellCurveWidth));
586 void GaussianBlurView::SetShaderConstants()
591 float w, totalWeights;
594 uvOffsets = new Vector2[mNumSamples + 1];
595 weights = new float[mNumSamples + 1];
597 totalWeights = weights[0] = CalcGaussianWeight(0);
598 uvOffsets[0].x = 0.0f;
599 uvOffsets[0].y = 0.0f;
601 for(i=0; i<mNumSamples >> 1; i++)
603 w = CalcGaussianWeight((float)(i + 1));
604 weights[(i << 1) + 1] = w;
605 weights[(i << 1) + 2] = w;
606 totalWeights += w * 2.0f;
608 // offset texture lookup to between texels, that way the bilinear filter in the texture hardware will average two samples with one lookup
609 ofs = ((float)(i << 1)) + 1.5f;
611 // get offsets from units of pixels into uv coordinates in [0..1]
612 float ofsX = ofs / mDownsampledWidth;
613 float ofsY = ofs / mDownsampledHeight;
614 uvOffsets[(i << 1) + 1].x = ofsX;
615 uvOffsets[(i << 1) + 1].y = ofsY;
617 uvOffsets[(i << 1) + 2].x = -ofsX;
618 uvOffsets[(i << 1) + 2].y = -ofsY;
621 for(i=0; i<mNumSamples; i++)
623 weights[i] /= totalWeights;
626 // set shader constants
627 Vector2 xAxis(1.0f, 0.0f);
628 Vector2 yAxis(0.0f, 1.0f);
629 for (i = 0; i < mNumSamples; ++i )
631 mHorizBlurActor.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
632 mHorizBlurActor.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
634 mVertBlurActor.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
635 mVertBlurActor.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
642 std::string GaussianBlurView::GetSampleOffsetsPropertyName( unsigned int index ) const
644 DALI_ASSERT_ALWAYS( index < mNumSamples );
646 std::ostringstream oss;
647 oss << "uSampleOffsets[" << index << "]";
651 std::string GaussianBlurView::GetSampleWeightsPropertyName( unsigned int index ) const
653 DALI_ASSERT_ALWAYS( index < mNumSamples );
655 std::ostringstream oss;
656 oss << "uSampleWeights[" << index << "]";
660 Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal& GaussianBlurView::FinishedSignal()
662 return mFinishedSignal;
665 void GaussianBlurView::OnRenderTaskFinished(Dali::RenderTask& renderTask)
667 Toolkit::GaussianBlurView handle( GetOwner() );
668 mFinishedSignal.Emit( handle );
671 } // namespace Internal
672 } // namespace Toolkit