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 #include <chrono>
16
17 #include "ge_log.h"
18 #include "ge_wave_gradient_shader_mask.h"
19
20 namespace OHOS {
21 namespace Rosen {
22 namespace Drawing {
23
GEWaveGradientShaderMask(GEWaveGradientShaderMaskParams param)24 GEWaveGradientShaderMask::GEWaveGradientShaderMask(GEWaveGradientShaderMaskParams param) : param_(param) {}
25
GenerateDrawingShader(float width,float height) const26 std::shared_ptr<ShaderEffect> GEWaveGradientShaderMask::GenerateDrawingShader(float width, float height) const
27 {
28 std::shared_ptr<Drawing::RuntimeShaderBuilder> builder = nullptr;
29 builder = GetWaveGradientShaderMaskBuilder();
30 if (!builder) {
31 LOGE("GEWaveGradientShaderMask::GenerateDrawingShaderHas builder error");
32 return nullptr;
33 }
34 builder->SetUniform("iResolution", width, height);
35 builder->SetUniform("waveCenter", param_.center_.first, param_.center_.second);
36 builder->SetUniform("waveWidth", param_.width_);
37 builder->SetUniform("turbulenceStrength", param_.turbulenceStrength_);
38 builder->SetUniform("blurRadius", param_.blurRadius_);
39 builder->SetUniform("propagationRadius", param_.propagationRadius_);
40 auto waveMaskEffectShader = builder->MakeShader(nullptr, false);
41 if (!waveMaskEffectShader) {
42 LOGE("GEWaveGradientShaderMask::GenerateDrawingShader effect build failed");
43 }
44 return waveMaskEffectShader;
45 }
46
GetWaveGradientShaderMaskBuilder() const47 std::shared_ptr<Drawing::RuntimeShaderBuilder> GEWaveGradientShaderMask::GetWaveGradientShaderMaskBuilder() const
48 {
49 thread_local std::shared_ptr<Drawing::RuntimeShaderBuilder> waveShaderMaskBuilder = nullptr;
50 if (waveShaderMaskBuilder) {
51 return waveShaderMaskBuilder;
52 }
53
54 static constexpr char prog[] = R"(
55 uniform half2 iResolution;
56 uniform half2 waveCenter;
57 uniform half waveWidth;
58 uniform half turbulenceStrength;
59 uniform half blurRadius;
60 uniform half propagationRadius;
61
62 vec2 random2(vec2 st)
63 {
64 // Magic constants for dot products: chosen to avoid grid artifacts and ensure good distribution
65 return fract(sin(vec2(dot(st, vec2(127.1, 311.7)),
66 dot(st, vec2(269.5, 183.3)))) * 43758.5453) * 2.0 - 1.0;
67 }
68
69 float noise(vec2 st)
70 {
71 vec2 i = floor(st);
72 vec2 f = fract(st);
73 vec2 u = f * f * (3.0 - 2.0 * f);
74 return mix(
75 mix(dot(random2(i), f),
76 dot(random2(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x),
77 mix(dot(random2(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)),
78 dot(random2(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x),
79 u.y);
80 }
81
82 float fbm(vec2 st)
83 {
84 float value = 0.0;
85 float amp = 0.5;
86 value += amp * noise(st);
87 st *= 2.0;
88 amp = 0.25; // half of origin value
89 value += amp * noise(st);
90 return value;
91 }
92
93 half4 main(vec2 fragCoord)
94 {
95 vec2 uv = fragCoord.xy / iResolution.xy;
96
97 float aspect = iResolution.x / iResolution.y;
98 vec2 center = vec2(waveCenter.x * aspect, waveCenter.y);
99 float currentRadius = propagationRadius;
100
101 float turbulenceTime = currentRadius * 5.0 + sin(currentRadius * 6.28) * 2.0;
102 float n1 = fbm(uv * 3.0 + vec2(turbulenceTime, 0.0));
103 float n2 = fbm(uv * 3.0 + vec2(0.0, turbulenceTime));
104 vec2 turbulenceOffset = vec2(n1, n2) * turbulenceStrength;
105
106 vec2 uvWarped = uv + turbulenceOffset;
107 vec2 uvCorrectedWarped = vec2(uvWarped.x * aspect, uvWarped.y);
108 vec2 dirWarped = uvCorrectedWarped - center;
109 float distWarped = length(dirWarped);
110
111 float mask;
112 if (waveWidth < 0.0001) {
113 float outer = currentRadius + blurRadius;
114 mask = 1.0 - smoothstep(currentRadius - blurRadius, outer, distWarped);
115 } else {
116 float inner = currentRadius - waveWidth - blurRadius;
117 float outer = currentRadius + waveWidth + blurRadius;
118 mask = smoothstep(inner, inner + blurRadius, distWarped)
119 - smoothstep(outer - blurRadius, outer, distWarped);
120 }
121 return half4(mask);
122 }
123 )";
124
125 auto waveShaderMaskEffect = Drawing::RuntimeEffect::CreateForShader(prog);
126 if (!waveShaderMaskEffect) {
127 LOGE("GEWaveGradientShaderMask::GetWaveShaderMaskBuilder effect error");
128 return nullptr;
129 }
130
131 waveShaderMaskBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(waveShaderMaskEffect);
132 return waveShaderMaskBuilder;
133 }
134
GenerateDrawingShaderHasNormal(float width,float height) const135 std::shared_ptr<ShaderEffect> GEWaveGradientShaderMask::GenerateDrawingShaderHasNormal(float width, float height) const
136 {
137 std::shared_ptr<Drawing::RuntimeShaderBuilder> builder = nullptr;
138 builder = GetWaveGradientShaderNormalMaskBuilder();
139 if (!builder) {
140 LOGE("GEWaveGradientShaderMask::GenerateDrawingShaderHasNormal builder error");
141 return nullptr;
142 }
143 builder->SetUniform("iResolution", width, height);
144 builder->SetUniform("waveCenter", param_.center_.first, param_.center_.second);
145 builder->SetUniform("waveWidth", param_.width_);
146 builder->SetUniform("turbulenceStrength", param_.turbulenceStrength_);
147 builder->SetUniform("blurRadius", param_.blurRadius_);
148 builder->SetUniform("propagationRadius", param_.propagationRadius_);
149 auto waveMaskEffectShader = builder->MakeShader(nullptr, false);
150 if (!waveMaskEffectShader) {
151 LOGE("GEWaveGradientShaderMask::GenerateDrawingShaderHasNormal effect error");
152 }
153 return waveMaskEffectShader;
154 }
155
GetWaveGradientShaderNormalMaskBuilder() const156 std::shared_ptr<Drawing::RuntimeShaderBuilder> GEWaveGradientShaderMask::GetWaveGradientShaderNormalMaskBuilder() const
157 {
158 thread_local std::shared_ptr<Drawing::RuntimeShaderBuilder> waveShaderMaskNormalBuilder = nullptr;
159 if (waveShaderMaskNormalBuilder) {
160 return waveShaderMaskNormalBuilder;
161 }
162
163 static constexpr char prog[] = R"(
164 uniform half2 iResolution;
165 uniform half2 waveCenter;
166 uniform half waveWidth;
167 uniform half turbulenceStrength;
168 uniform half blurRadius;
169 uniform half propagationRadius;
170
171 vec2 random2(vec2 st)
172 {
173 // Magic constants for dot products: chosen to avoid grid artifacts and ensure good distribution
174 return fract(sin(vec2(dot(st, vec2(127.1, 311.7)),
175 dot(st, vec2(269.5, 183.3)))) * 43758.5453) * 2.0 - 1.0;
176 }
177
178 float noise(vec2 st)
179 {
180 vec2 i = floor(st);
181 vec2 f = fract(st);
182 vec2 u = f * f * (3.0 - 2.0 * f);
183 return mix(
184 mix(dot(random2(i), f),
185 dot(random2(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x),
186 mix(dot(random2(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)),
187 dot(random2(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x),
188 u.y);
189 }
190
191 float fbm(vec2 st)
192 {
193 float value = 0.0;
194 float amp = 0.5;
195 value += amp * noise(st);
196 st *= 2.0;
197 amp = 0.25; // half of origin value
198 value += amp * noise(st);
199 return value;
200 }
201
202 half4 main(vec2 fragCoord)
203 {
204 vec2 uv = fragCoord.xy / iResolution.xy;
205
206 float aspect = iResolution.x / iResolution.y;
207 vec2 center = vec2(waveCenter.x * aspect, waveCenter.y);
208 float currentRadius = propagationRadius;
209
210 float turbulenceTime = currentRadius * 5.0 + sin(currentRadius * 6.28) * 2.0;
211 float n1 = fbm(uv * 3.0 + vec2(turbulenceTime, 0.0));
212 float n2 = fbm(uv * 3.0 + vec2(0.0, turbulenceTime));
213 vec2 turbulenceOffset = vec2(n1, n2) * turbulenceStrength;
214
215 vec2 uvWarped = uv + turbulenceOffset;
216 vec2 uvCorrectedWarped = vec2(uvWarped.x * aspect, uvWarped.y);
217 vec2 dirWarped = uvCorrectedWarped - center;
218 float distWarped = length(dirWarped);
219
220 float mask;
221 if (waveWidth < 0.0001) {
222 float outer = currentRadius + blurRadius;
223 mask = 1.0 - smoothstep(currentRadius - blurRadius, outer, distWarped);
224 } else {
225 float inner = currentRadius - waveWidth - blurRadius;
226 float outer = currentRadius + waveWidth + blurRadius;
227 mask = smoothstep(inner, inner + blurRadius, distWarped)
228 - smoothstep(outer - blurRadius, outer, distWarped);
229 }
230 vec2 direction = vec2(0.0);
231 if (mask > 0.001) {
232 vec2 radialDir = normalize(dirWarped);
233 vec2 turbulentDir = normalize(turbulenceOffset + 0.0001);
234 direction = radialDir * 0.4 + turbulentDir * turbulenceStrength * 3.0;
235 direction *= mask;
236 }
237 direction = clamp(direction, -1.0, 1.0);
238 vec2 normalizedDirection = direction * 0.5 + 0.5;
239
240 return half4(normalizedDirection, 1.0, mask);
241 }
242 )";
243
244 auto waveShaderMaskNormalEffect = Drawing::RuntimeEffect::CreateForShader(prog);
245 if (!waveShaderMaskNormalEffect) {
246 LOGE("GEWaveGradientShaderMask::GetWaveShaderNormalMaskBuilder effect error");
247 return nullptr;
248 }
249
250 waveShaderMaskNormalBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(waveShaderMaskNormalEffect);
251 return waveShaderMaskNormalBuilder;
252 }
253 } // namespace Drawing
254 } // namespace Rosen
255 } // namespace OHOS