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