Remove OnControl methods & add up-calls
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / bloom-view / bloom-view-impl.cpp
index dfbebc4..474a16e 100644 (file)
 // EXTERNAL INCLUDES
 #include <sstream>
 #include <iomanip>
-#include <dali/public-api/animation/active-constraint.h>
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/object/type-registry-helper.h>
 #include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/devel-api/rendering/renderer.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
-#include <dali-toolkit/public-api/controls/bloom-view/bloom-view.h>
+#include <dali-toolkit/devel-api/controls/bloom-view/bloom-view.h>
 #include "../gaussian-blur-view/gaussian-blur-view-impl.h"
 
 namespace Dali
@@ -52,7 +54,8 @@ BaseHandle Create()
   return Toolkit::BloomView::New();
 }
 
-TypeRegistration mType( typeid(Toolkit::BloomView), typeid(Toolkit::Control), Create );
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::BloomView, Toolkit::Control, Create )
+DALI_TYPE_REGISTRATION_END()
 
 // default parameters
 const float BLOOM_THRESHOLD_DEFAULT = 0.25f;
@@ -72,14 +75,15 @@ const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
 
 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
 
-const std::string BLOOM_BLUR_STRENGTH_PROPERTY_NAME( "BlurStrengthProperty" );
+const char* const BLOOM_BLUR_STRENGTH_PROPERTY_NAME = "BlurStrengthProperty";
+const char* const BLOOM_THRESHOLD_PROPERTY_NAME = "uBloomThreshold";
+const char* const RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME = "uRecipOneMinusBloomThreshold";
+const char* const BLOOM_INTENSITY_PROPERTY_NAME = "uBloomIntensity";
+const char* const BLOOM_SATURATION_PROPERTY_NAME = "uBloomSaturation";
+const char* const IMAGE_INTENSITY_PROPERTY_NAME = "uImageIntensity";
+const char* const IMAGE_SATURATION_PROPERTY_NAME = "uImageSaturation";
 
-const std::string BLOOM_THRESHOLD_PROPERTY_NAME( "uBloomThreshold" );
-const std::string RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME( "uRecipOneMinusBloomThreshold" );
-const std::string BLOOM_INTENSITY_PROPERTY_NAME( "uBloomIntensity" );
-const std::string BLOOM_SATURATION_PROPERTY_NAME( "uBloomSaturation" );
-const std::string IMAGE_INTENSITY_PROPERTY_NAME( "uImageIntensity" );
-const std::string IMAGE_SATURATION_PROPERTY_NAME( "uImageSaturation" );
+const char* const EFFECT_IMAGE_NAME( "sEffect" );
 
 ///////////////////////////////////////////////////////
 //
@@ -87,17 +91,25 @@ const std::string IMAGE_SATURATION_PROPERTY_NAME( "uImageSaturation" );
 //
 
 const char* const BLOOM_EXTRACT_FRAGMENT_SOURCE =
-  "uniform float uBloomThreshold;\n"
-  "uniform float uRecipOneMinusBloomThreshold;\n"
+  "varying mediump vec2 vTexCoord;\n"
+  "uniform sampler2D sTexture;\n"
+  "uniform lowp vec4 uColor;\n"
+  "uniform mediump float uBloomThreshold;\n"
+  "uniform mediump float uRecipOneMinusBloomThreshold;\n"
   "void main()\n"
   "{\n"
   "  mediump vec4 col;\n"
-  "  col = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y));\n"
+  "  col = texture2D(sTexture, vTexCoord);\n"
   "  col = (col - uBloomThreshold) * uRecipOneMinusBloomThreshold;\n" // remove intensities lower than the thresold and remap intensities above the threshold to [0..1]
   "  gl_FragColor = clamp(col, 0.0, 1.0);\n"
   "}\n";
 
 const char* const COMPOSITE_FRAGMENT_SOURCE =
+  "precision mediump float;\n"
+  "varying mediump vec2 vTexCoord;\n"
+  "uniform sampler2D sTexture;\n"
+  "uniform sampler2D sEffect;\n"
+  "uniform lowp vec4 uColor;\n"
   "uniform float uBloomIntensity;\n"
   "uniform float uImageIntensity;\n"
   "uniform float uBloomSaturation;\n"
