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