2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "bloom-view-impl.h"
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/object/type-registry-helper.h>
30 #include <dali/public-api/render-tasks/render-task-list.h>
33 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
34 #include <dali-toolkit/public-api/controls/bloom-view/bloom-view.h>
35 #include "../gaussian-blur-view/gaussian-blur-view-impl.h"
53 return Toolkit::BloomView::New();
56 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::BloomView, Toolkit::Control, Create )
57 DALI_TYPE_REGISTRATION_END()
60 const float BLOOM_THRESHOLD_DEFAULT = 0.25f;
61 const float BLOOM_BLUR_STRENGTH_DEFAULT = 1.0f;
62 const float BLOOM_INTENSITY_DEFAULT = 1.0f;
63 const float IMAGE_INTENSITY_DEFAULT = 1.0f;
64 const float BLOOM_SATURATION_DEFAULT = 1.0f;
65 const float IMAGE_SATURATION_DEFAULT = 1.0f;
68 const unsigned int BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES = 5;
69 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH = 1.5f;
70 const Pixel::Format BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
71 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_FADE_IN = 1.0f; // default, fully blurred
72 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
73 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
75 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
77 const char* const BLOOM_BLUR_STRENGTH_PROPERTY_NAME = "BlurStrengthProperty";
78 const char* const BLOOM_THRESHOLD_PROPERTY_NAME = "uBloomThreshold";
79 const char* const RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME = "uRecipOneMinusBloomThreshold";
80 const char* const BLOOM_INTENSITY_PROPERTY_NAME = "uBloomIntensity";
81 const char* const BLOOM_SATURATION_PROPERTY_NAME = "uBloomSaturation";
82 const char* const IMAGE_INTENSITY_PROPERTY_NAME = "uImageIntensity";
83 const char* const IMAGE_SATURATION_PROPERTY_NAME = "uImageSaturation";
85 ///////////////////////////////////////////////////////
90 const char* const BLOOM_EXTRACT_FRAGMENT_SOURCE =
91 "uniform float uBloomThreshold;\n"
92 "uniform float uRecipOneMinusBloomThreshold;\n"
95 " mediump vec4 col;\n"
96 " col = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y));\n"
97 " col = (col - uBloomThreshold) * uRecipOneMinusBloomThreshold;\n" // remove intensities lower than the thresold and remap intensities above the threshold to [0..1]
98 " gl_FragColor = clamp(col, 0.0, 1.0);\n"
101 const char* const COMPOSITE_FRAGMENT_SOURCE =
102 "uniform float uBloomIntensity;\n"
103 "uniform float uImageIntensity;\n"
104 "uniform float uBloomSaturation;\n"
105 "uniform float uImageSaturation;\n"
107 "vec4 ChangeSaturation(vec4 col, float sat)\n"
109 " float grey = dot(col.rgb, vec3(0.3, 0.6, 0.1));\n"
110 " return mix(vec4(grey, grey, grey, 1.0), col, sat);\n"
115 " mediump vec4 image;\n"
116 " mediump vec4 bloom;\n"
117 " image = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y));\n"
118 " bloom = texture2D(sEffect, vec2(vTexCoord.x, vTexCoord.y));\n"
119 " image = ChangeSaturation(image, uImageSaturation) * uImageIntensity;\n"
120 " bloom = ChangeSaturation(bloom, uBloomSaturation) * uBloomIntensity;\n"
121 " image *= 1.0 - clamp(bloom, 0.0, 1.0);\n" // darken base where bloom is strong, to prevent excessive burn-out of result
122 " gl_FragColor = image + bloom;\n"
129 BloomView::BloomView()
130 : Control( CONTROL_BEHAVIOUR_NONE )
131 , mBlurNumSamples(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES)
132 , mBlurBellCurveWidth(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH)
133 , mPixelFormat(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT)
134 , mDownsampleWidthScale(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE)
135 , mDownsampleHeightScale(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE)
136 , mDownsampledWidth( 0.0f )
137 , mDownsampledHeight( 0.0f )
138 , mTargetSize(Vector2::ZERO)
139 , mLastSize(Vector2::ZERO)
140 , mChildrenRoot(Actor::New())
141 , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
142 , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
143 , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
144 , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
145 , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
146 , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
150 BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
151 const float downsampleWidthScale, const float downsampleHeightScale)
152 : Control( CONTROL_BEHAVIOUR_NONE )
153 , mBlurNumSamples(blurNumSamples)
154 , mBlurBellCurveWidth(blurBellCurveWidth)
155 , mPixelFormat(renderTargetPixelFormat)
156 , mDownsampleWidthScale(downsampleWidthScale)
157 , mDownsampleHeightScale(downsampleHeightScale)
158 , mDownsampledWidth( 0.0f )
159 , mDownsampledHeight( 0.0f )
160 , mTargetSize(Vector2::ZERO)
161 , mLastSize(Vector2::ZERO)
162 , mChildrenRoot(Actor::New())
163 , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
164 , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
165 , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
166 , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
167 , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
168 , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
172 BloomView::~BloomView()
176 Toolkit::BloomView BloomView::New()
178 BloomView* impl = new BloomView();
180 Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
182 // Second-phase init of the implementation
183 // This can only be done after the CustomActor connection has been made...
189 Toolkit::BloomView BloomView::New(const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
190 const float downsampleWidthScale, const float downsampleHeightScale)
192 BloomView* impl = new BloomView( blurNumSamples, blurBellCurveWidth, renderTargetPixelFormat, downsampleWidthScale, downsampleHeightScale);
194 Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
196 // Second-phase init of the implementation
197 // This can only be done after the CustomActor connection has been made...
203 /////////////////////////////////////////////////////////////
204 // 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
205 // 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.
206 void BloomView::Add(Actor child)
208 mChildrenRoot.Add(child);
211 void BloomView::Remove(Actor child)
213 mChildrenRoot.Remove(child);
221 ///////////////////////////////////////////////////////////
226 void BloomView::OnInitialize()
228 // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
229 mChildrenRoot.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
231 //////////////////////////////////////////////////////
234 // Create shader used for extracting the bright parts of an image
235 mBloomExtractShader = ShaderEffect::New( "", BLOOM_EXTRACT_FRAGMENT_SOURCE );
237 // Create shader used to composite bloom and original image to output render target
238 mCompositeShader = ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE );
241 //////////////////////////////////////////////////////
244 // Create an ImageActor for rendering from the scene texture to the bloom texture
245 mBloomExtractImageActor = ImageActor::New();
246 mBloomExtractImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
247 mBloomExtractImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
248 mBloomExtractImageActor.SetShaderEffect( mBloomExtractShader );
250 // Create an ImageActor for compositing the result (scene and bloom textures) to output
251 mCompositeImageActor = ImageActor::New();
252 mCompositeImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
253 mCompositeImageActor.SetShaderEffect( mCompositeShader );
254 mCompositeImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
256 // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
257 mTargetImageActor = ImageActor::New();
258 mTargetImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
259 mTargetImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
262 // Create the Gaussian Blur object + render tasks
263 // 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
264 // render targets etc internally, so we make better use of resources
265 // Note, this also internally creates the render tasks used by the Gaussian blur, this must occur after the bloom extraction and before the compositing
266 mGaussianBlurView = Dali::Toolkit::GaussianBlurView::New(mBlurNumSamples, mBlurBellCurveWidth, mPixelFormat, mDownsampleWidthScale, mDownsampleHeightScale, true);
267 mGaussianBlurView.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
270 //////////////////////////////////////////////////////
271 // Create cameras for the renders corresponding to the (potentially downsampled) render targets' size
272 mRenderDownsampledCamera = CameraActor::New();
273 mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
275 mRenderFullSizeCamera = CameraActor::New();
276 mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
279 ////////////////////////////////
280 // Connect to actor tree
281 Self().Add( mChildrenRoot );
282 Self().Add( mBloomExtractImageActor );
283 Self().Add( mGaussianBlurView );
284 Self().Add( mCompositeImageActor );
285 Self().Add( mTargetImageActor );
286 Self().Add( mRenderDownsampledCamera );
287 Self().Add( mRenderFullSizeCamera );
289 // bind properties for / set shader constants to defaults
293 void BloomView::OnControlSizeSet(const Vector3& targetSize)
295 mTargetSize = Vector2(targetSize);
296 mChildrenRoot.SetSize(targetSize);
297 mCompositeImageActor.SetSize(targetSize);
298 mTargetImageActor.SetSize(targetSize);
300 // Children render camera must move when GaussianBlurView object is
301 // resized. This is since we cannot change render target size - so we need
302 // to remap the child actors' rendering accordingly so they still exactly
303 // fill the render target. Note that this means the effective resolution of
304 // the child render changes as the GaussianBlurView object changes size,
305 // this is the trade off for not being able to modify render target size
306 // Change camera z position based on GaussianBlurView actor height
307 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
308 mRenderFullSizeCamera.SetZ( mTargetSize.height * cameraPosConstraintScale);
310 // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
317 void BloomView::AllocateResources()
319 // size of render targets etc is based on the size of this actor, ignoring z
320 if(mTargetSize != mLastSize)
322 mLastSize = mTargetSize;
324 // get size of downsampled render targets
325 mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
326 mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
329 //////////////////////////////////////////////////////
332 // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
333 mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
334 // 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
335 mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
336 mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
337 mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
339 mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
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
348 float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
349 mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
351 //////////////////////////////////////////////////////
352 // Pass size change onto GaussianBlurView, so it matches
353 mGaussianBlurView.SetSize(mTargetSize);
354 GetImpl(mGaussianBlurView).AllocateResources();
357 //////////////////////////////////////////////////////
358 // Create render targets
360 // create off screen buffer of new size to render our child actors to
361 mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
362 mBloomExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
363 mOutputRenderTarget = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED);
366 //////////////////////////////////////////////////////
367 // Point actors and render tasks at new render targets
369 mBloomExtractImageActor.SetImage( mRenderTargetForRenderingChildren );
370 mBloomExtractImageActor.SetSize(mDownsampledWidth, mDownsampledHeight); // size needs to match render target
372 // set GaussianBlurView to blur our extracted bloom
373 mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBloomExtractTarget);
375 // use the completed blur in the first buffer and composite with the original child actors render
376 mCompositeImageActor.SetImage( mRenderTargetForRenderingChildren );
377 mCompositeShader.SetEffectImage( mBloomExtractTarget );
379 // set up target actor for rendering result, i.e. the blurred image
380 mTargetImageActor.SetImage(mOutputRenderTarget);
384 void BloomView::CreateRenderTasks()
386 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
388 // create render task to render our child actors to offscreen buffer
389 mRenderChildrenTask = taskList.CreateTask();
390 mRenderChildrenTask.SetSourceActor( mChildrenRoot );
391 mRenderChildrenTask.SetExclusive(true);
392 mRenderChildrenTask.SetInputEnabled( false );
393 mRenderChildrenTask.SetClearEnabled( true );
395 // 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.
396 mBloomExtractTask = taskList.CreateTask();
397 mBloomExtractTask.SetSourceActor( mBloomExtractImageActor );
398 mBloomExtractTask.SetExclusive(true);
399 mBloomExtractTask.SetInputEnabled( false );
400 mBloomExtractTask.SetClearEnabled( true );
402 // GaussianBlurView tasks must be created here, so they are executed in the correct order with respect to BloomView tasks
403 GetImpl(mGaussianBlurView).CreateRenderTasks();
405 // Use an image actor displaying the children render and composite it with the blurred bloom buffer, targeting the output
406 mCompositeTask = taskList.CreateTask();
407 mCompositeTask.SetSourceActor( mCompositeImageActor );
408 mCompositeTask.SetExclusive(true);
409 mCompositeTask.SetInputEnabled( false );
410 mCompositeTask.SetClearEnabled( true );
412 mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
413 mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
414 mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
416 mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
417 mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
418 mCompositeTask.SetTargetFrameBuffer( mOutputRenderTarget );
421 void BloomView::RemoveRenderTasks()
423 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
425 taskList.RemoveTask(mRenderChildrenTask);
426 taskList.RemoveTask(mBloomExtractTask);
428 GetImpl(mGaussianBlurView).RemoveRenderTasks();
430 taskList.RemoveTask(mCompositeTask);
433 void BloomView::OnStageDisconnection()
435 // TODO: can't call this here, since SetImage() calls fails similarly to above
436 // 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()
440 void BloomView::OnControlStageConnection()
442 // TODO: can't call this here, since SetImage() calls fail to connect images to stage, since parent chain not fully on stage yet
443 // 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()
447 void BloomView::Activate()
449 // make sure resources are allocated and start the render tasks processing
454 void BloomView::Deactivate()
456 // stop render tasks processing
457 // Note: render target resources are automatically freed since we set the Image::Unused flag
462 * EqualToConstraintFloat
464 * f(current, property) = property
466 struct EqualToConstraintFloat
468 EqualToConstraintFloat(){}
470 float operator()(const float current, const PropertyInput& property) {return property.GetFloat();}
474 * RecipOneMinusConstraint
476 * f(current, property) = property
478 struct RecipOneMinusConstraint
480 RecipOneMinusConstraint(){}
482 float operator()(const float current, const PropertyInput& property)
484 return 1.0f / (1.0f - property.GetFloat());
488 // 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
489 // internal implementation classes
490 void BloomView::SetupProperties()
492 CustomActor self = Self();
495 ///////////////////////////////////////////
498 // set defaults, makes sure properties are registered with shader
499 mBloomExtractShader.SetUniform( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
500 mBloomExtractShader.SetUniform( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
502 // Register a property that the user can control to change the bloom threshold
503 mBloomThresholdPropertyIndex = self.RegisterProperty(BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT);
504 Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
505 Constraint bloomThresholdConstraint = Constraint::New<float>(shaderBloomThresholdPropertyIndex, Source(self, mBloomThresholdPropertyIndex), EqualToConstraintFloat());
506 mBloomExtractShader.ApplyConstraint(bloomThresholdConstraint);
508 // precalc 1.0 / (1.0 - threshold) on CPU to save shader insns, using constraint to tie to the normal threshold property
509 Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
510 Constraint thresholdConstraint = Constraint::New<float>( shaderRecipOneMinusBloomThresholdPropertyIndex, LocalSource(shaderBloomThresholdPropertyIndex), RecipOneMinusConstraint());
511 mBloomExtractShader.ApplyConstraint(thresholdConstraint);
514 ////////////////////////////////////////////
517 // Register a property that the user can control to fade the blur in / out via internal GaussianBlurView object
518 mBlurStrengthPropertyIndex = self.RegisterProperty(BLOOM_BLUR_STRENGTH_PROPERTY_NAME, BLOOM_BLUR_STRENGTH_DEFAULT);
519 Constraint blurStrengthConstraint = Constraint::New<float>( mGaussianBlurView.GetBlurStrengthPropertyIndex(), Source(self, mBlurStrengthPropertyIndex), EqualToConstraintFloat());
520 mGaussianBlurView.ApplyConstraint(blurStrengthConstraint);
523 ////////////////////////////////////////////
526 // Register a property that the user can control to fade the bloom intensity via internally hidden shader
527 mBloomIntensityPropertyIndex = self.RegisterProperty(BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT);
528 mCompositeShader.SetUniform( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
529 Property::Index shaderBloomIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
530 Constraint bloomIntensityConstraint = Constraint::New<float>( shaderBloomIntensityPropertyIndex, Source(self, mBloomIntensityPropertyIndex), EqualToConstraintFloat());
531 mCompositeShader.ApplyConstraint(bloomIntensityConstraint);
534 ////////////////////////////////////////////
537 // Register a property that the user can control to fade the bloom saturation via internally hidden shader
538 mBloomSaturationPropertyIndex = self.RegisterProperty(BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT);
539 mCompositeShader.SetUniform( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
540 Property::Index shaderBloomSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
541 Constraint bloomSaturationConstraint = Constraint::New<float>( shaderBloomSaturationPropertyIndex, Source(self, mBloomSaturationPropertyIndex), EqualToConstraintFloat());
542 mCompositeShader.ApplyConstraint(bloomSaturationConstraint);
545 ////////////////////////////////////////////
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 mCompositeShader.SetUniform( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
551 Property::Index shaderImageIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
552 Constraint imageIntensityConstraint = Constraint::New<float>( shaderImageIntensityPropertyIndex, Source(self, mImageIntensityPropertyIndex), EqualToConstraintFloat());
553 mCompositeShader.ApplyConstraint(imageIntensityConstraint);
556 ////////////////////////////////////////////
559 // Register a property that the user can control to fade the image saturation via internally hidden shader
560 mImageSaturationPropertyIndex = self.RegisterProperty(IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT);
561 mCompositeShader.SetUniform( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
562 Property::Index shaderImageSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
563 Constraint imageSaturationConstraint = Constraint::New<float>( shaderImageSaturationPropertyIndex, Source(self, mImageSaturationPropertyIndex), EqualToConstraintFloat());
564 mCompositeShader.ApplyConstraint(imageSaturationConstraint);
567 } // namespace Internal
569 } // namespace Toolkit