2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 #include "bloom-view-impl.h"
19 #include "../gaussian-blur-view/gaussian-blur-view-impl.h"
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>
45 return Toolkit::BloomView::New();
48 TypeRegistration mType( typeid(Toolkit::BloomView), typeid(Toolkit::Control), Create );
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;
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;
66 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
68 const std::string BLOOM_BLUR_STRENGTH_PROPERTY_NAME( "BlurStrengthProperty" );
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" );
77 ///////////////////////////////////////////////////////
82 const char* const BLOOM_EXTRACT_FRAGMENT_SOURCE =
83 "uniform float uBloomThreshold;\n"
84 "uniform float uRecipOneMinusBloomThreshold;\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"
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"
99 "vec4 ChangeSaturation(vec4 col, float sat)\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"
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"
121 BloomView::BloomView()
122 : Control( 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)
142 BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
143 const float downsampleWidthScale, const float downsampleHeightScale)
144 : Control( 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)
164 BloomView::~BloomView()
168 Toolkit::BloomView BloomView::New()
170 BloomView* impl = new BloomView();
172 Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
174 // Second-phase init of the implementation
175 // This can only be done after the CustomActor connection has been made...
181 Toolkit::BloomView BloomView::New(const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
182 const float downsampleWidthScale, const float downsampleHeightScale)
184 BloomView* impl = new BloomView( blurNumSamples, blurBellCurveWidth, renderTargetPixelFormat, downsampleWidthScale, downsampleHeightScale);
186 Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
188 // Second-phase init of the implementation
189 // This can only be done after the CustomActor connection has been made...
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)
200 mChildrenRoot.Add(child);
203 void BloomView::Remove(Actor child)
205 mChildrenRoot.Remove(child);
213 ///////////////////////////////////////////////////////////
218 void BloomView::OnInitialize()
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
225 //////////////////////////////////////////////////////
228 // Create shader used for extracting the bright parts of an image
229 mBloomExtractShader = ShaderEffect::New( "", BLOOM_EXTRACT_FRAGMENT_SOURCE );
231 // Create shader used to composite bloom and original image to output render target
232 mCompositeShader = ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE );
235 //////////////////////////////////////////////////////
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 );
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
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
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 );
266 //////////////////////////////////////////////////////
267 // Create cameras for the renders corresponding to the (potentially downsampled) render targets' size
268 mRenderDownsampledCamera = CameraActor::New();
269 mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
271 mRenderFullSizeCamera = CameraActor::New();
272 mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
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 );
285 // bind properties for / set shader constants to defaults
290 * ZrelativeToYconstraint
292 * f(current, property, scale) = Vector3(current.x, current.y, property.y * scale)
294 struct ZrelativeToYconstraint
296 ZrelativeToYconstraint( float scale )
300 Vector3 operator()(const Vector3& current,
301 const PropertyInput& property)
307 v.z = property.GetVector3().y * mScale;
315 void BloomView::OnControlSizeSet(const Vector3& targetSize)
317 mTargetSize = Vector2(targetSize);
319 // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
326 void BloomView::AllocateResources()
328 // size of render targets etc is based on the size of this actor, ignoring z
329 if(mTargetSize != mLastSize)
331 mLastSize = mTargetSize;
333 // get size of downsampled render targets
334 mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
335 mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
338 //////////////////////////////////////////////////////
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
349 mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
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
359 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
360 mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
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
371 mRenderFullSizeCamera.RemoveConstraints();
372 mRenderFullSizeCamera.ApplyConstraint( Constraint::New<Vector3>( Actor::POSITION, ParentSource( Actor::SIZE ), ZrelativeToYconstraint(cameraPosConstraintScale) ) );
375 //////////////////////////////////////////////////////
376 // Pass size change onto GaussianBlurView, so it matches
377 mGaussianBlurView.SetSize(mTargetSize);
378 GetImpl(mGaussianBlurView).AllocateResources();
381 //////////////////////////////////////////////////////
382 // Create render targets
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 );
390 //////////////////////////////////////////////////////
391 // Point actors and render tasks at new render targets
393 mBloomExtractImageActor.SetImage( mRenderTargetForRenderingChildren );
394 mBloomExtractImageActor.SetSize(mDownsampledWidth, mDownsampledHeight); // size needs to match render target
396 // set GaussianBlurView to blur our extracted bloom
397 mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBloomExtractTarget);
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 );
403 // set up target actor for rendering result, i.e. the blurred image
404 mTargetImageActor.SetImage(mOutputRenderTarget);
408 void BloomView::CreateRenderTasks()
410 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
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 );
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 );
426 // GaussianBlurView tasks must be created here, so they are executed in the correct order with respect to BloomView tasks
427 GetImpl(mGaussianBlurView).CreateRenderTasks();
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 );
436 mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
437 mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
438 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
440 mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
441 mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
442 mCompositeTask.SetTargetFrameBuffer( mOutputRenderTarget );
445 void BloomView::RemoveRenderTasks()
447 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
449 taskList.RemoveTask(mRenderChildrenTask);
450 taskList.RemoveTask(mBloomExtractTask);
452 GetImpl(mGaussianBlurView).RemoveRenderTasks();
454 taskList.RemoveTask(mCompositeTask);
457 void BloomView::OnStageDisconnection()
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()
464 void BloomView::OnControlStageConnection()
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()
471 void BloomView::Activate()
473 // make sure resources are allocated and start the render tasks processing
478 void BloomView::Deactivate()
480 // stop render tasks processing
481 // Note: render target resources are automatically freed since we set the Image::Unused flag
486 * EqualToConstraintFloat
488 * f(current, property) = property
490 struct EqualToConstraintFloat
492 EqualToConstraintFloat(){}
494 float operator()(const float current, const PropertyInput& property) {return property.GetFloat();}
498 * RecipOneMinusConstraint
500 * f(current, property) = property
502 struct RecipOneMinusConstraint
504 RecipOneMinusConstraint(){}
506 float operator()(const float current, const PropertyInput& property)
508 return 1.0f / (1.0f - property.GetFloat());
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()
516 CustomActor self = Self();
519 ///////////////////////////////////////////
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) );
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);
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);
538 ////////////////////////////////////////////
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);
547 ////////////////////////////////////////////
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);
558 ////////////////////////////////////////////
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);
569 ////////////////////////////////////////////
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);
580 ////////////////////////////////////////////
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);
591 } // namespace Internal
593 } // namespace Toolkit