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