@@ -113,8 +125,8 @@ const char* const COMPOSITE_FRAGMENT_SOURCE =
   "{\n"
   "  mediump vec4 image;\n"
   "  mediump vec4 bloom;\n"
-  "  image = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y));\n"
-  "  bloom = texture2D(sEffect, vec2(vTexCoord.x, vTexCoord.y));\n"
+  "  image = texture2D(sTexture, vTexCoord);\n"
+  "  bloom = texture2D(sEffect, vTexCoord);\n"
   "  image = ChangeSaturation(image, uImageSaturation) * uImageIntensity;\n"
   "  bloom = ChangeSaturation(bloom, uBloomSaturation) * uBloomIntensity;\n"
   "  image *= 1.0 - clamp(bloom, 0.0, 1.0);\n" // darken base where bloom is strong, to prevent excessive burn-out of result
@@ -126,7 +138,7 @@ const char* const COMPOSITE_FRAGMENT_SOURCE =
 
 
 BloomView::BloomView()
-  : Control( CONTROL_BEHAVIOUR_NONE )
+  : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
   , mBlurNumSamples(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES)
   , mBlurBellCurveWidth(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH)
   , mPixelFormat(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT)
@@ -137,18 +149,20 @@ BloomView::BloomView()
   , mTargetSize(Vector2::ZERO)
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
+  , mInternalRoot(Actor::New() )
   , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
   , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
   , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
   , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
   , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
+  , mActivated( false )
 {
 }
 
 BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
                                     const float downsampleWidthScale, const float downsampleHeightScale)
-  : Control( CONTROL_BEHAVIOUR_NONE )
+  : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
   , mBlurNumSamples(blurNumSamples)
   , mBlurBellCurveWidth(blurBellCurveWidth)
   , mPixelFormat(renderTargetPixelFormat)
@@ -159,12 +173,14 @@ BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCur
   , mTargetSize(Vector2::ZERO)
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
+  , mInternalRoot(Actor::New())
   , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
   , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
   , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
   , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
   , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
+  , mActivated( false )
 {
 }
 
@@ -199,24 +215,6 @@ Toolkit::BloomView BloomView::New(const unsigned int blurNumSamples, const float
   return handle;
 }
 
-/////////////////////////////////////////////////////////////
-// 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
-// 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.
-void BloomView::Add(Actor child)
-{
-  mChildrenRoot.Add(child);
-}
-
-void BloomView::Remove(Actor child)
-{
-  mChildrenRoot.Remove(child);
-}
-
-
-
-
-
-
 ///////////////////////////////////////////////////////////
 //
 // Private methods
@@ -225,72 +223,75 @@ void BloomView::Remove(Actor child)
 void BloomView::OnInitialize()
 {
   // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
-  mChildrenRoot.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-
-  //////////////////////////////////////////////////////
-  // Create shaders
-
-  // Create shader used for extracting the bright parts of an image
-  mBloomExtractShader = ShaderEffect::New( "", BLOOM_EXTRACT_FRAGMENT_SOURCE );
-
-  // Create shader used to composite bloom and original image to output render target
-  mCompositeShader = ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE );
-
+  mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
+  mInternalRoot.SetParentOrigin( ParentOrigin::CENTER );
 
   //////////////////////////////////////////////////////
   // Create actors
 
   // Create an ImageActor for rendering from the scene texture to the bloom texture
-  mBloomExtractImageActor = ImageActor::New();
-  mBloomExtractImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mBloomExtractImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
-  mBloomExtractImageActor.SetShaderEffect( mBloomExtractShader );
+  mBloomExtractImageActor = Toolkit::ImageView::New();
+  mBloomExtractImageActor.SetParentOrigin( ParentOrigin::CENTER );
+
+  // Create shader used for extracting the bright parts of an image
+  Property::Map customShader;
+  customShader[ "fragmentShader" ] = BLOOM_EXTRACT_FRAGMENT_SOURCE;
+  Property::Map rendererMap;
+  rendererMap.Insert( "rendererType", "image" );
+  rendererMap.Insert( "shader", customShader );
+  mBloomExtractImageActor.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
 
   // Create an ImageActor for compositing the result (scene and bloom textures) to output
