• 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 
18 #include "ge_log.h"
19 #include "ge_ripple_shader_mask.h"
20 #include "utils/ge_trace.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 namespace Drawing {
25 
GERippleShaderMask(const GERippleShaderMaskParams & param)26 GERippleShaderMask::GERippleShaderMask(const GERippleShaderMaskParams& param) : param_(param) {}
27 
GenerateDrawingShader(float width,float height) const28 std::shared_ptr<ShaderEffect> GERippleShaderMask::GenerateDrawingShader(float width, float height) const
29 {
30     GE_TRACE_NAME_FMT("GERippleShaderMask::GenerateDrawingShader, Type: %s, Width: %g, Height: %g",
31         Drawing::GE_MASK_RIPPLE, width, height);
32     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder = nullptr;
33     builder = GetRippleShaderMaskBuilder();
34     if (!builder) {
35         LOGE("GERippleShaderMask::GenerateDrawingShaderHas builder error");
36         return nullptr;
37     }
38     builder->SetUniform("iResolution", width, height);
39     builder->SetUniform("centerPos", param_.center_.first, param_.center_.second);
40     builder->SetUniform("rippleRadius", param_.radius_);
41     builder->SetUniform("rippleWidth", param_.width_);
42     builder->SetUniform("widthCenterOffset", param_.widthCenterOffset_);
43     auto rippleMaskEffectShader = builder->MakeShader(nullptr, false);
44     if (!rippleMaskEffectShader) {
45         LOGE("GERippleShaderMask::GenerateDrawingShaderHas effect error");
46     }
47     return rippleMaskEffectShader;
48 }
49 
GetRippleShaderMaskBuilder() const50 std::shared_ptr<Drawing::RuntimeShaderBuilder> GERippleShaderMask::GetRippleShaderMaskBuilder() const
51 {
52     thread_local std::shared_ptr<Drawing::RuntimeShaderBuilder> rippleShaderMaskBuilder = nullptr;
53     if (rippleShaderMaskBuilder) {
54         return rippleShaderMaskBuilder;
55     }
56 
57     static constexpr char prog[] = R"(
58         uniform half2 iResolution;
59         uniform half2 centerPos;
60         uniform half rippleRadius;
61         uniform half rippleWidth;
62         uniform half widthCenterOffset;
63 
64         half4 main(vec2 fragCoord)
65         {
66             half2 uv = fragCoord.xy/iResolution.xy;
67             half screenRatio = iResolution.x/iResolution.y;
68             // Mask Info
69             half2 MaskCenterUVs = uv - centerPos;
70             MaskCenterUVs.x *= screenRatio;
71             half offsetWidth = rippleWidth * widthCenterOffset;
72             half uvDistance = length(MaskCenterUVs) - rippleRadius;
73             half maskAlpha = smoothstep(rippleWidth, offsetWidth, uvDistance)
74                             * smoothstep(-rippleWidth, offsetWidth, uvDistance);
75             return half4(maskAlpha);
76         }
77     )";
78 
79     auto rippleShaderMaskEffect = Drawing::RuntimeEffect::CreateForShader(prog);
80     if (!rippleShaderMaskEffect) {
81         LOGE("GERippleShaderMask::GetRippleShaderMaskBuilder effect error");
82         return nullptr;
83     }
84 
85     rippleShaderMaskBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(rippleShaderMaskEffect);
86     return rippleShaderMaskBuilder;
87 }
88 
GenerateDrawingShaderHasNormal(float width,float height) const89 std::shared_ptr<ShaderEffect> GERippleShaderMask::GenerateDrawingShaderHasNormal(float width, float height) const
90 {
91     GE_TRACE_NAME_FMT("GERippleShaderMask::GenerateDrawingShaderHasNormal, Type: %s, Width: %g, Height: %g",
92         Drawing::GE_MASK_RIPPLE, width, height);
93     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder = nullptr;
94     builder = GetRippleShaderNormalMaskBuilder();
95     if (!builder) {
96         LOGE("GERippleShaderMask::GenerateDrawingShaderHasNormal builder error");
97         return nullptr;
98     }
99     builder->SetUniform("iResolution", width, height);
100     builder->SetUniform("centerPos", param_.center_.first, param_.center_.second);
101     builder->SetUniform("rippleRadius", param_.radius_);
102     builder->SetUniform("rippleWidth", param_.width_);
103     builder->SetUniform("widthCenterOffset", param_.widthCenterOffset_);
104     auto rippleMaskEffectShader = builder->MakeShader(nullptr, false);
105     if (!rippleMaskEffectShader) {
106         LOGE("GERippleShaderMask::GenerateDrawingShaderHasNormal effect error");
107     }
108     return rippleMaskEffectShader;
109 }
110 
GetRippleShaderNormalMaskBuilder() const111 std::shared_ptr<Drawing::RuntimeShaderBuilder> GERippleShaderMask::GetRippleShaderNormalMaskBuilder() const
112 {
113     thread_local std::shared_ptr<Drawing::RuntimeShaderBuilder> rippleShaderMaskNormalBuilder = nullptr;
114     if (rippleShaderMaskNormalBuilder) {
115         return rippleShaderMaskNormalBuilder;
116     }
117 
118     static constexpr char prog[] = R"(
119         uniform half2 iResolution;
120         uniform half2 centerPos;
121         uniform half rippleRadius;
122         uniform half rippleWidth;
123         uniform half widthCenterOffset;
124 
125         half4 main(vec2 fragCoord)
126         {
127             half2 uv = fragCoord.xy/iResolution.xy;
128             half screenRatio = iResolution.x/iResolution.y;
129             // Mask Info
130             half2 MaskCenterUVs = uv - centerPos;
131             MaskCenterUVs.x *= screenRatio;
132             half dist = length(MaskCenterUVs);
133             half offsetWidth = rippleWidth * widthCenterOffset;
134             half uvDistance = dist - rippleRadius - offsetWidth;
135             uvDistance = clamp(uvDistance, -1.0, 1.0);
136 
137             half mask = smoothstep(rippleWidth - offsetWidth, 0.0, uvDistance) *
138                         smoothstep(-rippleWidth - offsetWidth, 0.0, uvDistance);
139 
140             half2 directionVector = MaskCenterUVs * (uvDistance * mask * 0.5 / (dist + 1e-4)) + 0.5;
141             return half4(directionVector, 1.0, mask);
142         }
143     )";
144 
145     auto rippleShaderMaskNormalEffect = Drawing::RuntimeEffect::CreateForShader(prog);
146     if (!rippleShaderMaskNormalEffect) {
147         LOGE("GERippleShaderMask::GetRippleShaderNormalMaskBuilder effect error");
148         return nullptr;
149     }
150 
151     rippleShaderMaskNormalBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(rippleShaderMaskNormalEffect);
152     return rippleShaderMaskNormalBuilder;
153 }
154 
155 } // namespace Drawing
156 } // namespace Rosen
157 } // namespace OHOS