1 #ifndef __DALI_TOOLKIT_SHADER_EFFECT_DISPLACEMENT_H__
2 #define __DALI_TOOLKIT_SHADER_EFFECT_DISPLACEMENT_H__
5 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 #include <dali/public-api/shader-effects/shader-effect.h>
31 * @brief Creates a new displacement effect
33 * Two state displacement effect shader that works on a per object basis. By passing a height-normal map as an effect image, the user can create
34 * various styles of buttons on an image actor. The shader requires two height-normal maps in one image, one for each state.
36 * The normals and height information for the two states of the button should be strictly specified in this format:
40 * | | --> Unpressed button normals in rgb and height in a
45 * | | --> Pressed button normals in rgb and height in a
49 * The RGB values should contain the surface normals and the alpha should contian the height map. For a better effect keep the highest point (alpha value) in
50 * the combined map as 1.0 and the lowest posint as 0.0 and 0.5 for any region which doesn't need displacement.
52 * For the supplied Normal map the Y-Axis should be down, Meaning (0,0) is in the top left. As the shader inverts the Y axis for lighting calculation.
54 * Limitations: Can be applied to ImageActor only, And doesn't provide support for specular color.
58 * // Create shader used for doing soft button\n
59 * ShaderEffect buttonEffect = CreateDisplacementEffect();
60 * buttonEffect.SetEffectImage(Image::New( FANCY_BUTTON_HEIGHT_MAP_IMAGE_PATH ););
62 * // set shader to the soft button\n
63 * ImageActor fancyButton = ImageActor::New( ... );\n
64 * fancyButton.SetShaderEffect( buttonEffect );
66 * // animate a button push, using e.g. AlphaFunction::BOUNCE. With these values the button pushes in and out (animates to and fro between the two states)
69 * Animation animation = Animation::New( ... );\n
70 * animation.AnimateTo( Property(buttonEffect, "uState"), 1.0f, AlphaFunction::BOUNCE, ... );\n
73 * Animatable/Constrainable uniforms:
74 * "uLightDirection" - The light direction is used in the lighting calculation. The angle of incidence directly affects the amount of light reflected.
75 * Default (0.0f, 0.7070168f, 0.7071068f), i.e angled at the surface from in front and above.
76 * "uAmbientLightColor" - The ambient light is used in the lighting calculation. Care must be taken to not saturate the image by setting this value too high,
77 * or the indentation will not look correct. Default 0.15.
78 * "uDiffuseLightColor" - The diffuse light is used in the lighting calculation. Default is (1.0f, 1.0f, 1.0f).
79 * "uLightMultiplier" - The ambient and diffuse lighting is multiplied by this factor. Since a diffuse light at an angle will cause the whole image to darken,
80 * this property can be used to scale the image back up closer to the pixel values of the original diffuse texture. Care must be taken
81 * to not saturate the image,or the indentation will not look correct. Default 1.0
82 * "uState" - The shader can have a maximum of two end states 0 or 1, Animate between these two values to do the transitions
83 * between states. Default 0.0
84 * "uHightScale" - The height displacement is multiplied by this factor. Tweak this to get the required level of depth. Default 0.1
85 * "uFixedNormal" - The Fixed normal will be used for the light calculation. Tweak this to get the required level of light.
86 * Only applicable for the FIXED type shader and not for DISPLACED type
88 * @param type The type of the effect, can be either DISPLACED, or FIXED.
89 * @return A handle to a newly allocated ShaderEffect
95 DISPLACEMENT_EFFECT_DISPLACED = 0, /// Image gets displaced
96 DISPLACEMENT_EFFECT_FIXED /// Image does not displace. Useful for matching lighting between areas that do not displace and those that do, e.g for backgrounds which are visible between buttons.
97 }DisplacementEffectType;
99 inline ShaderEffect CreateDisplacementEffect(DisplacementEffectType type)
101 std::string fragmentSourceFixed;
102 fragmentSourceFixed = "precision mediump float;\n"
103 "uniform vec3 uLightDirection;\n"
104 "uniform vec3 uAmbientLightColor;\n"
105 "uniform vec3 uDiffuseLightColor;\n"
106 "uniform float uLightMultiplier;\n"
107 "uniform float uState;\n"
108 "uniform float uHightScale;\n"
109 "uniform vec3 uFixedNormal;\n"
113 " vec4 col = texture2D(sTexture, vTexCoord);\n"
115 " float intensity = dot(uLightDirection, uFixedNormal);"
116 " vec3 lighting = (intensity * uDiffuseLightColor) + uAmbientLightColor;\n"
117 " lighting *= uLightMultiplier;\n"
118 // output col = image * light
119 " gl_FragColor = vec4(col.rgb * lighting * uColor.rgb, col.a * uColor.a);\n"
124 std::string fragmentSourceDisplaced(
125 "precision mediump float;\n"
126 "uniform vec3 uLightDirection;\n"
127 "uniform vec3 uAmbientLightColor;\n"
128 "uniform vec3 uDiffuseLightColor;\n"
129 "uniform float uLightMultiplier;\n"
130 "uniform float uState;\n"
131 "uniform float uHightScale;\n"
134 " highp vec4 displacementMap1 = texture2D(sEffect, vec2(vTexCoord.s, vTexCoord.t/2.0));\n"
135 " highp vec4 displacementMap2 = texture2D(sEffect, vec2(vTexCoord.s, 0.5+vTexCoord.t/2.0));\n"
136 " highp vec4 displacementMap = mix(displacementMap1, displacementMap2, uState);\n"
138 " vec3 normalAdjusted = normalize(displacementMap.rgb*2.0-1.0);\n"
139 " float height = uHightScale * (displacementMap.a*2.0 - 1.0);\n"
140 " vec2 displacement = vec2(0.0);\n"
141 " displacement += (vec2(0.5)-vTexCoord.st)*height;\n"
142 " vec2 newCoord = vTexCoord.st + displacement.xy;\n"
144 " vec4 col = texture2D(sTexture, newCoord);\n"
145 // Y-Axis for the normal map is taken as in Y-Down format, So inverting it for GL
146 " float intensity = dot(uLightDirection, vec3(1.0,-1.0, 1.0) * normalAdjusted);"
147 " vec3 lighting = (intensity * uDiffuseLightColor) + uAmbientLightColor;\n"
148 " lighting *= uLightMultiplier;\n"
149 " vec3 color = col.rgb * lighting * uColor.rgb;\n"
150 " gl_FragColor = vec4(color, col.a * uColor.a);\n"
153 //////////////////////////////////////
154 // Create shader effect
158 ShaderEffect shaderEffect;
161 case DISPLACEMENT_EFFECT_DISPLACED:
162 shaderEffect = ShaderEffect::New( "", fragmentSourceDisplaced);
165 case DISPLACEMENT_EFFECT_FIXED:
167 shaderEffect = ShaderEffect::New( "", fragmentSourceFixed);
172 //////////////////////////////////////
173 // Register uniform properties
176 // factors that scale the look, defaults
177 shaderEffect.SetUniform("uLightDirection",Vector3(0.0, 0.7070168f, 0.7071068f));
178 shaderEffect.SetUniform("uAmbientLightColor",Vector3(0.15f, 0.15f, 0.15f));
179 shaderEffect.SetUniform("uDiffuseLightColor",Vector3(1.0f, 1.0f, 1.0f));
180 shaderEffect.SetUniform("uLightMultiplier",1.0f);
181 shaderEffect.SetUniform("uState",0.0f);
182 shaderEffect.SetUniform("uHightScale",0.1f);
184 if(type == DISPLACEMENT_EFFECT_FIXED)
186 shaderEffect.SetUniform("uFixedNormal",Vector3(0.0f, 0.0f, 1.0f) );
196 #endif //#ifndef __DALI_TOOLKIT_SHADER_EFFECT_DISPLACEMENT_H__