-  mCompositeImageActor = ImageActor::New();
-  mCompositeImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mCompositeImageActor.SetShaderEffect( mCompositeShader );
-  mCompositeImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
+  mCompositeImageActor = Toolkit::ImageView::New();
+  mCompositeImageActor.SetParentOrigin( ParentOrigin::CENTER );
 
-  // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
-  mTargetImageActor = ImageActor::New();
-  mTargetImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mTargetImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
+  // Create shader used to composite bloom and original image to output render target
+  customShader[ "fragmentShader" ] = COMPOSITE_FRAGMENT_SOURCE;
+  rendererMap[ "shader" ] = customShader;
+  mCompositeImageActor.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
 
+  // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
+  mTargetImageActor = Toolkit::ImageView::New();
+  mTargetImageActor.SetParentOrigin( ParentOrigin::CENTER );
 
   // Create the Gaussian Blur object + render tasks
   // 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
   // render targets etc internally, so we make better use of resources
   // Note, this also internally creates the render tasks used by the Gaussian blur, this must occur after the bloom extraction and before the compositing
   mGaussianBlurView = Dali::Toolkit::GaussianBlurView::New(mBlurNumSamples, mBlurBellCurveWidth, mPixelFormat, mDownsampleWidthScale, mDownsampleHeightScale, true);
-  mGaussianBlurView.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+  mGaussianBlurView.SetParentOrigin( ParentOrigin::CENTER );
 
 
   //////////////////////////////////////////////////////
   // Create cameras for the renders corresponding to the (potentially downsampled) render targets' size
   mRenderDownsampledCamera = CameraActor::New();
   mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
+  mRenderDownsampledCamera.SetInvertYAxis( true );
 
   mRenderFullSizeCamera = CameraActor::New();
   mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
+  mRenderFullSizeCamera.SetInvertYAxis( true );
 
 
   ////////////////////////////////
   // Connect to actor tree
   Self().Add( mChildrenRoot );
-  Self().Add( mBloomExtractImageActor );
-  Self().Add( mGaussianBlurView );
-  Self().Add( mCompositeImageActor );
-  Self().Add( mTargetImageActor );
-  Self().Add( mRenderDownsampledCamera );
-  Self().Add( mRenderFullSizeCamera );
+  Self().Add( mInternalRoot );
+  mInternalRoot.Add( mBloomExtractImageActor );
+  mInternalRoot.Add( mGaussianBlurView );
+  mInternalRoot.Add( mCompositeImageActor );
+  mInternalRoot.Add( mTargetImageActor );
+  mInternalRoot.Add( mRenderDownsampledCamera );
+  mInternalRoot.Add( mRenderFullSizeCamera );
 
   // bind properties for / set shader constants to defaults
   SetupProperties();
 }
 
-void BloomView::OnControlSizeSet(const Vector3& targetSize)
+void BloomView::OnSizeSet(const Vector3& targetSize)
 {
+  Control::OnSizeSet( targetSize );
+
   mTargetSize = Vector2(targetSize);
   mChildrenRoot.SetSize(targetSize);
   mCompositeImageActor.SetSize(targetSize);
@@ -306,17 +307,35 @@ void BloomView::OnControlSizeSet(const Vector3& targetSize)
   float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
   mRenderFullSizeCamera.SetZ( mTargetSize.height * cameraPosConstraintScale);
 
-  // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
-  if(Self().OnStage())
+  // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
+  if(mActivated)
+  {
+    Deactivate();
+    Activate();
+  }
+}
+
+void BloomView::OnChildAdd( Actor& child )
+{
+  Control::OnChildAdd( child );
+
+  if( child != mChildrenRoot && child != mInternalRoot)
   {
-    AllocateResources();
+    mChildrenRoot.Add( child );
   }
 }
 
