2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "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>
37 #include <dali-toolkit/public-api/visuals/visual-properties.h>
38 #include <dali-toolkit/internal/controls/control/control-renderers.h>
41 // pixel format / size - set from JSON
42 // 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
43 // default near clip value
44 // Manager object - re-use render targets if there are multiple GaussianBlurViews created
47 /////////////////////////////////////////////////////////
48 // IMPLEMENTATION NOTES
50 // As the GaussianBlurView actor changes size, the amount of pixels we need to blur changes. Therefore we need some way of doing this. However:-
51 // OnSetSize() does not get called when GaussianBlurView object size is modified using a Constraint.
52 // 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
53 // OnSizeAnimation() to alter render target sizes.
54 // 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
55 // 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
56 // by using constraints relative to the GaussianBlurView actor size.
60 // 1st mode, this control has a tree of actors (use Add() to add children) that are rendered and blurred.
61 // mRenderChildrenTask renders children to FB mRenderTargetForRenderingChildren
62 // mHorizBlurTask renders mHorizBlurActor Actor showing FB mRenderTargetForRenderingChildren into FB mRenderTarget2
63 // mVertBlurTask renders mVertBlurActor Actor showing FB mRenderTarget2 into FB mRenderTarget1
64 // mCompositeTask renders mCompositingActor Actor showing FB mRenderTarget1 into FB mRenderTargetForRenderingChildren
66 // 2nd mode, an image is blurred and rendered to a supplied target framebuffer
67 // mHorizBlurTask renders mHorizBlurActor Actor showing mUserInputImage into FB mRenderTarget2
68 // mVertBlurTask renders mVertBlurActor Actor showing mRenderTarget2 into FB mUserOutputRenderTarget
70 // Only this 2nd mode handles ActivateOnce
88 return Toolkit::GaussianBlurView::New();
91 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::GaussianBlurView, Toolkit::Control, Create )
92 DALI_TYPE_REGISTRATION_END()
94 const unsigned int GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES = 5;
95 const float GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH = 1.5f;
96 const Pixel::Format GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
97 const float GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH = 1.0f; // default, fully blurred
98 const char* const GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME = "GaussianBlurStrengthPropertyName";
99 const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
100 const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
102 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
104 const char* const GAUSSIAN_BLUR_FRAGMENT_SOURCE = DALI_COMPOSE_SHADER(
105 varying mediump vec2 vTexCoord;\n
106 uniform sampler2D sTexture;\n
107 uniform lowp vec4 uColor;\n
108 uniform mediump vec2 uSampleOffsets[NUM_SAMPLES];\n
109 uniform mediump float uSampleWeights[NUM_SAMPLES];\n
113 mediump vec4 col = texture2D(sTexture, vTexCoord + uSampleOffsets[0]) * uSampleWeights[0];\n
114 for (int i=1; i<NUM_SAMPLES; ++i)\n
116 col += texture2D(sTexture, vTexCoord + uSampleOffsets[i]) * uSampleWeights[i];\n
118 gl_FragColor = col;\n
125 GaussianBlurView::GaussianBlurView()
126 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS ) ),
127 mNumSamples(GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES),
128 mBlurBellCurveWidth( 0.001f ),
129 mPixelFormat(GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT),
130 mDownsampleWidthScale(GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE),
131 mDownsampleHeightScale(GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE),
132 mDownsampledWidth( 0.0f ),
133 mDownsampledHeight( 0.0f ),
134 mBlurUserImage( false ),
135 mRenderOnce( false ),
136 mBackgroundColor( Color::BLACK ),
137 mTargetSize(Vector2::ZERO),
138 mLastSize(Vector2::ZERO),
139 mChildrenRoot(Actor::New()),
140 mInternalRoot(Actor::New()),
141 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
144 SetBlurBellCurveWidth(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH);
147 GaussianBlurView::GaussianBlurView( const unsigned int numSamples,
148 const float blurBellCurveWidth,
149 const Pixel::Format renderTargetPixelFormat,
150 const float downsampleWidthScale,
151 const float downsampleHeightScale,
153 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS ) ),
154 mNumSamples(numSamples),
155 mBlurBellCurveWidth( 0.001f ),
156 mPixelFormat(renderTargetPixelFormat),
157 mDownsampleWidthScale(downsampleWidthScale),
158 mDownsampleHeightScale(downsampleHeightScale),
159 mDownsampledWidth( 0.0f ),
160 mDownsampledHeight( 0.0f ),
161 mBlurUserImage( blurUserImage ),
162 mRenderOnce( false ),
163 mBackgroundColor( Color::BLACK ),
164 mTargetSize(Vector2::ZERO),
165 mLastSize(Vector2::ZERO),
166 mChildrenRoot(Actor::New()),
167 mInternalRoot(Actor::New()),
168 mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
171 SetBlurBellCurveWidth(blurBellCurveWidth);
174 GaussianBlurView::~GaussianBlurView()
179 Toolkit::GaussianBlurView GaussianBlurView::New()
181 GaussianBlurView* impl = new GaussianBlurView();
183 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
185 // Second-phase init of the implementation
186 // This can only be done after the CustomActor connection has been made...
192 Toolkit::GaussianBlurView GaussianBlurView::New(const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
193 const float downsampleWidthScale, const float downsampleHeightScale,
196 GaussianBlurView* impl = new GaussianBlurView( numSamples, blurBellCurveWidth, renderTargetPixelFormat,
197 downsampleWidthScale, downsampleHeightScale,
200 Dali::Toolkit::GaussianBlurView handle = Dali::Toolkit::GaussianBlurView( *impl );
202 // Second-phase init of the implementation
203 // This can only be done after the CustomActor connection has been made...
209 /////////////////////////////////////////////////////////////
210 // 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
211 // 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.
212 void GaussianBlurView::Add(Actor child)
214 mChildrenRoot.Add(child);
217 void GaussianBlurView::Remove(Actor child)
219 mChildrenRoot.Remove(child);
222 void GaussianBlurView::SetUserImageAndOutputRenderTarget(Texture inputImage, FrameBuffer outputRenderTarget)
224 // can only do this if the GaussianBlurView object was created with this parameter set
225 DALI_ASSERT_ALWAYS(mBlurUserImage);
227 mUserInputImage = inputImage;
229 SetRendererTexture( mHorizBlurActor.GetRendererAt(0), inputImage );
231 mUserOutputRenderTarget = outputRenderTarget;
234 FrameBuffer GaussianBlurView::GetBlurredRenderTarget() const
236 if(!mUserOutputRenderTarget)
238 return mRenderTargetForRenderingChildren;
241 return mUserOutputRenderTarget;
244 void GaussianBlurView::SetBackgroundColor( const Vector4& color )
246 mBackgroundColor = color;
249 Vector4 GaussianBlurView::GetBackgroundColor() const
251 return mBackgroundColor;
254 ///////////////////////////////////////////////////////////
259 void GaussianBlurView::OnInitialize()
261 // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
262 mChildrenRoot.SetParentOrigin(ParentOrigin::CENTER);
263 mInternalRoot.SetParentOrigin(ParentOrigin::CENTER);
265 //////////////////////////////////////////////////////
268 std::ostringstream fragmentStringStream;
269 fragmentStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
270 fragmentStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
271 std::string fragmentSource(fragmentStringStream.str());
273 //////////////////////////////////////////////////////
276 // Create an actor for performing a horizontal blur on the texture
277 mHorizBlurActor = Actor::New();
278 mHorizBlurActor.SetParentOrigin(ParentOrigin::CENTER);
279 Renderer renderer = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
280 mHorizBlurActor.AddRenderer( renderer );
282 // Create an actor for performing a vertical blur on the texture
283 mVertBlurActor = Actor::New();
284 mVertBlurActor.SetParentOrigin(ParentOrigin::CENTER);
285 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
286 mVertBlurActor.AddRenderer( renderer );
288 // Register a property that the user can control to fade the blur in / out via the GaussianBlurView object
290 mBlurStrengthPropertyIndex = self.RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
292 // Create an image view for compositing the blur and the original child actors render
295 mCompositingActor = Actor::New();
296 mCompositingActor.SetParentOrigin(ParentOrigin::CENTER);
297 mCompositingActor.SetOpacity(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
298 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
299 mCompositingActor.AddRenderer( renderer );
301 Constraint blurStrengthConstraint = Constraint::New<float>( mCompositingActor, Actor::Property::COLOR_ALPHA, EqualToConstraint());
302 blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) );
303 blurStrengthConstraint.Apply();
305 // 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
306 mTargetActor = Actor::New();
307 mTargetActor.SetParentOrigin(ParentOrigin::CENTER);
308 renderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
309 mTargetActor.AddRenderer( renderer );
311 //////////////////////////////////////////////////////
312 // Create cameras for the renders corresponding to the view size
313 mRenderFullSizeCamera = CameraActor::New();
314 mRenderFullSizeCamera.SetInvertYAxis( true );
315 mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
317 //////////////////////////////////////////////////////
318 // Connect to actor tree
319 mInternalRoot.Add( mCompositingActor );
320 mInternalRoot.Add( mTargetActor );
321 mInternalRoot.Add( mRenderFullSizeCamera );
324 //////////////////////////////////////////////////////
325 // Create camera for the renders corresponding to the (potentially downsampled) render targets' size
326 mRenderDownsampledCamera = CameraActor::New();
327 mRenderDownsampledCamera.SetInvertYAxis( true );
328 mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
330 //////////////////////////////////////////////////////
331 // Connect to actor tree
332 Self().Add( mChildrenRoot );
333 mInternalRoot.Add( mHorizBlurActor );
334 mInternalRoot.Add( mVertBlurActor );
335 mInternalRoot.Add( mRenderDownsampledCamera );
339 void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
341 mTargetSize = Vector2(targetSize);
343 mChildrenRoot.SetSize(targetSize);
345 if( !mBlurUserImage )
347 mCompositingActor.SetSize(targetSize);
348 mTargetActor.SetSize(targetSize);
350 // 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
351 // 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
352 // size, this is the trade off for not being able to modify render target size
353 // Change camera z position based on GaussianBlurView actor height
354 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
355 mRenderFullSizeCamera.SetZ(mTargetSize.height * cameraPosConstraintScale);
359 // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
366 Control::OnSizeSet( targetSize );
369 void GaussianBlurView::OnChildAdd( Actor& child )
371 if( child != mChildrenRoot && child != mInternalRoot)
373 mChildrenRoot.Add( child );
376 Control::OnChildAdd( child );
379 void GaussianBlurView::OnChildRemove( Actor& child )
381 mChildrenRoot.Remove( child );
383 Control::OnChildRemove( child );
386 void GaussianBlurView::AllocateResources()
388 // size of render targets etc is based on the size of this actor, ignoring z
389 if(mTargetSize != mLastSize)
391 mLastSize = mTargetSize;
393 // get size of downsampled render targets
394 mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
395 mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
397 // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
398 mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
399 // 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
400 mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
401 mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
402 mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
404 mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
406 // setup for normal operation
409 // Create and place a camera for the children render, corresponding to its render target size
410 mRenderFullSizeCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
411 // 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
412 mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
413 mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
414 mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
416 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
417 mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
419 // create offscreen buffer of new size to render our child actors to
420 mRenderTargetForRenderingChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
421 Texture texture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
422 mRenderTargetForRenderingChildren.AttachColorTexture( texture );
424 // Set actor for performing a horizontal blur
425 SetRendererTexture( mHorizBlurActor.GetRendererAt(0), mRenderTargetForRenderingChildren );
427 // Create offscreen buffer for vert blur pass
428 mRenderTarget1 = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
429 texture = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight));
430 mRenderTarget1.AttachColorTexture( texture );
432 // use the completed blur in the first buffer and composite with the original child actors render
433 SetRendererTexture( mCompositingActor.GetRendererAt(0), mRenderTarget1 );
435 // set up target actor for rendering result, i.e. the blurred image
436 SetRendererTexture( mTargetActor.GetRendererAt(0), mRenderTargetForRenderingChildren );
439 // Create offscreen buffer for horiz blur pass
440 mRenderTarget2 = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
441 Texture texture = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight));
442 mRenderTarget2.AttachColorTexture( texture );
444 // size needs to match render target
445 mHorizBlurActor.SetSize(mDownsampledWidth, mDownsampledHeight);
447 // size needs to match render target
448 mVertBlurActor.SetSize(mDownsampledWidth, mDownsampledHeight);
449 SetRendererTexture( mVertBlurActor.GetRendererAt(0), mRenderTarget2 );
451 // set gaussian blur up for new sized render targets
452 SetShaderConstants();
456 void GaussianBlurView::CreateRenderTasks()
458 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
462 // create render task to render our child actors to offscreen buffer
463 mRenderChildrenTask = taskList.CreateTask();
464 mRenderChildrenTask.SetSourceActor( mChildrenRoot );
465 mRenderChildrenTask.SetExclusive(true);
466 mRenderChildrenTask.SetInputEnabled( false );
467 mRenderChildrenTask.SetClearEnabled( true );
468 mRenderChildrenTask.SetClearColor( mBackgroundColor );
470 mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera);
471 mRenderChildrenTask.SetFrameBuffer( mRenderTargetForRenderingChildren );
474 // perform a horizontal blur targeting the second buffer
475 mHorizBlurTask = taskList.CreateTask();
476 mHorizBlurTask.SetSourceActor( mHorizBlurActor );
477 mHorizBlurTask.SetExclusive(true);
478 mHorizBlurTask.SetInputEnabled( false );
479 mHorizBlurTask.SetClearEnabled( true );
480 mHorizBlurTask.SetClearColor( mBackgroundColor );
481 mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
482 mHorizBlurTask.SetFrameBuffer( mRenderTarget2 );
483 if( mRenderOnce && mBlurUserImage )
485 mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
488 // use the second buffer and perform a horizontal blur targeting the first buffer
489 mVertBlurTask = taskList.CreateTask();
490 mVertBlurTask.SetSourceActor( mVertBlurActor );
491 mVertBlurTask.SetExclusive(true);
492 mVertBlurTask.SetInputEnabled( false );
493 mVertBlurTask.SetClearEnabled( true );
494 mVertBlurTask.SetClearColor( mBackgroundColor );
495 mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
496 if(mUserOutputRenderTarget)
498 mVertBlurTask.SetFrameBuffer( mUserOutputRenderTarget );
502 mVertBlurTask.SetFrameBuffer( mRenderTarget1 );
504 if( mRenderOnce && mBlurUserImage )
506 mVertBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
507 mVertBlurTask.FinishedSignal().Connect( this, &GaussianBlurView::OnRenderTaskFinished );
510 // use the completed blur in the first buffer and composite with the original child actors render
513 mCompositeTask = taskList.CreateTask();
514 mCompositeTask.SetSourceActor( mCompositingActor );
515 mCompositeTask.SetExclusive(true);
516 mCompositeTask.SetInputEnabled( false );
518 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
519 mCompositeTask.SetFrameBuffer( mRenderTargetForRenderingChildren );
523 void GaussianBlurView::RemoveRenderTasks()
525 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
527 taskList.RemoveTask(mRenderChildrenTask);
528 taskList.RemoveTask(mHorizBlurTask);
529 taskList.RemoveTask(mVertBlurTask);
530 taskList.RemoveTask(mCompositeTask);
533 void GaussianBlurView::Activate()
535 // make sure resources are allocated and start the render tasks processing
536 Self().Add( mInternalRoot );
542 void GaussianBlurView::ActivateOnce()
544 DALI_ASSERT_ALWAYS(mBlurUserImage); // Only works with blurring image mode.
549 void GaussianBlurView::Deactivate()
551 // stop render tasks processing
552 // Note: render target resources are automatically freed since we set the Image::Unused flag
553 mInternalRoot.Unparent();
555 mRenderTargetForRenderingChildren.Reset();
556 mRenderTarget1.Reset();
557 mRenderTarget2.Reset();
562 void GaussianBlurView::SetBlurBellCurveWidth(float blurBellCurveWidth)
564 // a value of zero leads to undefined Gaussian weights, do not allow user to do this
565 mBlurBellCurveWidth = std::max( blurBellCurveWidth, 0.001f );
568 float GaussianBlurView::CalcGaussianWeight(float x)
570 return (1.0f / sqrt(2.0f * Math::PI * mBlurBellCurveWidth)) * exp(-(x * x) / (2.0f * mBlurBellCurveWidth * mBlurBellCurveWidth));
573 void GaussianBlurView::SetShaderConstants()
578 float w, totalWeights;
581 uvOffsets = new Vector2[mNumSamples + 1];
582 weights = new float[mNumSamples + 1];
584 totalWeights = weights[0] = CalcGaussianWeight(0);
585 uvOffsets[0].x = 0.0f;
586 uvOffsets[0].y = 0.0f;
588 for(i=0; i<mNumSamples >> 1; i++)
590 w = CalcGaussianWeight((float)(i + 1));
591 weights[(i << 1) + 1] = w;
592 weights[(i << 1) + 2] = w;
593 totalWeights += w * 2.0f;
595 // offset texture lookup to between texels, that way the bilinear filter in the texture hardware will average two samples with one lookup
596 ofs = ((float)(i << 1)) + 1.5f;
598 // get offsets from units of pixels into uv coordinates in [0..1]
599 float ofsX = ofs / mDownsampledWidth;
600 float ofsY = ofs / mDownsampledHeight;
601 uvOffsets[(i << 1) + 1].x = ofsX;
602 uvOffsets[(i << 1) + 1].y = ofsY;
604 uvOffsets[(i << 1) + 2].x = -ofsX;
605 uvOffsets[(i << 1) + 2].y = -ofsY;
608 for(i=0; i<mNumSamples; i++)
610 weights[i] /= totalWeights;
613 // set shader constants
614 Vector2 xAxis(1.0f, 0.0f);
615 Vector2 yAxis(0.0f, 1.0f);
616 for (i = 0; i < mNumSamples; ++i )
618 mHorizBlurActor.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
619 mHorizBlurActor.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
621 mVertBlurActor.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
622 mVertBlurActor.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
629 std::string GaussianBlurView::GetSampleOffsetsPropertyName( unsigned int index ) const
631 DALI_ASSERT_ALWAYS( index < mNumSamples );
633 std::ostringstream oss;
634 oss << "uSampleOffsets[" << index << "]";
638 std::string GaussianBlurView::GetSampleWeightsPropertyName( unsigned int index ) const
640 DALI_ASSERT_ALWAYS( index < mNumSamples );
642 std::ostringstream oss;
643 oss << "uSampleWeights[" << index << "]";
647 Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal& GaussianBlurView::FinishedSignal()
649 return mFinishedSignal;
652 void GaussianBlurView::OnRenderTaskFinished(Dali::RenderTask& renderTask)
654 Toolkit::GaussianBlurView handle( GetOwner() );
655 mFinishedSignal.Emit( handle );
658 } // namespace Internal
659 } // namespace Toolkit