X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fbubble-effect%2Fbubble-emitter-impl.cpp;h=5ee90472c022397e815dbc6cfb1cdd55083a99ba;hp=4ff070b136a1c5d64ee7b32cdc25e96c3ea79d1a;hb=b1e8521ad77e7b4e62b59613b2edef64429130e9;hpb=daa91492858a758d4ac0cfb8a11e05e5b00e849b diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp index 4ff070b..5ee9047 100644 --- a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,39 +21,123 @@ // EXTERNAL INCLUDES #include #include -#include +#include +#include // INTERNAL INCLUDES -#include -#include -#include #include +#include namespace { struct Vertex { - float index; - Dali::Vector2 position; - Dali::Vector2 textureCoord; - Vertex() - {} + : index( 0.0f ), position(), textureCoord() + { + } Vertex( float index, const Dali::Vector2& position, const Dali::Vector2& textureCoord ) : index( index ), position( position ), textureCoord( textureCoord ) - {} + { + } + + float index; + Dali::Vector2 position; + Dali::Vector2 textureCoord; }; /** * Return a random value between the given interval. * @param[in] f0 The low bound * @param[in] f1 The up bound + * @param[in] seed The seed to genergate random number * @return A random value between the given interval */ -float RandomRange(float f0, float f1) +float RandomRange(float f0, float f1, unsigned int& seed) +{ + return f0 + (rand_r( &seed ) & 0xfff) * (f1-f0) * (1.0f/4095.0f); +} + +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + attribute mediump vec2 aTexCoord;\n + uniform mediump vec3 uSize;\n + uniform mediump mat4 uMvpMatrix;\n + varying mediump vec2 vTexCoord;\n + \n + + void main()\n + {\n + gl_Position = uMvpMatrix * vec4(aPosition*uSize.xy,0.0,1.0); + vTexCoord = aTexCoord;\n + }\n +); + +const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( + precision highp float;\n + uniform vec3 uHSVDelta;\n + varying mediump vec2 vTexCoord;\n + uniform sampler2D sTexture;\n + float rand(vec2 co) \n + {\n + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n} + \n + vec3 rgb2hsv(vec3 c)\n + {\n + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n + \n + float d = q.x - min(q.w, q.y);\n + float e = 1.0e-10;\n + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n + }\n + vec3 hsv2rgb(vec3 c)\n + {\n + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n + }\n + void main() {\n + vec4 color = texture2D(sTexture, vTexCoord); \n + vec3 hsvColor = rgb2hsv( color.rgb );\n + // modify the hsv Value + hsvColor += uHSVDelta * rand(vTexCoord); \n + // if the new vale exceeds one, then decrease it + hsvColor -= max(hsvColor*2.0 - vec3(2.0), 0.0);\n + // if the new vale drops below zero, then increase it + hsvColor -= min(hsvColor*2.0, 0.0);\n + color = vec4( hsv2rgb( hsvColor ), 1.0 ); \n + gl_FragColor = color; \n + }\n + ); + +Dali::Geometry CreateTexturedQuad() { - return f0 + (rand() & 0xfff) * (f1-f0) * (1.0f/4095.0f); + struct Vertex + { + Dali::Vector2 position; + Dali::Vector2 texCoord; + }; + + static const Vertex data[] = {{ Dali::Vector2( -0.5f, -0.5f ), Dali::Vector2( 0.0f, 0.0f ) }, + { Dali::Vector2( 0.5f, -0.5f ), Dali::Vector2( 1.0f, 0.0f ) }, + { Dali::Vector2( -0.5f, 0.5f ), Dali::Vector2( 0.0f, 1.0f ) }, + { Dali::Vector2( 0.5f, 0.5f ), Dali::Vector2( 1.0f, 1.0f ) }}; + + // Create a vertex buffer for vertex positions and texture coordinates + Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New( Dali::Property::Map() + .Add( "aPosition", Dali::Property::VECTOR2 ) + .Add( "aTexCoord", Dali::Property::VECTOR2 ) ); + vertexBuffer.SetData( data, 4u ); + + //Create the geometry + Dali::Geometry geometry = Dali::Geometry::New(); + geometry.AddVertexBuffer( vertexBuffer ); + geometry.SetType(Dali::Geometry::TRIANGLE_STRIP ); + + return geometry; } } @@ -67,35 +151,38 @@ namespace Toolkit namespace Internal { BubbleEmitter::BubbleEmitter( const Vector2& movementArea, - Image shapeImage, + Texture shapeTexture, unsigned int maximumNumberOfBubble, const Vector2& bubbleSizeRange ) -: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ), - mShapeImage( shapeImage ), +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), + mShapeTexture( shapeTexture ), mMovementArea( movementArea ), mBubbleSizeRange( bubbleSizeRange ), mDensity( 5 ), mTotalNumOfBubble( maximumNumberOfBubble ), mCurrentBubble( 0 ), + mRandomSeed( 0 ), mRenderTaskRunning(false) { // Calculate how many shaders are required if( mTotalNumOfBubble>100 ) { - mNumBubblePerActor = 100; - mNumActor = mTotalNumOfBubble / 100; - if( mNumActor*mNumBubblePerActor < mTotalNumOfBubble ) + mNumBubblePerRenderer = 100; + mNumRenderer = mTotalNumOfBubble / 100; + if( mNumRenderer*mNumBubblePerRenderer < mTotalNumOfBubble ) { - mNumActor++; - mNumBubblePerActor = mTotalNumOfBubble / mNumActor+1; - mTotalNumOfBubble = mNumActor * mNumBubblePerActor; + mNumRenderer++; + mNumBubblePerRenderer = mTotalNumOfBubble / mNumRenderer+1; + mTotalNumOfBubble = mNumRenderer * mNumBubblePerRenderer; } } else { - mNumBubblePerActor = mTotalNumOfBubble; - mNumActor = 1; + mNumBubblePerRenderer = mTotalNumOfBubble; + mNumRenderer = 1; } + + mRandomSeed = time( NULL ); } BubbleEmitter::~BubbleEmitter() @@ -103,12 +190,12 @@ BubbleEmitter::~BubbleEmitter() } Toolkit::BubbleEmitter BubbleEmitter::New( const Vector2& winSize, - Image shapeImage, + Texture shapeTexture, unsigned int maximumNumberOfBubble, const Vector2& bubbleSizeRange ) { // Create the implementation - IntrusivePtr internalBubbleEmitter ( new BubbleEmitter( winSize, shapeImage, + IntrusivePtr internalBubbleEmitter ( new BubbleEmitter( winSize, shapeTexture, maximumNumberOfBubble,bubbleSizeRange ) ); // Pass ownership to Toolkit::BubbleEmitter handle @@ -124,35 +211,34 @@ void BubbleEmitter::OnInitialize() { // Create the root actor, all the meshActor should be its children mBubbleRoot = Actor::New(); - mBubbleRoot.SetSize(mMovementArea); - - // Prepare the frame buffer to store the color adjusted background image - mEffectImage = FrameBufferImage::New( mMovementArea.width/4.f, mMovementArea.height/4.f, Pixel::RGBA8888, Dali::Image::UNUSED ); + mBubbleRoot.SetProperty( Actor::Property::SIZE, mMovementArea ); - // Generate the samplers and geometry, which is used by all bubbleActors - mSamplerBackground = Sampler::New( mEffectImage, "sBackground" ); - mSamplerBubbleShape = Sampler::New( mShapeImage, "sBubbleShape" ); - mMeshGeometry = CreateGeometry( mNumBubblePerActor*mDensity ); + // Prepare the frame buffer to store the color adjusted background texture + Vector2 imageSize = Vector2( mMovementArea.width/4.f, mMovementArea.height/4.f ); + mFrameBuffer = FrameBuffer::New( imageSize.x, imageSize.y, FrameBuffer::Attachment::NONE ); + mEffectTexture = Texture::New( TextureType::TEXTURE_2D, Pixel::RGBA8888, imageSize.x, imageSize.y ); + mFrameBuffer.AttachColorTexture( mEffectTexture ); - Shader bubbleShader = CreateBubbleShader (mNumBubblePerActor ); + // Generate the geometry, which is used by all bubbleActors + mMeshGeometry = CreateGeometry( mNumBubblePerRenderer*mDensity ); - mMaterial = Material::New( bubbleShader ); - mMaterial.AddSampler( mSamplerBackground ); - mMaterial.AddSampler( mSamplerBubbleShape ); + Shader bubbleShader = CreateBubbleShader( mNumBubblePerRenderer ); - mBubbleActors.resize( mNumActor ); + mTextureSet = TextureSet::New(); + mTextureSet.SetTexture( 0u, mEffectTexture ); + mTextureSet.SetTexture( 1u, mShapeTexture ); - // Create the meshActor group and bubbleEffect group to emit bubbles following the given track, such as finger touch track. - for(unsigned int i=0; i < mNumActor; i++ ) + // Create the renderers to render the bubbles + mBubbleRenderers.resize( mNumRenderer ); + for(unsigned int i=0; i < mNumRenderer; i++ ) { - mBubbleActors[i] = new BubbleActor( mNumBubblePerActor, mMovementArea ); - (mBubbleActors[i])->MakeRenderable( mMeshGeometry, mMaterial ); - mBubbleRoot.Add( (mBubbleActors[i])->GetMeshActor() ); + mBubbleRenderers[i].Initialize( mNumBubblePerRenderer, mMovementArea, mMeshGeometry, mTextureSet, bubbleShader ); + mBubbleRoot.AddRenderer( mBubbleRenderers[i].GetRenderer() ); } // Create a cameraActor for the off screen render task. mCameraActor = CameraActor::New(mMovementArea); - mCameraActor.SetParentOrigin(ParentOrigin::CENTER); + mCameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); Stage stage = Stage::GetCurrent(); @@ -165,18 +251,26 @@ Actor BubbleEmitter::GetRootActor() return mBubbleRoot; } -void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta ) +void BubbleEmitter::SetBackground( Texture bgTexture, const Vector3& hsvDelta ) { - mBackgroundImage = bgImage; + mBackgroundTexture = bgTexture; mHSVDelta = hsvDelta; - ImageActor sourceActor = ImageActor::New( bgImage ); - sourceActor.SetSize( mMovementArea ); - sourceActor.SetParentOrigin(ParentOrigin::CENTER); + //Create RenderTask source actor + Actor sourceActor = Actor::New(); + sourceActor.SetProperty( Actor::Property::SIZE, mMovementArea ); + sourceActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + sourceActor.RegisterProperty( "uHSVDelta", hsvDelta ); Stage::GetCurrent().Add( sourceActor ); - ShaderEffect colorAdjuster = CreateColorAdjuster( hsvDelta, true /*ignore alpha to make bubble color always*/ ); - sourceActor.SetShaderEffect( colorAdjuster ); + //Create renderer + Dali::Geometry geometry = CreateTexturedQuad(); + Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); + Renderer renderer = Renderer::New( geometry, shader ); + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture(0u, bgTexture ); + renderer.SetTextures( textureSet ); + sourceActor.AddRenderer( renderer ); RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); RenderTask task = taskList.CreateTask(); @@ -185,21 +279,21 @@ void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta ) task.SetExclusive(true); task.SetCameraActor(mCameraActor); task.GetCameraActor().SetInvertYAxis(true); - task.SetTargetFrameBuffer( mEffectImage ); + task.SetFrameBuffer( mFrameBuffer ); task.FinishedSignal().Connect(this, &BubbleEmitter::OnRenderFinished); mRenderTaskRunning = true; } -void BubbleEmitter::SetShapeImage( Image shapeImage ) +void BubbleEmitter::SetBubbleShape( Texture shapeTexture ) { - mSamplerBubbleShape.SetImage( shapeImage ); + mTextureSet.SetTexture( 1, shapeTexture ); } void BubbleEmitter::SetBubbleScale( float scale ) { - for(unsigned int i=0; i < mNumActor; i++ ) + for(unsigned int i=0; i < mNumRenderer; i++ ) { - (mBubbleActors[i])->SetDynamicScale( scale ); + mBubbleRenderers[i].SetDynamicScale( scale ); } } @@ -214,44 +308,19 @@ void BubbleEmitter::SetBubbleDensity( unsigned int density ) else { mDensity = density; - mMeshGeometry = CreateGeometry( mNumBubblePerActor*mDensity ); - for(unsigned int i=0; i < mNumActor; i++ ) + mMeshGeometry = CreateGeometry( mNumBubblePerRenderer*mDensity ); + for(unsigned int i=0; i < mNumRenderer; i++ ) { - (mBubbleActors[i])->SetGeometry( mMeshGeometry ); + mBubbleRenderers[i].SetGeometry( mMeshGeometry ); } } } -void BubbleEmitter::SetBlendMode( bool enable ) -{ - if(enable) - { - // linear overlay - mMaterial.SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE, - BlendingFactor::ZERO, BlendingFactor::ONE); - } - else - { - // using default blend func - mMaterial.SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA, - BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA ); - } -} - // clear the resources created for the off screen rendering void BubbleEmitter::OnRenderFinished(RenderTask& source) { mRenderTaskRunning = false; Actor sourceActor = source.GetSourceActor(); - if( sourceActor ) - { - ImageActor renderable = ImageActor::DownCast( sourceActor ); - if( renderable ) - { - renderable.RemoveShaderEffect(); - } - } - Stage stage = Stage::GetCurrent(); stage.Remove(sourceActor); stage.GetRenderTaskList().RemoveTask(source); @@ -263,16 +332,16 @@ void BubbleEmitter::OnContextRegained() // and trigger re-draw if not already running if( ! mRenderTaskRunning ) { - SetBackground( mBackgroundImage, mHSVDelta ); + SetBackground( mBackgroundTexture, mHSVDelta ); } } void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) { - unsigned int curUniform = mCurrentBubble % mNumBubblePerActor; - unsigned int groupIdx = mCurrentBubble / mNumBubblePerActor; - SetBubbleParameter( mBubbleActors[groupIdx], curUniform, emitPosition, direction, displacement); - animation.AnimateTo( (mBubbleActors[groupIdx])->GetPercentageProperty(curUniform), + unsigned int curUniform = mCurrentBubble % mNumBubblePerRenderer; + unsigned int groupIdx = mCurrentBubble / mNumBubblePerRenderer; + SetBubbleParameter( mBubbleRenderers[groupIdx], curUniform, emitPosition - Vector2(mMovementArea.x*0.5f,mMovementArea.y*0.5f), direction, displacement); + animation.AnimateTo( mBubbleRenderers[groupIdx].GetPercentageProperty(curUniform), 1.f, AlphaFunction::LINEAR ); mCurrentBubble = (mCurrentBubble + 1) % mTotalNumOfBubble; @@ -280,33 +349,33 @@ void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPositio void BubbleEmitter::Restore() { - for(unsigned int i=0; i < mNumActor; i++ ) + for(unsigned int i=0; i < mNumRenderer; i++ ) { - (mBubbleActors[i])->ResetProperties(); + mBubbleRenderers[i].ResetProperties(); } } Geometry BubbleEmitter::CreateGeometry( unsigned int numOfPatch ) { unsigned int numVertex = numOfPatch*4u; - std::vector vertexData; - vertexData.reserve( numVertex ); + Vector vertexData; + vertexData.Reserve( numVertex ); unsigned int numIndex = numOfPatch*6u; - Vector indexData; + Vector indexData; indexData.Reserve( numIndex ); for(unsigned int i = 0; i < numOfPatch; i++) { - float curSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y); + float halfSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y, mRandomSeed) * 0.5f; float index = static_cast( i ); - vertexData.push_back( Vertex( index, Vector2(0.f,0.f), Vector2(0.f,0.f) ) ); - vertexData.push_back( Vertex( index, Vector2(0.f,curSize), Vector2(0.f,1.f) ) ); - vertexData.push_back( Vertex( index, Vector2(curSize,curSize), Vector2(1.f,1.f) ) ); - vertexData.push_back( Vertex( index, Vector2(curSize,0.f), Vector2(1.f,0.f) ) ); + vertexData.PushBack( Vertex( index, Vector2(-halfSize,-halfSize),Vector2(0.f,0.f) ) ); + vertexData.PushBack( Vertex( index, Vector2(-halfSize, halfSize), Vector2(0.f,1.f) ) ); + vertexData.PushBack( Vertex( index, Vector2( halfSize, halfSize), Vector2(1.f,1.f) ) ); + vertexData.PushBack( Vertex( index, Vector2( halfSize,-halfSize), Vector2(1.f,0.f) ) ); - unsigned int idx = index * 4; + unsigned short idx = index * 4; indexData.PushBack( idx ); indexData.PushBack( idx+1 ); indexData.PushBack( idx+2 ); @@ -319,29 +388,24 @@ Geometry BubbleEmitter::CreateGeometry( unsigned int numOfPatch ) vertexFormat["aIndex"] = Property::FLOAT; vertexFormat["aPosition"] = Property::VECTOR2; vertexFormat["aTexCoord"] = Property::VECTOR2; - PropertyBuffer vertices = PropertyBuffer::New( vertexFormat, numVertex ); - vertices.SetData( &vertexData[0] ); - - Property::Map indexFormat; - indexFormat["indices"] = Property::UNSIGNED_INTEGER; - PropertyBuffer indices = PropertyBuffer::New( indexFormat, numIndex ); - indices.SetData( &indexData[0] ); + VertexBuffer vertices = VertexBuffer::New( vertexFormat ); + vertices.SetData( &vertexData[0], numVertex ); Geometry geometry = Geometry::New(); geometry.AddVertexBuffer( vertices ); - geometry.SetIndexBuffer( indices ); + geometry.SetIndexBuffer( &indexData[0], numIndex ); return geometry; } -void BubbleEmitter::SetBubbleParameter( BubbleActorPtr bubbleActor, unsigned int curUniform, +void BubbleEmitter::SetBubbleParameter( BubbleRenderer& bubbleRenderer, unsigned int curUniform, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) { Vector2 dir(direction); int halfRange = displacement.x / 2; // for the y coordinate, always negative, so bubbles always go upwards - Vector2 randomVec(rand()%static_cast(displacement.x) - halfRange, -rand()%static_cast(displacement.y)); + Vector2 randomVec( rand_r( &mRandomSeed ) % static_cast(displacement.x) - halfRange, -rand_r( &mRandomSeed ) % static_cast(displacement.y) ); dir.Normalize(); randomVec.x -= dir.x*halfRange; randomVec.y *= 1.0f - fabsf(dir.x)*0.33f; @@ -351,9 +415,9 @@ void BubbleEmitter::SetBubbleParameter( BubbleActorPtr bubbleActor, unsigned int randomVec.y *= 0.33f; } Vector4 startAndEndPos( emitPosition.x, emitPosition.y, emitPosition.x+randomVec.x, emitPosition.y+randomVec.y ); - bubbleActor->SetStartAndEndPosition( curUniform, startAndEndPos ); + bubbleRenderer.SetStartAndEndPosition( curUniform, startAndEndPos ); - bubbleActor->SetPercentage( curUniform, 0.f); + bubbleRenderer.SetPercentage( curUniform, 0.f); } } // namespace Internal