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