• 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 #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