• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 
16 #include <chrono>
17 #include "ge_double_ripple_shader_mask.h"
18 
19 namespace OHOS {
20 namespace Rosen {
21 namespace Drawing {
22 
GEDoubleRippleShaderMask(GEDoubleRippleShaderMaskParams param)23 GEDoubleRippleShaderMask::GEDoubleRippleShaderMask(GEDoubleRippleShaderMaskParams param) : param_(param) {}
24 
GenerateDrawingShader(float width,float height) const25 std::shared_ptr<ShaderEffect> GEDoubleRippleShaderMask::GenerateDrawingShader(float width, float height) const
26 {
27     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder = nullptr;
28     builder = GetDoubleRippleShaderMaskBuilder();
29     if (!builder) {
30         LOGE("GEDoubleRippleShaderMask::GenerateDrawingShaderHas builder error");
31         return nullptr;
32     }
33     builder->SetUniform("iResolution", width, height);
34     builder->SetUniform("centerPos1", param_.center1_.first, param_.center1_.second);
35     builder->SetUniform("centerPos2", param_.center2_.first, param_.center2_.second);
36     builder->SetUniform("rippleRadius", param_.radius_);
37     builder->SetUniform("rippleWidth", param_.width_);
38     builder->SetUniform("turbulence", param_.turbulence_);
39     builder->SetUniform("haloThickness", param_.haloThickness_);
40     auto rippleMaskEffectShader = builder->MakeShader(nullptr, false);
41     if (!rippleMaskEffectShader) {
42         LOGE("GEDoubleRippleShaderMask::GenerateDrawingShaderHas effect error");
43     }
44     return rippleMaskEffectShader;
45 }
46 
GetDoubleRippleShaderMaskBuilder() const47 std::shared_ptr<Drawing::RuntimeShaderBuilder> GEDoubleRippleShaderMask::GetDoubleRippleShaderMaskBuilder() const
48 {
49     thread_local std::shared_ptr<Drawing::RuntimeShaderBuilder> rippleShaderMaskBuilder = nullptr;
50     if (rippleShaderMaskBuilder) {
51         return rippleShaderMaskBuilder;
52     }
53 
54 static constexpr char prog[] = R"(
55         uniform half2 iResolution;
56         uniform half2 centerPos1;
57         uniform half2 centerPos2;
58         uniform half rippleRadius;
59         uniform half rippleWidth;
60         uniform half turbulence;
61         uniform half haloThickness;
62 
63         const float waveScale  = 0.5;
64         const float freqX = 4.0;
65         const float freqY = 6.0;
66         const float freqDiag = 8.0;
67 
68         float ShapeSDF(vec2 p, float radius, float noiseScale, vec2 center)
69         {
70             float dist = length(p);
71             float phaseX = center.x * 1.0;
72             float phaseY = center.y * 1.0;
73             float phaseDiag = dot(center, vec2(1.0)) * 0.4;
74 
75             float noise = 0.;
76             noise += sin(p.x * freqX + phaseX) * 0.15; // 0.15: reduce the strength of noise on x axis
77             noise += sin(p.y * freqY + phaseY) * 0.15; // 0.15: reduce the strength of noise on y axis
78             // 0.075: reduce the strength of noise in the diagonal direction
79             noise += sin((p.x + p.y) * freqDiag + phaseDiag) * 0.075;
80 
81             float distortedDist = dist + noise * noiseScale;
82             float attenuation = waveScale / (1.0 + distortedDist * 5.0); // 5.0: control the falloff speed of the wave
83             float wave = sin(distortedDist * 30.0) * attenuation; // 30.0: control the frequency of the wave
84             return distortedDist - radius + wave * 0.05; // 0.05: control the amplitude of the wave
85         }
86 
87         float SmoothUnion(float d1, float d2, float k) {
88             float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
89             return mix(d2, d1, h) - k * h * (1.0 - h);
90         }
91 
92         half4 main(float2 fragCoord)
93         {
94             float thickness = rippleWidth;
95             float noiseScale = turbulence;
96 
97             vec2 center1 = centerPos1;
98             vec2 center2 = centerPos2;
99             vec2 center = (centerPos1 + centerPos2) / 2.0;
100 
101             vec2 uv = fragCoord.xy / iResolution.xy;
102             float aspect = iResolution.x / iResolution.y;
103 
104             vec2 p = uv * 2.0 - 1.0;
105             p.x *= aspect;
106 
107             vec2 c1 = center1 * 2.0 - 1.0;
108             c1.x *= aspect;
109             vec2 delta1 = p - c1;
110 
111             vec2 c2 = center2 * 2.0 - 1.0;
112             c2.x *= aspect;
113             vec2 delta2 = p - c2;
114 
115             float currentRadius1 = rippleRadius;
116             float currentRadius2 = rippleRadius;
117 
118             float d1Outer = ShapeSDF(delta1, currentRadius1, noiseScale, c1);
119             float d2Outer = ShapeSDF(delta2, currentRadius2, noiseScale, c2);
120             float d1Inner = ShapeSDF(delta1, currentRadius1 * (1.0 - thickness), noiseScale, c1);
121             float d2Inner = ShapeSDF(delta2, currentRadius2 * (1.0 - thickness), noiseScale, c2);
122 
123             float smoothness = 0.4;
124             float dOuter = SmoothUnion(d1Outer, d2Outer, smoothness);
125             float dInner = SmoothUnion(d1Inner, d2Inner, smoothness);
126             float ring = max(-dInner, dOuter);
127             ring = smoothstep(0.001 + haloThickness * length(uv - center),
128                 -0.001 - haloThickness * length(uv - center) * 0.5, ring);
129 
130             return half4(clamp(ring, 0., 1.));
131         }
132     )";
133 
134     auto rippleShaderMaskEffect = Drawing::RuntimeEffect::CreateForShader(prog);
135     if (!rippleShaderMaskEffect) {
136         return nullptr;
137     }
138 
139     rippleShaderMaskBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(rippleShaderMaskEffect);
140     return rippleShaderMaskBuilder;
141 }
142 
GenerateDrawingShaderHasNormal(float width,float height) const143 std::shared_ptr<ShaderEffect> GEDoubleRippleShaderMask::GenerateDrawingShaderHasNormal(float width, float height) const
144 {
145     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder = nullptr;
146     builder = GetDoubleRippleShaderNormalMaskBuilder();
147     if (!builder) {
148         LOGE("GEDoubleRippleShaderMask::GenerateDrawingShaderHasNormal builder error");
149         return nullptr;
150     }
151     builder->SetUniform("iResolution", width, height);
152     builder->SetUniform("centerPos1", param_.center1_.first, param_.center1_.second);
153     builder->SetUniform("centerPos2", param_.center2_.first, param_.center2_.second);
154     builder->SetUniform("rippleRadius", param_.radius_);
155     builder->SetUniform("rippleWidth", param_.width_);
156     builder->SetUniform("turbulence", param_.turbulence_);
157     builder->SetUniform("haloThickness", param_.haloThickness_);
158     auto rippleMaskEffectShader = builder->MakeShader(nullptr, false);
159     if (!rippleMaskEffectShader) {
160         LOGE("GEDoubleRippleShaderMask::GenerateDrawingShaderHasNormal effect error");
161     }
162     return rippleMaskEffectShader;
163 }
164 
165 
GetDoubleRippleShaderNormalMaskBuilder() const166 std::shared_ptr<Drawing::RuntimeShaderBuilder> GEDoubleRippleShaderMask::GetDoubleRippleShaderNormalMaskBuilder() const
167 {
168     thread_local std::shared_ptr<Drawing::RuntimeShaderBuilder> rippleShaderMaskNormalBuilder = nullptr;
169     if (rippleShaderMaskNormalBuilder) {
170         return rippleShaderMaskNormalBuilder;
171     }
172 
173     static constexpr char prog[] = R"(
174         uniform half2 iResolution;
175         uniform half2 centerPos1;
176         uniform half2 centerPos2;
177         uniform half rippleRadius;
178         uniform half rippleWidth;
179         uniform half turbulence;
180         uniform half haloThickness;
181 
182         const float waveScale  = 0.5;
183         const float freqX = 4.0;
184         const float freqY = 6.0;
185         const float freqDiag = 8.0;
186 
187         float ShapeSDF(vec2 p, float radius, float noiseScale, vec2 center)
188         {
189             float dist = length(p);
190             float phaseX = center.x * 1.0;
191             float phaseY = center.y * 1.0;
192             float phaseDiag = dot(center, vec2(1.0)) * 0.4;
193 
194             float noise = 0.;
195             noise += sin(p.x * freqX + phaseX) * 0.15; // 0.15: reduce the strength of noise on x axis
196             noise += sin(p.y * freqY + phaseY) * 0.15; // 0.15: reduce the strength of noise on y axis
197             // 0.075: reduce the strength of noise in the diagonal direction
198             noise += sin((p.x + p.y) * freqDiag + phaseDiag) * 0.075;
199 
200             float distortedDist = dist + noise * noiseScale;
201             float attenuation = waveScale / (1.0 + distortedDist * 5.0); // 5.0: control the falloff speed of the wave
202             float wave = sin(distortedDist * 30.0) * attenuation; // 30.0: control the frequency of the wave
203             return distortedDist - radius + wave * 0.05; // 0.05: control the amplitude of the wave
204         }
205 
206         float SmoothUnion(float d1, float d2, float k) {
207             float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
208             return mix(d2, d1, h) - k * h * (1.0 - h);
209         }
210 
211         half4 main(float2 fragCoord)
212         {
213             float thickness = rippleWidth;
214             float noiseScale = turbulence;
215 
216             vec2 center1 = centerPos1;
217             vec2 center2 = centerPos2;
218             vec2 center = (centerPos1 + centerPos2) / 2.0;
219 
220             vec2 uv = fragCoord.xy / iResolution.xy;
221             float aspect = iResolution.x / iResolution.y;
222 
223             vec2 p = uv * 2.0 - 1.0;
224             p.x *= aspect;
225 
226             vec2 c1 = center1 * 2.0 - 1.0;
227             c1.x *= aspect;
228             vec2 delta1 = p - c1;
229 
230             vec2 c2 = center2 * 2.0 - 1.0;
231             c2.x *= aspect;
232             vec2 delta2 = p - c2;
233 
234             float currentRadius1 = rippleRadius;
235             float currentRadius2 = rippleRadius;
236 
237             float d1Outer = ShapeSDF(delta1, currentRadius1, noiseScale, c1);
238             float d2Outer = ShapeSDF(delta2, currentRadius2, noiseScale, c2);
239             float d1Inner = ShapeSDF(delta1, currentRadius1 * (1.0 - thickness), noiseScale, c1);
240             float d2Inner = ShapeSDF(delta2, currentRadius2 * (1.0 - thickness), noiseScale, c2);
241 
242             float smoothness = 0.4;
243             float dOuter = SmoothUnion(d1Outer, d2Outer, smoothness);
244             float dInner = SmoothUnion(d1Inner, d2Inner, smoothness);
245             float ring = max(-dInner, dOuter);
246             ring = smoothstep(0.001 + haloThickness * length(uv - center),
247                 -0.001 - haloThickness * length(uv - center) * 0.5, ring);
248 
249             float mask = clamp(ring, 0., 1.);
250 
251             vec2 directionVector = normalize(p + 1.0 - center1 - center2) * mask * 0.5 + 0.5;
252             return half4(directionVector, 1.0, mask);
253         }
254     )";
255 
256     auto rippleShaderMaskNormalEffect = Drawing::RuntimeEffect::CreateForShader(prog);
257     if (!rippleShaderMaskNormalEffect) {
258         LOGE("GEDoubleRippleShaderMask::GetRippleShaderNormalMaskBuilder effect error");
259         return nullptr;
260     }
261 
262     rippleShaderMaskNormalBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(rippleShaderMaskNormalEffect);
263     return rippleShaderMaskNormalBuilder;
264 }
265 
266 } // namespace Drawing
267 } // namespace Rosen
268 } // namespace OHOS