+void BloomView::OnChildRemove( Actor& child )
+{
+  mChildrenRoot.Remove( child );
+
+  Control::OnChildRemove( child );
+}
+
 void BloomView::AllocateResources()
 {
   // size of render targets etc is based on the size of this actor, ignoring z
-  if(mTargetSize != mLastSize)
+  if(mTargetSize != mLastSize || !mActivated)
   {
     mLastSize = mTargetSize;
 
@@ -334,7 +353,6 @@ void BloomView::AllocateResources()
     mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
     mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
     mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
-    mRenderDownsampledCamera.SetRotation(Quaternion(M_PI, Vector3::YAXIS)); // Rotate to look at origin
 
     mRenderDownsampledCamera.SetPosition(0.0f, 0.0f, ((mDownsampledHeight * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
 
@@ -344,7 +362,6 @@ void BloomView::AllocateResources()
     mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
     mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
     mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
-    mRenderFullSizeCamera.SetRotation(Quaternion(M_PI, Vector3::YAXIS)); // Rotate to look at origin
 
     float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
     mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
@@ -361,6 +378,7 @@ void BloomView::AllocateResources()
     // create off screen buffer of new size to render our child actors to
     mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
     mBloomExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
+    FrameBufferImage mBlurExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
     mOutputRenderTarget = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED);
 
 
@@ -371,11 +389,20 @@ void BloomView::AllocateResources()
     mBloomExtractImageActor.SetSize(mDownsampledWidth, mDownsampledHeight); // size needs to match render target
 
     // set GaussianBlurView to blur our extracted bloom
-    mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBloomExtractTarget);
+    mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBlurExtractTarget);
 
     // use the completed blur in the first buffer and composite with the original child actors render
     mCompositeImageActor.SetImage( mRenderTargetForRenderingChildren );
-    mCompositeShader.SetEffectImage( mBloomExtractTarget );
+    Material material = mCompositeImageActor.GetRendererAt(0).GetMaterial();
+    int textureIndex = material.GetTextureIndex( EFFECT_IMAGE_NAME );
+    if( textureIndex == -1 )
+    {
+      material.AddTexture( mBlurExtractTarget, EFFECT_IMAGE_NAME );
+    }
+    else
+    {
+      material.SetTextureImage( textureIndex, mBlurExtractTarget );
+    }
 
     // set up target actor for rendering result, i.e. the blurred image
     mTargetImageActor.SetImage(mOutputRenderTarget);
@@ -392,6 +419,8 @@ void BloomView::CreateRenderTasks()
   mRenderChildrenTask.SetExclusive(true);
   mRenderChildrenTask.SetInputEnabled( false );
   mRenderChildrenTask.SetClearEnabled( true );
+  mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
+  mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
 
   // 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.
   mBloomExtractTask = taskList.CreateTask();
@@ -399,6 +428,8 @@ void BloomView::CreateRenderTasks()
   mBloomExtractTask.SetExclusive(true);
   mBloomExtractTask.SetInputEnabled( false );
   mBloomExtractTask.SetClearEnabled( true );
+  mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
+  mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
 
   // GaussianBlurView tasks must be created here, so they are executed in the correct order with respect to BloomView tasks
   GetImpl(mGaussianBlurView).CreateRenderTasks();
@@ -409,13 +440,7 @@ void BloomView::CreateRenderTasks()
   mCompositeTask.SetExclusive(true);
   mCompositeTask.SetInputEnabled( false );
   mCompositeTask.SetClearEnabled( true );
-
-  mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
-  mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
   mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
-
-  mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
-  mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
   mCompositeTask.SetTargetFrameBuffer( mOutputRenderTarget );
 }
 
@@ -431,25 +456,12 @@ void BloomView::RemoveRenderTasks()
   taskList.RemoveTask(mCompositeTask);
 }
 
-void BloomView::OnStageDisconnection()
-{
-  // TODO: can't call this here, since SetImage() calls fails similarly to above
-  // 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()
-  //Deactivate();
-}
-
-void BloomView::OnControlStageConnection()
-{
-  // TODO: can't call this here, since SetImage() calls fail to connect images to stage, since parent chain not fully on stage yet
-  // 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()
-  //Activate();
-}
-
 void BloomView::Activate()
 {
   // make sure resources are allocated and start the render tasks processing
   AllocateResources();
   CreateRenderTasks();
+  mActivated = true;
 }
 
 void BloomView::Deactivate()
