1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef GRAPHICS_EFFECT_GE_WATER_RIPPLE_FILTER_H 16 #define GRAPHICS_EFFECT_GE_WATER_RIPPLE_FILTER_H 17 18 #include <memory> 19 20 #include "ge_shader_filter.h" 21 #include "ge_visual_effect.h" 22 23 #include "draw/canvas.h" 24 #include "effect/color_filter.h" 25 #include "effect/runtime_effect.h" 26 #include "effect/runtime_shader_builder.h" 27 #include "image/image.h" 28 #include "utils/matrix.h" 29 #include "utils/rect.h" 30 31 namespace OHOS { 32 namespace Rosen { 33 class GEWaterRippleFilter : public GEShaderFilter { 34 public: 35 GEWaterRippleFilter(const Drawing::GEWaterRippleFilterParams& params); 36 ~GEWaterRippleFilter() override = default; 37 38 std::shared_ptr<Drawing::Image> ProcessImage(Drawing::Canvas& canvas, const std::shared_ptr<Drawing::Image> image, 39 const Drawing::Rect& src, const Drawing::Rect& dst) override; 40 41 private: 42 std::shared_ptr<Drawing::RuntimeEffect> GetWaterRippleEffectSM(const int rippleMode); 43 std::shared_ptr<Drawing::RuntimeEffect> GetWaterRippleEffectSS(); 44 float progress_ = 0.0f; 45 uint32_t waveCount_ = 2; 46 float rippleCenterX_ = 0.5f; 47 float rippleCenterY_ = 0.7f; 48 uint32_t rippleMode_ = 1; 49 50 inline static const std::string shaderStringSMsend = R"( 51 uniform shader image; 52 uniform half2 iResolution; 53 uniform half progress; 54 uniform half waveCount; 55 uniform half2 rippleCenter; 56 57 const half basicSlope = 0.5; 58 const half gAmplSupress = 0.012; 59 const half waveFreq = 31.0; 60 const half wavePropRatio = 2.0; 61 const half ampSupArea = 0.45; 62 const half intensity = 0.15; 63 64 half calcWave(half dis) 65 { 66 half preWave = smoothstep(0., -0.3, dis); 67 half waveForm = (waveCount == 1.) ? 68 smoothstep(-0.4, -0.2, dis) * smoothstep(0., -0.2, dis) : 69 (waveCount == 2.) ? 70 smoothstep(-0.6, -0.3, dis) * preWave : 71 smoothstep(-0.9, -0.6, dis) * step(abs(dis + 0.45), 0.45) * preWave; 72 return -sin(waveFreq * dis) * waveForm; 73 } 74 75 half waveGenerator(half propDis, half t) 76 { 77 half dis = propDis - wavePropRatio * t; 78 half h = 1e-3; 79 half d1 = dis - h; 80 half d2 = dis + h; 81 return (calcWave(d2) - calcWave(d1)) / (2. * h); 82 } 83 84 half4 main(vec2 fragCoord) 85 { 86 half shortEdge = min(iResolution.x, iResolution.y); 87 half2 uv = fragCoord.xy / iResolution.xy; 88 half2 uvHomo = fragCoord.xy / shortEdge; 89 half2 resRatio = iResolution.xy / shortEdge; 90 91 half progSlope = basicSlope + 0.1 * waveCount; 92 half t = progSlope * progress; 93 94 half2 waveCenter = rippleCenter * resRatio; 95 half propDis = distance(uvHomo, waveCenter); 96 half2 v = uvHomo - waveCenter; 97 half ampDecayByT = (propDis < 1.) ? pow((1. - propDis), 4.) : 0.; 98 99 half ampSupByDis = smoothstep(0., ampSupArea, propDis); 100 half hIntense = waveGenerator(propDis, t) * ampDecayByT * ampSupByDis * gAmplSupress; 101 half2 circles = normalize(v) * hIntense; 102 103 half3 norm = vec3(circles, hIntense); 104 half2 expandUV = (uv - intensity * norm.xy) * iResolution.xy; 105 half3 color = image.eval(expandUV).rgb; 106 color += 150. * pow(clamp(dot(norm, normalize(vec3(0., 4., -0.5))), 0., 1.), 2.5); 107 108 return half4(color, 1.0); 109 } 110 )"; 111 112 inline static const std::string shaderStringSSmutual = R"( 113 uniform shader image; 114 uniform vec2 iResolution; 115 uniform float progress; 116 uniform float waveCount; 117 uniform vec2 rippleCenter; 118 // small 119 const float s_basicSlope = 0.5; 120 const float s_ampSupress = 0.04; 121 const float s_waveFreq = 31.0; 122 float s_wavePropRatio = 2.; 123 const float s_ampSupArea = 0.3; 124 const float s_intensity = 0.15; 125 const float s_decayExp = 4. ; 126 const float s_luminance = 60.; 127 const vec3 s_lightDirect = vec3(0., -4., -0.2); 128 // big 129 const float b_ampSupress = 0.01; 130 const float b_waveFreq = 7.0; 131 float b_wavePropRatio = 6.9; 132 const float b_intensity = 0.15; 133 const float b_decayExp = 4.; 134 const float b_luminance = 30.; 135 136 const vec3 waveAxis = vec3(2., 3., 5.); 137 138 vec3 lightBlend(vec3 colorA, vec3 colorB) 139 { 140 vec3 oneVec = vec3(1.); 141 return oneVec - ((oneVec - colorA) * (oneVec - colorB)); 142 } 143 144 float calcWave(float count, float freq, float dis) 145 { 146 float axisVal = (count == 1.) ? waveAxis.x : (count == 2.) ? waveAxis.y : waveAxis.z; 147 float axisPoint = -(axisVal * 3.1416) / freq; 148 float waveForm = smoothstep(axisPoint * 2., axisPoint, dis) * smoothstep(0., axisPoint, dis); 149 float downCond = (count == 3.) ? -1. : 1.; 150 return sin(freq * dis) * waveForm * downCond; 151 } 152 153 float calcBLight(float dis, float freq) 154 { 155 float currentX = pow(dis + (6.2832 / freq), 2.); 156 return 1.2 * exp(-55. * currentX); 157 } 158 159 float calcSLight(float dis, float freq, float yShift) 160 { 161 float pivot1 = pow(dis + (9.4248 / freq) - 0.14, 2.); 162 float pivot2 = pow(dis + (9.4248 / freq) + 0.01, 2.); 163 return 2. * yShift * (exp(-1000. * pivot2) + exp(-1000. * pivot1)); 164 } 165 166 vec2 waveGenerator(float propDis, float t, float count, float freq, float prop, float yShift) 167 { 168 float dis = propDis - prop * t; 169 float h = 1e-3; 170 float d1 = dis - h; 171 float d2 = dis + h; 172 float waveVal = (calcWave(count, freq, d2) - calcWave(count, freq, d1)) / (2. * h); 173 float lightAdjust = (freq < 10.) ? calcBLight(dis, freq) : calcSLight(dis, freq, yShift); 174 return vec2(waveVal, lightAdjust); 175 } 176 177 vec4 main(vec2 fragCoord) 178 { 179 float s_waveCount = waveCount; 180 vec2 b_rippleCenter = rippleCenter; 181 float shortEdge = min(iResolution.x, iResolution.y); 182 vec2 uv = fragCoord.xy / iResolution.xy; 183 vec2 uvHomo = fragCoord.xy / shortEdge; 184 vec2 resRatio = iResolution.xy / shortEdge; 185 186 float b_progSlope = 0.4; 187 float s_progSlope = s_basicSlope + 0.1 * s_waveCount; 188 float b_t = b_progSlope * (progress + 0.4); 189 // float s_t = fract(s_progSlope * progress); 190 float s_t = s_progSlope * (progress + 0.11); 191 192 float veloDecay = 1. - 0.04 * (smoothstep(0.2, 0.16, progress) + smoothstep(0.2, 1.2, progress)); 193 b_wavePropRatio *= veloDecay; 194 s_wavePropRatio *= veloDecay; 195 196 vec2 b_waveCenter = b_rippleCenter * resRatio; 197 vec2 s_rippleCenter = vec2(0.5, 0.); 198 s_rippleCenter.x = (b_rippleCenter.x == 0.5) ? 0.5 : floor(b_rippleCenter.x + 0.5); 199 s_rippleCenter.y = (b_rippleCenter.y == 0.5) ? 0.5 : floor(b_rippleCenter.y + 0.5); 200 vec2 s_waveCenter = s_rippleCenter * resRatio; 201 float b_propDis = distance(uvHomo, b_waveCenter); 202 float s_propDis = distance(uvHomo, s_waveCenter); 203 vec2 b_vec = uvHomo - b_waveCenter; 204 vec2 s_vec = uvHomo - s_waveCenter; 205 float b_ampDecayByDis = (b_propDis < 1.9) ? clamp(pow((1.9 - b_propDis), b_decayExp), 0., 1.): 0.; 206 float s_ampDecayByDis = (s_propDis < 0.7) ? clamp(pow((0.7 - s_propDis), s_decayExp), 0., 1.): 0.; 207 208 float s_ampSupCenter = smoothstep(0., s_ampSupArea, s_propDis); 209 vec2 b_waveRes = waveGenerator(b_propDis, b_t, 1., b_waveFreq, b_wavePropRatio, 1.); 210 vec2 s_waveRes = waveGenerator( 211 s_propDis, s_t, s_waveCount, s_waveFreq, s_wavePropRatio, abs(normalize(s_vec)[1])); 212 float b_intense = b_waveRes[0] * b_ampDecayByDis * b_ampSupress; 213 float s_intense = s_waveRes[0] * s_ampDecayByDis * s_ampSupCenter * s_ampSupress; 214 float b_Prime = b_waveRes[1] * b_ampDecayByDis * b_ampSupress; 215 float s_Prime = s_waveRes[1] * s_ampDecayByDis * s_ampSupCenter * s_ampSupress; 216 vec2 b_circles = normalize(b_vec) * b_intense; 217 vec2 s_circles = normalize(s_vec) * s_intense; 218 219 vec3 b_norm = vec3(b_circles, b_intense); 220 vec3 s_norm = vec3(s_circles, s_intense); 221 222 vec2 warp = (b_intensity * b_norm.xy + s_intensity * s_norm.xy) * smoothstep(0., 0.07, progress); 223 vec2 expandUV = (uv - warp) * iResolution.xy; 224 vec3 color = image.eval(expandUV).rgb; 225 226 float b_light = b_luminance * clamp(b_Prime, 0., 1.) * smoothstep(0., 0.125, progress);; 227 float s_light = s_luminance * clamp(s_Prime, 0., 1.); 228 229 color += s_light; 230 color = lightBlend(color, vec3(b_light)); 231 // color = lightBlend(color, vec3(s_light)); 232 233 return vec4(color, 1.0); 234 } 235 )"; 236 237 inline static const std::string shaderStringSMrecv = R"( 238 uniform shader image; 239 uniform vec2 iResolution; 240 uniform float progress; 241 uniform float waveCount; 242 uniform vec2 rippleCenter; 243 244 const float basicSlope = 0.7; 245 const float gAmplSupress = 0.003; 246 float waveFreq = 25.0; 247 const float wavePropRatio = 2.0; 248 const float ampSupArea = 0.45; 249 const float intensity = 0.15; 250 251 const float decayExp = 1.5; 252 float luminance = 230.; 253 const float highLightExp = 2.5; 254 const vec3 lightDirect = half3(0., -4., 0.5); 255 const vec3 waveAxis = half3(2., 3., 5.); 256 257 float calcWave(float dis) 258 { 259 float axisPoint = -6.283 / waveFreq; 260 float waveForm = smoothstep(axisPoint * 2., axisPoint, dis) * smoothstep(0., axisPoint, dis); 261 return sin(waveFreq * dis) * waveForm; 262 } 263 264 float waveGenerator(float propDis, float t) 265 { 266 float dis = propDis - wavePropRatio * t; 267 float h = 1e-3; 268 float d1 = dis - h; 269 float d2 = dis + h; 270 return (calcWave(d2) - calcWave(d1)) / (2. * h); 271 } 272 273 vec4 main(vec2 fragCoord) 274 { 275 float shortEdge = min(iResolution.x, iResolution.y); 276 vec2 uv = fragCoord.xy / iResolution.xy; 277 vec2 uvHomo = fragCoord.xy / shortEdge; 278 vec2 resRatio = iResolution.xy / shortEdge; 279 280 float progSlope = basicSlope + 0.1 * waveCount; 281 float t = progSlope * progress; 282 waveFreq -= t * 20.; 283 waveFreq = (waveFreq > 15.) ? waveFreq : 15.; 284 285 vec2 waveCenter = rippleCenter * resRatio; 286 float propDis = distance(uvHomo, waveCenter); 287 vec2 v = uvHomo - waveCenter; 288 float ampDecayByT = (propDis < 1.3) ? clamp(pow((1.3 - propDis), decayExp), 0., 1.): 0.; 289 290 float ampSupByDis = smoothstep(0., ampSupArea, propDis); 291 float hIntense = waveGenerator(propDis, t) * ampDecayByT * ampSupByDis * gAmplSupress; 292 vec2 circles = normalize(v) * hIntense; 293 294 vec3 norm = vec3(circles, hIntense); 295 vec2 expandUV = (uv - intensity * norm.xy) * iResolution.xy; 296 vec3 color = image.eval(expandUV).rgb; 297 color += luminance * pow(clamp(dot(norm, normalize(lightDirect)), 0., 1.), highLightExp); 298 299 return vec4(color, 1.0); 300 } 301 )"; 302 }; 303 304 } // namespace Rosen 305 } // namespace OHOS 306 307 #endif // GRAPHICS_EFFECT_GE_WATER_RIPPLE_FILTER_H