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 /** Shader that renders sparkles in [CompositeLoadingShader]. */
22 // TODO (b/281878827): remove this and use loading animation in SystemUIShaderLib when available
23 class SparkleShader : RuntimeShader(SPARKLE_SHADER) {
24     // language=AGSL
25     companion object {
26         private const val UNIFORMS =
27             """
28             uniform float in_gridNum;
29             uniform vec3 in_noiseMove;
30             uniform vec2 in_size;
31             uniform float in_aspectRatio;
32             uniform half in_time;
33             uniform half in_pixelDensity;
34             layout(color) uniform vec4 in_color;
35         """
36         private const val MAIN_SHADER =
37             """vec4 main(vec2 p) {
38             vec2 uv = p / in_size.xy;
39             uv.x *= in_aspectRatio;
40             vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
41             // Inverse luminosity per spec.
42             half luma = 1.0 - getLuminosity(vec3(simplex3d(noiseP)));
43             luma = max(/* intensity= */ 1.75 * luma - /* dim= */ 1.3, 0.);
44             float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time);
45 
46             return vec4(maskLuminosity(in_color.rgb * sparkle, luma) * in_color.a, in_color.a);
47         }
48         """
49         private const val SPARKLE_SHADER = UNIFORMS + ShaderUtilLibrary.SHADER_LIB + MAIN_SHADER
50     }
51 
52     /** Sets noise move offset in x, y, and z direction. */
setNoiseMovenull53     fun setNoiseMove(x: Float, y: Float, z: Float) {
54         setFloatUniform("in_noiseMove", x, y, z)
55     }
56 
57     /** Sets the number of grid for generating noise. */
setGridCountnull58     fun setGridCount(gridNumber: Float = 1.0f) {
59         setFloatUniform("in_gridNum", gridNumber)
60     }
61 
62     /** Sets the size of the shader. */
setSizenull63     fun setSize(width: Float, height: Float) {
64         setFloatUniform("in_size", width, height)
65         setFloatUniform("in_aspectRatio", width / java.lang.Float.max(height, 0.001f))
66     }
67 
68     /** Sets the pixel density of the screen. */
setPixelDensitynull69     fun setPixelDensity(pixelDensity: Float) {
70         setFloatUniform("in_pixelDensity", pixelDensity)
71     }
72 
setColornull73     fun setColor(color: Int) {
74         setColorUniform("in_color", color)
75     }
76 
setTimenull77     fun setTime(time: Float) {
78         setFloatUniform("in_time", time)
79     }
80 }
81