1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.wallpaper.picker.customization.animation.shader
17 
18 import android.graphics.RuntimeShader
19 import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
20 
21 /**
22  * Shader rendered when images are loading. Contains:
23  * - Sparkles
24  * - Clouds
25  * - Displacement map
26  */
27 // TODO (b/281878827): remove this and use loading animation in SystemUIShaderLib when available
28 class CompositeLoadingShader : RuntimeShader(LOADING_SHADER) {
29     // language=AGSL
30     companion object {
31         private const val UNIFORMS =
32             """
33             uniform shader in_background;
34             uniform shader in_sparkleMask;
35             uniform shader in_colorMask;
36             uniform half in_alpha;
37             layout(color) uniform vec4 in_screenColor;
38         """
39 
40         private const val MAIN_SHADER =
41             """ vec4 main(vec2 p) {
42             half4 bgColor = in_background.eval(p);
43             half3 sparkleMask = in_sparkleMask.eval(p).rgb;
44             half3 colorMask = in_colorMask.eval(p).rgb;
45 
46             float sparkleAlpha = smoothstep(0, 0.75, in_alpha);
47             half3 effect = screen(screen(bgColor.rgb, in_screenColor.rgb), colorMask * 0.22)
48                             + sparkleMask * sparkleAlpha;
49             return mix(bgColor, vec4(effect, 1.), in_alpha);
50         }
51         """
52 
53         private const val LOADING_SHADER = UNIFORMS + ShaderUtilLibrary.SHADER_LIB + MAIN_SHADER
54     }
55 
56     /** Sets the overall opacity of the effect. */
setAlphanull57     fun setAlpha(alpha: Float) {
58         setFloatUniform("in_alpha", alpha)
59     }
60 
61     /** Sets the color that is applied with screen blending on top of the background image. */
setScreenColornull62     fun setScreenColor(color: Int) {
63         setColorUniform("in_screenColor", color)
64     }
65 
66     /**
67      * Sets the sparkle layer. Expected to get the color tinted sparkles turbulence noise shader.
68      */
setSparklenull69     fun setSparkle(sparkleTurbulenceMask: RuntimeShader) {
70         setInputShader("in_sparkleMask", sparkleTurbulenceMask)
71     }
72 
73     /** Sets the color layer. Expected to get the color tinted turbulence noise shader. */
setColorTurbulenceMasknull74     fun setColorTurbulenceMask(colorTurbulenceMask: RuntimeShader) {
75         setInputShader("in_colorMask", colorTurbulenceMask)
76     }
77 }
78