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