@@ -457,21 +469,13 @@ void BloomView::Deactivate()
   // stop render tasks processing
   // Note: render target resources are automatically freed since we set the Image::Unused flag
   RemoveRenderTasks();
+  mRenderTargetForRenderingChildren.Reset();
+  mBloomExtractTarget.Reset();
+  mOutputRenderTarget.Reset();
+  mActivated = false;
 }
 
 /**
- * EqualToConstraintFloat
- *
- * f(current, property) = property
- */
-struct EqualToConstraintFloat
-{
-  EqualToConstraintFloat(){}
-
-  float operator()(const float current, const PropertyInput& property) {return property.GetFloat();}
-};
-
-/**
  * RecipOneMinusConstraint
  *
  * f(current, property) = property
@@ -480,9 +484,9 @@ struct RecipOneMinusConstraint
 {
   RecipOneMinusConstraint(){}
 
-  float operator()(const float current, const PropertyInput& property)
+  void operator()( float& current, const PropertyInputContainer& inputs )
   {
-    return 1.0f / (1.0f - property.GetFloat());
+    current = 1.0f / ( 1.0f - inputs[0]->GetFloat() );
   }
 };
 
@@ -497,19 +501,21 @@ void BloomView::SetupProperties()
   // bloom threshold
 
   // set defaults, makes sure properties are registered with shader
-  mBloomExtractShader.SetUniform( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
-  mBloomExtractShader.SetUniform( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
+  mBloomExtractImageActor.RegisterProperty( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
+  mBloomExtractImageActor.RegisterProperty( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
 
   // Register a property that the user can control to change the bloom threshold
   mBloomThresholdPropertyIndex = self.RegisterProperty(BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT);
-  Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
-  Constraint bloomThresholdConstraint = Constraint::New<float>(shaderBloomThresholdPropertyIndex, Source(self, mBloomThresholdPropertyIndex), EqualToConstraintFloat());
-  mBloomExtractShader.ApplyConstraint(bloomThresholdConstraint);
+  Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractImageActor.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
+  Constraint bloomThresholdConstraint = Constraint::New<float>( mBloomExtractImageActor, shaderBloomThresholdPropertyIndex, EqualToConstraint());
+  bloomThresholdConstraint.AddSource( Source(self, mBloomThresholdPropertyIndex) );
+  bloomThresholdConstraint.Apply();
 
   // precalc 1.0 / (1.0 - threshold) on CPU to save shader insns, using constraint to tie to the normal threshold property
-  Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
-  Constraint thresholdConstraint = Constraint::New<float>( shaderRecipOneMinusBloomThresholdPropertyIndex, LocalSource(shaderBloomThresholdPropertyIndex), RecipOneMinusConstraint());
-  mBloomExtractShader.ApplyConstraint(thresholdConstraint);
+  Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractImageActor.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
+  Constraint thresholdConstraint = Constraint::New<float>( mBloomExtractImageActor, shaderRecipOneMinusBloomThresholdPropertyIndex, RecipOneMinusConstraint());
+  thresholdConstraint.AddSource( LocalSource(shaderBloomThresholdPropertyIndex) );
+  thresholdConstraint.Apply();
 
 
   ////////////////////////////////////////////
@@ -517,8 +523,9 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the blur in / out via internal GaussianBlurView object
   mBlurStrengthPropertyIndex = self.RegisterProperty(BLOOM_BLUR_STRENGTH_PROPERTY_NAME, BLOOM_BLUR_STRENGTH_DEFAULT);
-  Constraint blurStrengthConstraint = Constraint::New<float>( mGaussianBlurView.GetBlurStrengthPropertyIndex(), Source(self, mBlurStrengthPropertyIndex), EqualToConstraintFloat());
-  mGaussianBlurView.ApplyConstraint(blurStrengthConstraint);
+  Constraint blurStrengthConstraint = Constraint::New<float>( mGaussianBlurView, mGaussianBlurView.GetBlurStrengthPropertyIndex(), EqualToConstraint());
+  blurStrengthConstraint.AddSource( Source(self, mBlurStrengthPropertyIndex) );
+  blurStrengthConstraint.Apply();
 
 
   ////////////////////////////////////////////
@@ -526,10 +533,11 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the bloom intensity via internally hidden shader
   mBloomIntensityPropertyIndex = self.RegisterProperty(BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT);
-  mCompositeShader.SetUniform( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
-  Property::Index shaderBloomIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
-  Constraint bloomIntensityConstraint = Constraint::New<float>( shaderBloomIntensityPropertyIndex, Source(self, mBloomIntensityPropertyIndex), EqualToConstraintFloat());
-  mCompositeShader.ApplyConstraint(bloomIntensityConstraint);
+  mCompositeImageActor.RegisterProperty( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
+  Property::Index shaderBloomIntensityPropertyIndex = mCompositeImageActor.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
+  Constraint bloomIntensityConstraint = Constraint::New<float>( mCompositeImageActor, shaderBloomIntensityPropertyIndex, EqualToConstraint());
+  bloomIntensityConstraint.AddSource( Source(self, mBloomIntensityPropertyIndex) );
+  bloomIntensityConstraint.Apply();
 
 
   ////////////////////////////////////////////
@@ -537,10 +545,11 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the bloom saturation via internally hidden shader
   mBloomSaturationPropertyIndex = self.RegisterProperty(BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT);
-  mCompositeShader.SetUniform( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
-  Property::Index shaderBloomSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
-  Constraint bloomSaturationConstraint = Constraint::New<float>( shaderBloomSaturationPropertyIndex, Source(self, mBloomSaturationPropertyIndex), EqualToConstraintFloat());
-  mCompositeShader.ApplyConstraint(bloomSaturationConstraint);
+  mCompositeImageActor.RegisterProperty( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
+  Property::Index shaderBloomSaturationPropertyIndex = mCompositeImageActor.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
+  Constraint bloomSaturationConstraint = Constraint::New<float>( mCompositeImageActor, shaderBloomSaturationPropertyIndex, EqualToConstraint());
+  bloomSaturationConstraint.AddSource( Source(self, mBloomSaturationPropertyIndex) );
+  bloomSaturationConstraint.Apply();
 
 
   ////////////////////////////////////////////
@@ -548,10 +557,11 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the image intensity via internally hidden shader
   mImageIntensityPropertyIndex = self.RegisterProperty(IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT);
-  mCompositeShader.SetUniform( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
-  Property::Index shaderImageIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
-  Constraint imageIntensityConstraint = Constraint::New<float>( shaderImageIntensityPropertyIndex, Source(self, mImageIntensityPropertyIndex), EqualToConstraintFloat());
-  mCompositeShader.ApplyConstraint(imageIntensityConstraint);
+  mCompositeImageActor.RegisterProperty( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
+  Property::Index shaderImageIntensityPropertyIndex = mCompositeImageActor.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
+  Constraint imageIntensityConstraint = Constraint::New<float>( mCompositeImageActor, shaderImageIntensityPropertyIndex, EqualToConstraint());
+  imageIntensityConstraint.AddSource( Source(self, mImageIntensityPropertyIndex) );
+  imageIntensityConstraint.Apply();
 
 
   ////////////////////////////////////////////
@@ -559,10 +569,11 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the image saturation via internally hidden shader
   mImageSaturationPropertyIndex = self.RegisterProperty(IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT);
-  mCompositeShader.SetUniform( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
-  Property::Index shaderImageSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
-  Constraint imageSaturationConstraint = Constraint::New<float>( shaderImageSaturationPropertyIndex, Source(self, mImageSaturationPropertyIndex), EqualToConstraintFloat());
-  mCompositeShader.ApplyConstraint(imageSaturationConstraint);
+  mCompositeImageActor.RegisterProperty( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
+  Property::Index shaderImageSaturationPropertyIndex = mCompositeImageActor.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
+  Constraint imageSaturationConstraint = Constraint::New<float>( mCompositeImageActor, shaderImageSaturationPropertyIndex, EqualToConstraint());
+  imageSaturationConstraint.AddSource( Source(self, mImageSaturationPropertyIndex) );
+  imageSaturationConstraint.Apply();
 }
 
 } // namespace Internal