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 <algorithm>
16 #include "ge_log.h"
17 #include "ge_wavy_ripple_light_shader.h"
18
19 namespace OHOS {
20 namespace Rosen {
21 namespace {
22 static constexpr char WAVY_PROG[] = R"(
23 uniform vec2 iResolution;
24 uniform vec2 center;
25 uniform float radius;
26 uniform float thickness;
27 const float noiseScale = 0.3;
28 const float waveScale = 0.5;
29 const float freqX = 4.0;
30 const float freqY = 6.0;
31 const float freqDiag = 8.0;
32 float shapeSDF(vec2 p, float radius)
33 {
34 float dist = length(p);
35 float noise = 0.0;
36 noise += sin(p.x * freqX) * 0.25;
37 noise += sin(p.y * freqY) * 0.35;
38 noise += sin((p.x + p.y) * freqDiag) * 0.1;
39 float distortedDist = dist + noise * noiseScale;
40 float attenuation = waveScale / (1.0 + distortedDist * 5.0);
41 float wave = sin(distortedDist * 30.0) * attenuation;
42 return distortedDist - radius + wave * 0.05;
43 }
44 vec4 main(vec2 fragCoord)
45 {
46 vec2 uv = fragCoord.xy / iResolution.xy;
47 float aspect = iResolution.x / iResolution.y;
48 vec3 color = vec3(0.0);
49 vec2 p = uv * 2.0 - 1.0;
50 p.x *= aspect;
51 vec2 c = center * 2.0 - 1.0;
52 c.x *= aspect;
53 vec2 delta = p - c;
54 float dist0 = length(c - vec2(-aspect, -1.0));
55 float dist1 = length(c - vec2(-aspect, 1.0));
56 float dist2 = length(c - vec2(aspect, -1.0));
57 float dist3 = length(c - vec2(aspect, 1.0));
58 float maxRadius = thickness + max(max(dist0, dist1), max(dist2, dist3));
59 float currentRadius = maxRadius * radius;
60 float d = abs(shapeSDF(delta, currentRadius));
61 float mask = smoothstep(thickness, 0.0, d);
62 vec3 baseColor = vec3(0.8, 0.5, 1.0);
63 color = baseColor * mask;
64 return vec4(color, mask);
65 }
66 )";
67 } // anonymous namespace
GEWavyRippleLightShader()68 GEWavyRippleLightShader::GEWavyRippleLightShader() {}
69
GEWavyRippleLightShader(Drawing::GEWavyRippleLightShaderParams & param)70 GEWavyRippleLightShader::GEWavyRippleLightShader(Drawing::GEWavyRippleLightShaderParams& param)
71 {
72 wavyRippleLightParams_ = param;
73 }
74
CreateWavyRippleLightShader(Drawing::GEWavyRippleLightShaderParams & param)75 std::shared_ptr<GEWavyRippleLightShader> GEWavyRippleLightShader::CreateWavyRippleLightShader(
76 Drawing::GEWavyRippleLightShaderParams& param)
77 {
78 std::shared_ptr<GEWavyRippleLightShader> wavyRippleLightShader = std::make_shared<GEWavyRippleLightShader>(param);
79 return wavyRippleLightShader;
80 }
81
MakeDrawingShader(const Drawing::Rect & rect,float progress)82 void GEWavyRippleLightShader::MakeDrawingShader(const Drawing::Rect& rect, float progress)
83 {
84 drShader_ = MakeWavyRippleLightShader(rect);
85 }
86
GetWavyRippleLightBuilder()87 std::shared_ptr<Drawing::RuntimeShaderBuilder> GEWavyRippleLightShader::GetWavyRippleLightBuilder()
88 {
89 thread_local std::shared_ptr<Drawing::RuntimeEffect> wavyRippleLightShaderEffect_ = nullptr;
90
91 if (wavyRippleLightShaderEffect_ == nullptr) {
92 wavyRippleLightShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(WAVY_PROG);
93 }
94 if (wavyRippleLightShaderEffect_ == nullptr) {
95 GE_LOGE("GEWavyRippleLightShader::GetWavyRippleLightBuilder wavyRippleLightShaderEffect_ is nullptr.");
96 return nullptr;
97 }
98 return std::make_shared<Drawing::RuntimeShaderBuilder>(wavyRippleLightShaderEffect_);
99 }
100
MakeWavyRippleLightShader(const Drawing::Rect & rect)101 std::shared_ptr<Drawing::ShaderEffect> GEWavyRippleLightShader::MakeWavyRippleLightShader(const Drawing::Rect& rect)
102 {
103 auto width = rect.GetWidth();
104 auto height = rect.GetHeight();
105 builder_ = GetWavyRippleLightBuilder();
106 builder_->SetUniform("iResolution", width, height);
107 builder_->SetUniform("center", wavyRippleLightParams_.center_.first,
108 wavyRippleLightParams_.center_.second);
109 builder_->SetUniform("radius", std::max(0.0f, wavyRippleLightParams_.radius_));
110 builder_->SetUniform("thickness", std::max(0.01f, wavyRippleLightParams_.thickness_)); // 0.01f: minimum thickness
111 auto wavyRippleLightShader = builder_->MakeShader(nullptr, false);
112 if (wavyRippleLightShader == nullptr) {
113 GE_LOGE("GEWavyRippleLightShader::MakeWavyRippleLightShader wavyRippleLightShader is nullptr.");
114 return nullptr;
115 }
116 return wavyRippleLightShader;
117 }
118
119 } // namespace Rosen
120 } // namespace OHOS