diff options
| author | 2023-03-09 21:53:10 +0000 | |
|---|---|---|
| committer | 2023-03-13 17:39:46 +0000 | |
| commit | 0458f10bffa630310934adf61c9eb92537b5b39f (patch) | |
| tree | 37598f744dece33c51e04f19e16bcbb19128636c | |
| parent | 73ec965c30a42287ce23ffe1f39f497a55eed957 (diff) | |
Add fractal noise support in TurbulenceNoiseShader
Bug: 271134655
Test: Manual, atest TurbulenceNoiseShaderTest
Change-Id: I7e6cd67a7c8316200be9abbc4ef14b608c6ce882
3 files changed, 99 insertions, 22 deletions
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt index d78e0c153db8..280e7ed9ea2e 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt @@ -53,6 +53,19 @@ class ShaderUtilLibrary { cos(p.y * 0.01 + time * 0.005931)) * distort_amount_xy; } + // Perceived luminosity (L′), not absolute luminosity. + half getLuminosity(vec3 c) { + return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b; + } + + // Creates a luminosity mask and clamp to the legal range. + vec3 maskLuminosity(vec3 dest, float lum) { + dest.rgb *= vec3(lum); + // Clip back into the legal range + dest = clamp(dest, vec3(0.), vec3(1.0)); + return dest; + } + // Return range [-1, 1]. vec3 hash(vec3 p) { p = fract(p * vec3(.3456, .1234, .9876)); @@ -62,14 +75,14 @@ class ShaderUtilLibrary { } // Skew factors (non-uniform). - const float SKEW = 0.3333333; // 1/3 - const float UNSKEW = 0.1666667; // 1/6 + const half SKEW = 0.3333333; // 1/3 + const half UNSKEW = 0.1666667; // 1/6 // Return range roughly [-1,1]. // It's because the hash function (that returns a random gradient vector) returns // different magnitude of vectors. Noise doesn't have to be in the precise range thus // skipped normalize. - float simplex3d(vec3 p) { + half simplex3d(vec3 p) { // Skew the input coordinate, so that we get squashed cubical grid vec3 s = floor(p + (p.x + p.y + p.z) * SKEW); @@ -143,6 +156,22 @@ class ShaderUtilLibrary { // Should multiply by the possible max contribution to adjust the range in [-1,1]. return dot(vec4(32.), nc); } + + // Random rotations. + // The way you create fractal noise is layering simplex noise with some rotation. + // To make random cloud looking noise, the rotations should not align. (Otherwise it + // creates patterned noise). + // Below rotations only rotate in one axis. + const mat3 rot1 = mat3(1.0, 0. ,0., 0., 0.15, -0.98, 0., 0.98, 0.15); + const mat3 rot2 = mat3(-0.95, 0. ,-0.3, 0., 1., 0., 0.3, 0., -0.95); + const mat3 rot3 = mat3(1.0, 0. ,0., 0., -0.44, -0.89, 0., 0.89, -0.44); + + // Octave = 4 + // Divide each coefficient by 3 to produce more grainy noise. + half simplex3d_fractal(vec3 mat) { + return 0.675 * simplex3d(mat * rot1) + 0.225 * simplex3d(2.0 * mat * rot2) + + 0.075 * simplex3d(4.0 * mat * rot3) + 0.025 * simplex3d(8.0 * mat); + } """ } } diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt index 7456c4334f0f..0e2266734274 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt @@ -19,8 +19,13 @@ import android.graphics.RuntimeShader import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary import java.lang.Float.max -/** Shader that renders turbulence simplex noise, with no octave. */ -class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) { +/** + * Shader that renders turbulence simplex noise, by default no octave. + * + * @param useFractal whether to use fractal noise (4 octaves). + */ +class TurbulenceNoiseShader(useFractal: Boolean = false) : + RuntimeShader(if (useFractal) FRACTAL_NOISE_SHADER else SIMPLEX_NOISE_SHADER) { // language=AGSL companion object { private const val UNIFORMS = @@ -35,21 +40,7 @@ class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) { layout(color) uniform vec4 in_backgroundColor; """ - private const val SHADER_LIB = - """ - float getLuminosity(vec3 c) { - return 0.3*c.r + 0.59*c.g + 0.11*c.b; - } - - vec3 maskLuminosity(vec3 dest, float lum) { - dest.rgb *= vec3(lum); - // Clip back into the legal range - dest = clamp(dest, vec3(0.), vec3(1.0)); - return dest; - } - """ - - private const val MAIN_SHADER = + private const val SIMPLEX_SHADER = """ vec4 main(vec2 p) { vec2 uv = p / in_size.xy; @@ -71,8 +62,26 @@ class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) { } """ - private const val TURBULENCE_NOISE_SHADER = - ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SHADER_LIB + MAIN_SHADER + private const val FRACTAL_SHADER = + """ + vec4 main(vec2 p) { + vec2 uv = p / in_size.xy; + uv.x *= in_aspectRatio; + + vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum; + float luma = simplex3d_fractal(noiseP) * in_opacity; + vec3 mask = maskLuminosity(in_color.rgb, luma); + vec3 color = in_backgroundColor.rgb + mask * 0.6; + + // Skip dithering. + return vec4(color * in_color.a, in_color.a); + } + """ + + private const val SIMPLEX_NOISE_SHADER = + ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SIMPLEX_SHADER + private const val FRACTAL_NOISE_SHADER = + ShaderUtilLibrary.SHADER_LIB + UNIFORMS + FRACTAL_SHADER } /** Sets the number of grid for generating noise. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt new file mode 100644 index 000000000000..71bd51174452 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.surfaceeffects.turbulencenoise + +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class TurbulenceNoiseShaderTest : SysuiTestCase() { + + private lateinit var turbulenceNoiseShader: TurbulenceNoiseShader + + @Test + fun compliesSimplexNoise() { + turbulenceNoiseShader = TurbulenceNoiseShader() + } + + @Test + fun compliesFractalNoise() { + turbulenceNoiseShader = TurbulenceNoiseShader(useFractal = true) + } +} |