• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.systemui.surfaceeffects.turbulencenoise
17 
18 import android.graphics.RuntimeShader
19 import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
20 import java.lang.Float.max
21 
22 /** Shader that renders turbulence simplex noise, with no octave. */
23 class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_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 float in_opacity;
33             uniform float in_pixelDensity;
34             layout(color) uniform vec4 in_color;
35             layout(color) uniform vec4 in_backgroundColor;
36         """
37 
38         private const val SHADER_LIB =
39             """
40             float getLuminosity(vec3 c) {
41                 return 0.3*c.r + 0.59*c.g + 0.11*c.b;
42             }
43 
44             vec3 maskLuminosity(vec3 dest, float lum) {
45                 dest.rgb *= vec3(lum);
46                 // Clip back into the legal range
47                 dest = clamp(dest, vec3(0.), vec3(1.0));
48                 return dest;
49             }
50         """
51 
52         private const val MAIN_SHADER =
53             """
54             vec4 main(vec2 p) {
55                 vec2 uv = p / in_size.xy;
56                 uv.x *= in_aspectRatio;
57 
58                 vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
59                 float luma = simplex3d(noiseP) * in_opacity;
60                 vec3 mask = maskLuminosity(in_color.rgb, luma);
61                 vec3 color = in_backgroundColor.rgb + mask * 0.6;
62 
63                 // Add dither with triangle distribution to avoid color banding. Ok to dither in the
64                 // shader here as we are in gamma space.
65                 float dither = triangleNoise(p * in_pixelDensity) / 255.;
66 
67                 // The result color should be pre-multiplied, i.e. [R*A, G*A, B*A, A], thus need to
68                 // multiply rgb with a to get the correct result.
69                 color = (color + dither.rrr) * in_color.a;
70                 return vec4(color, in_color.a);
71             }
72         """
73 
74         private const val TURBULENCE_NOISE_SHADER =
75             ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SHADER_LIB + MAIN_SHADER
76     }
77 
78     /** Sets the number of grid for generating noise. */
setGridCountnull79     fun setGridCount(gridNumber: Float = 1.0f) {
80         setFloatUniform("in_gridNum", gridNumber)
81     }
82 
83     /**
84      * Sets the pixel density of the screen.
85      *
86      * Used it for noise dithering.
87      */
setPixelDensitynull88     fun setPixelDensity(pixelDensity: Float) {
89         setFloatUniform("in_pixelDensity", pixelDensity)
90     }
91 
92     /** Sets the noise color of the effect. */
setColornull93     fun setColor(color: Int) {
94         setColorUniform("in_color", color)
95     }
96 
97     /** Sets the background color of the effect. */
setBackgroundColornull98     fun setBackgroundColor(color: Int) {
99         setColorUniform("in_backgroundColor", color)
100     }
101 
102     /**
103      * Sets the opacity to achieve fade in/ out of the animation.
104      *
105      * Expected value range is [1, 0].
106      */
setOpacitynull107     fun setOpacity(opacity: Float) {
108         setFloatUniform("in_opacity", opacity)
109     }
110 
111     /** Sets the size of the shader. */
setSizenull112     fun setSize(width: Float, height: Float) {
113         setFloatUniform("in_size", width, height)
114         setFloatUniform("in_aspectRatio", width / max(height, 0.001f))
115     }
116 
117     /** Current noise movements in x, y, and z axes. */
118     var noiseOffsetX: Float = 0f
119         private set
120     var noiseOffsetY: Float = 0f
121         private set
122     var noiseOffsetZ: Float = 0f
123         private set
124 
125     /** Sets noise move offset in x, y, and z direction. */
setNoiseMovenull126     fun setNoiseMove(x: Float, y: Float, z: Float) {
127         noiseOffsetX = x
128         noiseOffsetY = y
129         noiseOffsetZ = z
130         setFloatUniform("in_noiseMove", noiseOffsetX, noiseOffsetY, noiseOffsetZ)
131     }
132 }
133