• 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.shaderutil
17 
18 /** Library class that contains 2D signed distance functions. */
19 class SdfShaderLibrary {
20     // language=AGSL
21     companion object {
22         const val CIRCLE_SDF =
23             """
24             float sdCircle(vec2 p, float r) {
25                 return (length(p)-r) / r;
26             }
27 
28             float circleRing(vec2 p, float radius) {
29                 float thicknessHalf = radius * 0.25;
30 
31                 float outerCircle = sdCircle(p, radius + thicknessHalf);
32                 float innerCircle = sdCircle(p, radius);
33 
34                 return subtract(outerCircle, innerCircle);
35             }
36         """
37 
38         const val BOX_SDF =
39             """
40                 float sdBox(vec2 p, vec2 size) {
41                     size = size * 0.5;
42                     vec2 d = abs(p) - size;
43                     return length(max(d, 0.)) + min(max(d.x, d.y), 0.) / size.y;
44                 }
45             """
46 
47         const val ROUNDED_BOX_SDF =
48             """
49             float sdRoundedBox(vec2 p, vec2 size, float cornerRadius) {
50                 size *= 0.5;
51                 cornerRadius *= 0.5;
52                 vec2 d = abs(p) - size + cornerRadius;
53 
54                 float outside = length(max(d, 0.0));
55                 float inside = min(max(d.x, d.y), 0.0);
56 
57                 return (outside + inside - cornerRadius) / size.y;
58             }
59 
60             float roundedBoxRing(vec2 p, vec2 size, float cornerRadius,
61                 float borderThickness) {
62                 float outerRoundBox = sdRoundedBox(p, size + vec2(borderThickness),
63                     cornerRadius + borderThickness);
64                 float innerRoundBox = sdRoundedBox(p, size, cornerRadius);
65                 return subtract(outerRoundBox, innerRoundBox);
66             }
67         """
68 
69         // Used non-trigonometry parametrization and Halley's method (iterative) for root finding.
70         // This is more expensive than the regular circle SDF, recommend to use the circle SDF if
71         // possible.
72         const val ELLIPSE_SDF =
73             """float sdEllipse(vec2 p, vec2 wh) {
74             wh *= 0.5;
75 
76             // symmetry
77             (wh.x > wh.y) ? wh = wh.yx, p = abs(p.yx) : p = abs(p);
78 
79             vec2 u = wh*p, v = wh*wh;
80 
81             float U1 = u.y/2.0;
82             float U2 = v.y-v.x;
83             float U3 = u.x-U2;
84             float U4 = u.x+U2;
85             float U5 = 4.0*U1;
86             float U6 = 6.0*U1;
87             float U7 = 3.0*U3;
88 
89             float t = 0.5;
90             for (int i = 0; i < 3; i ++) {
91                 float F1 = t*(t*t*(U1*t+U3)+U4)-U1;
92                 float F2 = t*t*(U5*t+U7)+U4;
93                 float F3 = t*(U6*t+U7);
94 
95                 t += (F1*F2)/(F1*F3-F2*F2);
96             }
97 
98             t = clamp(t, 0.0, 1.0);
99 
100             float d = distance(p, wh*vec2(1.0-t*t,2.0*t)/(t*t+1.0));
101             d /= wh.y;
102 
103             return (dot(p/wh,p/wh)>1.0) ? d : -d;
104         }
105 
106         float ellipseRing(vec2 p, vec2 wh) {
107             vec2 thicknessHalf = wh * 0.25;
108 
109             float outerEllipse = sdEllipse(p, wh + thicknessHalf);
110             float innerEllipse = sdEllipse(p, wh);
111 
112             return subtract(outerEllipse, innerEllipse);
113         }
114         """
115 
116         const val SHADER_SDF_OPERATION_LIB =
117             """
118             float soften(float d, float blur) {
119                 float blurHalf = blur * 0.5;
120                 return smoothstep(-blurHalf, blurHalf, d);
121             }
122 
123             float subtract(float outer, float inner) {
124                 return max(outer, -inner);
125             }
126         """
127     }
128 }
129