Merge "Type registry helper: Toolkit change to correct Programming Guide for Custom...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / bloom-view / bloom-view-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "bloom-view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <iomanip>
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/property-map.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali/public-api/render-tasks/render-task-list.h>
31 #include <dali/devel-api/rendering/renderer.h>
32
33 // INTERNAL INCLUDES
34 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
35 #include <dali-toolkit/devel-api/controls/bloom-view/bloom-view.h>
36 #include "../gaussian-blur-view/gaussian-blur-view-impl.h"
37
38 namespace Dali
39 {
40
41 namespace Toolkit
42 {
43
44 namespace Internal
45 {
46
47 namespace
48 {
49
50 using namespace Dali;
51
52 BaseHandle Create()
53 {
54   return Toolkit::BloomView::New();
55 }
56
57 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::BloomView, Toolkit::Control, Create )
58 DALI_TYPE_REGISTRATION_END()
59
60 // default parameters
61 const float BLOOM_THRESHOLD_DEFAULT = 0.25f;
62 const float BLOOM_BLUR_STRENGTH_DEFAULT = 1.0f;
63 const float BLOOM_INTENSITY_DEFAULT = 1.0f;
64 const float IMAGE_INTENSITY_DEFAULT = 1.0f;
65 const float BLOOM_SATURATION_DEFAULT = 1.0f;
66 const float IMAGE_SATURATION_DEFAULT = 1.0f;
67
68 // gaussian blur
69 const unsigned int BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES = 5;
70 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH = 1.5f;
71 const Pixel::Format BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
72 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_FADE_IN = 1.0f;                                       // default, fully blurred
73 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
74 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
75
76 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
77
78 const char* const BLOOM_BLUR_STRENGTH_PROPERTY_NAME = "BlurStrengthProperty";
79 const char* const BLOOM_THRESHOLD_PROPERTY_NAME = "uBloomThreshold";
80 const char* const RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME = "uRecipOneMinusBloomThreshold";
81 const char* const BLOOM_INTENSITY_PROPERTY_NAME = "uBloomIntensity";
82 const char* const BLOOM_SATURATION_PROPERTY_NAME = "uBloomSaturation";
83 const char* const IMAGE_INTENSITY_PROPERTY_NAME = "uImageIntensity";
84 const char* const IMAGE_SATURATION_PROPERTY_NAME = "uImageSaturation";
85
86 ///////////////////////////////////////////////////////
87 //
88 // Bloom shaders
89 //
90
91 const char* const BLOOM_EXTRACT_FRAGMENT_SOURCE =
92   "varying mediump vec2 vTexCoord;\n"
93   "uniform sampler2D sTexture;\n"
94   "uniform lowp vec4 uColor;\n"
95   "uniform mediump float uBloomThreshold;\n"
96   "uniform mediump float uRecipOneMinusBloomThreshold;\n"
97   "void main()\n"
98   "{\n"
99   "  mediump vec4 col;\n"
100   "  col = texture2D(sTexture, vTexCoord);\n"
101   "  col = (col - uBloomThreshold) * uRecipOneMinusBloomThreshold;\n" // remove intensities lower than the thresold and remap intensities above the threshold to [0..1]
102   "  gl_FragColor = clamp(col, 0.0, 1.0);\n"
103   "}\n";
104
105 const char* const COMPOSITE_FRAGMENT_SOURCE =
106   "precision mediump float;\n"
107   "varying mediump vec2 vTexCoord;\n"
108   "uniform sampler2D sTexture;\n"
109   "uniform sampler2D sEffect;\n"
110   "uniform lowp vec4 uColor;\n"
111   "uniform float uBloomIntensity;\n"
112   "uniform float uImageIntensity;\n"
113   "uniform float uBloomSaturation;\n"
114   "uniform float uImageSaturation;\n"
115
116   "vec4 ChangeSaturation(vec4 col, float sat)\n"
117   "{\n"
118   "  float grey = dot(col.rgb, vec3(0.3, 0.6, 0.1));\n"
119   "  return mix(vec4(grey, grey, grey, 1.0), col, sat);\n"
120   "}\n"
121
122   "void main()\n"
123   "{\n"
124   "  mediump vec4 image;\n"
125   "  mediump vec4 bloom;\n"
126   "  image = texture2D(sTexture, vTexCoord);\n"
127   "  bloom = texture2D(sEffect, vTexCoord);\n"
128   "  image = ChangeSaturation(image, uImageSaturation) * uImageIntensity;\n"
129   "  bloom = ChangeSaturation(bloom, uBloomSaturation) * uBloomIntensity;\n"
130   "  image *= 1.0 - clamp(bloom, 0.0, 1.0);\n" // darken base where bloom is strong, to prevent excessive burn-out of result
131   "  gl_FragColor = image + bloom;\n"
132   "}\n";
133
134 } // namespace
135
136
137
138 BloomView::BloomView()
139   : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
140   , mBlurNumSamples(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES)
141   , mBlurBellCurveWidth(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH)
142   , mPixelFormat(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT)
143   , mDownsampleWidthScale(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE)
144   , mDownsampleHeightScale(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE)
145   , mDownsampledWidth( 0.0f )
146   , mDownsampledHeight( 0.0f )
147   , mTargetSize(Vector2::ZERO)
148   , mLastSize(Vector2::ZERO)
149   , mChildrenRoot(Actor::New())
150   , mInternalRoot(Actor::New() )
151   , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
152   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
153   , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
154   , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
155   , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
156   , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
157   , mActivated( false )
158 {
159 }
160
161 BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
162                                     const float downsampleWidthScale, const float downsampleHeightScale)
163   : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
164   , mBlurNumSamples(blurNumSamples)
165   , mBlurBellCurveWidth(blurBellCurveWidth)
166   , mPixelFormat(renderTargetPixelFormat)
167   , mDownsampleWidthScale(downsampleWidthScale)
168   , mDownsampleHeightScale(downsampleHeightScale)
169   , mDownsampledWidth( 0.0f )
170   , mDownsampledHeight( 0.0f )
171   , mTargetSize(Vector2::ZERO)
172   , mLastSize(Vector2::ZERO)
173   , mChildrenRoot(Actor::New())
174   , mInternalRoot(Actor::New())
175   , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
176   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
177   , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
178   , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
179   , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
180   , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
181   , mActivated( false )
182 {
183 }
184
185 BloomView::~BloomView()
186 {
187 }
188
189 Toolkit::BloomView BloomView::New()
190 {
191   BloomView* impl = new BloomView();
192
193   Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
194
195   // Second-phase init of the implementation
196   // This can only be done after the CustomActor connection has been made...
197   impl->Initialize();
198
199   return handle;
200 }
201
202 Toolkit::BloomView BloomView::New(const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
203                                                 const float downsampleWidthScale, const float downsampleHeightScale)
204 {
205   BloomView* impl = new BloomView( blurNumSamples, blurBellCurveWidth, renderTargetPixelFormat, downsampleWidthScale, downsampleHeightScale);
206
207   Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
208
209   // Second-phase init of the implementation
210   // This can only be done after the CustomActor connection has been made...
211   impl->Initialize();
212
213   return handle;
214 }
215
216 ///////////////////////////////////////////////////////////
217 //
218 // Private methods
219 //
220
221 void BloomView::OnInitialize()
222 {
223   // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
224   mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
225   mInternalRoot.SetParentOrigin( ParentOrigin::CENTER );
226
227   //////////////////////////////////////////////////////
228   // Create actors
229
230   // Create an ImageActor for rendering from the scene texture to the bloom texture
231   mBloomExtractImageActor = Toolkit::ImageView::New();
232   mBloomExtractImageActor.SetParentOrigin( ParentOrigin::CENTER );
233
234   // Create shader used for extracting the bright parts of an image
235   Property::Map customShader;
236   customShader[ "fragmentShader" ] = BLOOM_EXTRACT_FRAGMENT_SOURCE;
237   Property::Map rendererMap;
238   rendererMap.Insert( "rendererType", "image" );
239   rendererMap.Insert( "shader", customShader );
240   mBloomExtractImageActor.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
241
242   // Create an ImageActor for compositing the result (scene and bloom textures) to output
243   mCompositeImageActor = Toolkit::ImageView::New();
244   mCompositeImageActor.SetParentOrigin( ParentOrigin::CENTER );
245
246   // Create shader used to composite bloom and original image to output render target
247   customShader[ "fragmentShader" ] = COMPOSITE_FRAGMENT_SOURCE;
248   rendererMap[ "shader" ] = customShader;
249   mCompositeImageActor.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
250
251   // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
252   mTargetImageActor = Toolkit::ImageView::New();
253   mTargetImageActor.SetParentOrigin( ParentOrigin::CENTER );
254
255   // Create the Gaussian Blur object + render tasks
256   // Note that we use mBloomExtractTarget as the source image and also re-use this as the gaussian blur final render target. This saves the gaussian blur code from creating it
257   // render targets etc internally, so we make better use of resources
258   // Note, this also internally creates the render tasks used by the Gaussian blur, this must occur after the bloom extraction and before the compositing
259   mGaussianBlurView = Dali::Toolkit::GaussianBlurView::New(mBlurNumSamples, mBlurBellCurveWidth, mPixelFormat, mDownsampleWidthScale, mDownsampleHeightScale, true);
260   mGaussianBlurView.SetParentOrigin( ParentOrigin::CENTER );
261
262
263   //////////////////////////////////////////////////////
264   // Create cameras for the renders corresponding to the (potentially downsampled) render targets' size
265   mRenderDownsampledCamera = CameraActor::New();
266   mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
267   mRenderDownsampledCamera.SetInvertYAxis( true );
268
269   mRenderFullSizeCamera = CameraActor::New();
270   mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
271   mRenderFullSizeCamera.SetInvertYAxis( true );
272
273
274   ////////////////////////////////
275   // Connect to actor tree
276   Self().Add( mChildrenRoot );
277   Self().Add( mInternalRoot );
278   mInternalRoot.Add( mBloomExtractImageActor );
279   mInternalRoot.Add( mGaussianBlurView );
280   mInternalRoot.Add( mCompositeImageActor );
281   mInternalRoot.Add( mTargetImageActor );
282   mInternalRoot.Add( mRenderDownsampledCamera );
283   mInternalRoot.Add( mRenderFullSizeCamera );
284
285   // bind properties for / set shader constants to defaults
286   SetupProperties();
287 }
288
289 void BloomView::OnSizeSet(const Vector3& targetSize)
290 {
291   Control::OnSizeSet( targetSize );
292
293   mTargetSize = Vector2(targetSize);
294   mChildrenRoot.SetSize(targetSize);
295   mCompositeImageActor.SetSize(targetSize);
296   mTargetImageActor.SetSize(targetSize);
297
298   // Children render camera must move when GaussianBlurView object is
299   // resized. This is since we cannot change render target size - so we need
300   // to remap the child actors' rendering accordingly so they still exactly
301   // fill the render target. Note that this means the effective resolution of
302   // the child render changes as the GaussianBlurView object changes size,
303   // this is the trade off for not being able to modify render target size
304   // Change camera z position based on GaussianBlurView actor height
305   float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
306   mRenderFullSizeCamera.SetZ( mTargetSize.height * cameraPosConstraintScale);
307
308   // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
309   if(mActivated)
310   {
311     Deactivate();
312     Activate();
313   }
314 }
315
316 void BloomView::OnChildAdd( Actor& child )
317 {
318   Control::OnChildAdd( child );
319
320   if( child != mChildrenRoot && child != mInternalRoot)
321   {
322     mChildrenRoot.Add( child );
323   }
324 }
325
326 void BloomView::OnChildRemove( Actor& child )
327 {
328   mChildrenRoot.Remove( child );
329
330   Control::OnChildRemove( child );
331 }
332
333 void BloomView::AllocateResources()
334 {
335   // size of render targets etc is based on the size of this actor, ignoring z
336   if(mTargetSize != mLastSize || !mActivated)
337   {
338     mLastSize = mTargetSize;
339
340     // get size of downsampled render targets
341     mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
342     mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
343
344
345     //////////////////////////////////////////////////////
346     // Create cameras
347
348     // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
349     mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
350     // 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
351     mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
352     mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
353     mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
354
355     mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
356
357     // Create and place a camera for the children render, corresponding to its render target size
358     mRenderFullSizeCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
359     // 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
360     mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
361     mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
362     mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
363
364     float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
365     mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
366
367     //////////////////////////////////////////////////////
368     // Pass size change onto GaussianBlurView, so it matches
369     mGaussianBlurView.SetSize(mTargetSize);
370     GetImpl(mGaussianBlurView).AllocateResources();
371
372
373     //////////////////////////////////////////////////////
374     // Create render targets
375
376     // create off screen buffer of new size to render our child actors to
377     mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
378     mBloomExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
379     FrameBufferImage mBlurExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
380     mOutputRenderTarget = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED);
381
382
383     //////////////////////////////////////////////////////
384     // Point actors and render tasks at new render targets
385
386     mBloomExtractImageActor.SetImage( mRenderTargetForRenderingChildren );
387     mBloomExtractImageActor.SetSize(mDownsampledWidth, mDownsampledHeight); // size needs to match render target
388
389     // set GaussianBlurView to blur our extracted bloom
390     mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBlurExtractTarget);
391
392     // use the completed blur in the first buffer and composite with the original child actors render
393     mCompositeImageActor.SetImage( mRenderTargetForRenderingChildren );
394     TextureSet textureSet = mCompositeImageActor.GetRendererAt(0).GetTextures();
395     textureSet.SetImage( 1u, mBlurExtractTarget );
396
397     // set up target actor for rendering result, i.e. the blurred image
398     mTargetImageActor.SetImage(mOutputRenderTarget);
399   }
400 }
401
402 void BloomView::CreateRenderTasks()
403 {
404   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
405
406   // create render task to render our child actors to offscreen buffer
407   mRenderChildrenTask = taskList.CreateTask();
408   mRenderChildrenTask.SetSourceActor( mChildrenRoot );
409   mRenderChildrenTask.SetExclusive(true);
410   mRenderChildrenTask.SetInputEnabled( false );
411   mRenderChildrenTask.SetClearEnabled( true );
412   mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
413   mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
414
415   // Extract the bright part of the image and render to a new buffer. Downsampling also occurs at this stage to save pixel fill, if it is set up.
416   mBloomExtractTask = taskList.CreateTask();
417   mBloomExtractTask.SetSourceActor( mBloomExtractImageActor );
418   mBloomExtractTask.SetExclusive(true);
419   mBloomExtractTask.SetInputEnabled( false );
420   mBloomExtractTask.SetClearEnabled( true );
421   mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
422   mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
423
424   // GaussianBlurView tasks must be created here, so they are executed in the correct order with respect to BloomView tasks
425   GetImpl(mGaussianBlurView).CreateRenderTasks();
426
427   // Use an image actor displaying the children render and composite it with the blurred bloom buffer, targeting the output
428   mCompositeTask = taskList.CreateTask();
429   mCompositeTask.SetSourceActor( mCompositeImageActor );
430   mCompositeTask.SetExclusive(true);
431   mCompositeTask.SetInputEnabled( false );
432   mCompositeTask.SetClearEnabled( true );
433   mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
434   mCompositeTask.SetTargetFrameBuffer( mOutputRenderTarget );
435 }
436
437 void BloomView::RemoveRenderTasks()
438 {
439   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
440
441   taskList.RemoveTask(mRenderChildrenTask);
442   taskList.RemoveTask(mBloomExtractTask);
443
444   GetImpl(mGaussianBlurView).RemoveRenderTasks();
445
446   taskList.RemoveTask(mCompositeTask);
447 }
448
449 void BloomView::Activate()
450 {
451   // make sure resources are allocated and start the render tasks processing
452   AllocateResources();
453   CreateRenderTasks();
454   mActivated = true;
455 }
456
457 void BloomView::Deactivate()
458 {
459   // stop render tasks processing
460   // Note: render target resources are automatically freed since we set the Image::Unused flag
461   RemoveRenderTasks();
462   mRenderTargetForRenderingChildren.Reset();
463   mBloomExtractTarget.Reset();
464   mOutputRenderTarget.Reset();
465   mActivated = false;
466 }
467
468 /**
469  * RecipOneMinusConstraint
470  *
471  * f(current, property) = property
472  */
473 struct RecipOneMinusConstraint
474 {
475   RecipOneMinusConstraint(){}
476
477   void operator()( float& current, const PropertyInputContainer& inputs )
478   {
479     current = 1.0f / ( 1.0f - inputs[0]->GetFloat() );
480   }
481 };
482
483 // create properties and constraints to tie internal shader etc settings to BloomView object. User can therefore animate / set them via BloomView object without knowing about
484 // internal implementation classes
485 void BloomView::SetupProperties()
486 {
487   CustomActor self = Self();
488
489
490   ///////////////////////////////////////////
491   // bloom threshold
492
493   // set defaults, makes sure properties are registered with shader
494   mBloomExtractImageActor.RegisterProperty( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
495   mBloomExtractImageActor.RegisterProperty( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
496
497   // Register a property that the user can control to change the bloom threshold
498   mBloomThresholdPropertyIndex = self.RegisterProperty(BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT);
499   Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractImageActor.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
500   Constraint bloomThresholdConstraint = Constraint::New<float>( mBloomExtractImageActor, shaderBloomThresholdPropertyIndex, EqualToConstraint());
501   bloomThresholdConstraint.AddSource( Source(self, mBloomThresholdPropertyIndex) );
502   bloomThresholdConstraint.Apply();
503
504   // precalc 1.0 / (1.0 - threshold) on CPU to save shader insns, using constraint to tie to the normal threshold property
505   Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractImageActor.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
506   Constraint thresholdConstraint = Constraint::New<float>( mBloomExtractImageActor, shaderRecipOneMinusBloomThresholdPropertyIndex, RecipOneMinusConstraint());
507   thresholdConstraint.AddSource( LocalSource(shaderBloomThresholdPropertyIndex) );
508   thresholdConstraint.Apply();
509
510
511   ////////////////////////////////////////////
512   // bloom strength
513
514   // Register a property that the user can control to fade the blur in / out via internal GaussianBlurView object
515   mBlurStrengthPropertyIndex = self.RegisterProperty(BLOOM_BLUR_STRENGTH_PROPERTY_NAME, BLOOM_BLUR_STRENGTH_DEFAULT);
516   Constraint blurStrengthConstraint = Constraint::New<float>( mGaussianBlurView, mGaussianBlurView.GetBlurStrengthPropertyIndex(), EqualToConstraint());
517   blurStrengthConstraint.AddSource( Source(self, mBlurStrengthPropertyIndex) );
518   blurStrengthConstraint.Apply();
519
520
521   ////////////////////////////////////////////
522   // bloom intensity
523
524   // Register a property that the user can control to fade the bloom intensity via internally hidden shader
525   mBloomIntensityPropertyIndex = self.RegisterProperty(BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT);
526   mCompositeImageActor.RegisterProperty( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
527   Property::Index shaderBloomIntensityPropertyIndex = mCompositeImageActor.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
528   Constraint bloomIntensityConstraint = Constraint::New<float>( mCompositeImageActor, shaderBloomIntensityPropertyIndex, EqualToConstraint());
529   bloomIntensityConstraint.AddSource( Source(self, mBloomIntensityPropertyIndex) );
530   bloomIntensityConstraint.Apply();
531
532
533   ////////////////////////////////////////////
534   // bloom saturation
535
536   // Register a property that the user can control to fade the bloom saturation via internally hidden shader
537   mBloomSaturationPropertyIndex = self.RegisterProperty(BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT);
538   mCompositeImageActor.RegisterProperty( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
539   Property::Index shaderBloomSaturationPropertyIndex = mCompositeImageActor.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
540   Constraint bloomSaturationConstraint = Constraint::New<float>( mCompositeImageActor, shaderBloomSaturationPropertyIndex, EqualToConstraint());
541   bloomSaturationConstraint.AddSource( Source(self, mBloomSaturationPropertyIndex) );
542   bloomSaturationConstraint.Apply();
543
544
545   ////////////////////////////////////////////
546   // image intensity
547
548   // Register a property that the user can control to fade the image intensity via internally hidden shader
549   mImageIntensityPropertyIndex = self.RegisterProperty(IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT);
550   mCompositeImageActor.RegisterProperty( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
551   Property::Index shaderImageIntensityPropertyIndex = mCompositeImageActor.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
552   Constraint imageIntensityConstraint = Constraint::New<float>( mCompositeImageActor, shaderImageIntensityPropertyIndex, EqualToConstraint());
553   imageIntensityConstraint.AddSource( Source(self, mImageIntensityPropertyIndex) );
554   imageIntensityConstraint.Apply();
555
556
557   ////////////////////////////////////////////
558   // image saturation
559
560   // Register a property that the user can control to fade the image saturation via internally hidden shader
561   mImageSaturationPropertyIndex = self.RegisterProperty(IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT);
562   mCompositeImageActor.RegisterProperty( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
563   Property::Index shaderImageSaturationPropertyIndex = mCompositeImageActor.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
564   Constraint imageSaturationConstraint = Constraint::New<float>( mCompositeImageActor, shaderImageSaturationPropertyIndex, EqualToConstraint());
565   imageSaturationConstraint.AddSource( Source(self, mImageSaturationPropertyIndex) );
566   imageSaturationConstraint.Apply();
567 }
568
569 } // namespace Internal
570
571 } // namespace Toolkit
572
573 } // namespace Dali