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 ROUNDED_BOX_SDF = 39 """ 40 float sdRoundedBox(vec2 p, vec2 size, float cornerRadius) { 41 size *= 0.5; 42 cornerRadius *= 0.5; 43 vec2 d = abs(p)-size+cornerRadius; 44 45 float outside = length(max(d, 0.0)); 46 float inside = min(max(d.x, d.y), 0.0); 47 48 return (outside+inside-cornerRadius)/size.y; 49 } 50 51 float roundedBoxRing(vec2 p, vec2 size, float cornerRadius, 52 float borderThickness) { 53 float outerRoundBox = sdRoundedBox(p, size + vec2(borderThickness), 54 cornerRadius + borderThickness); 55 float innerRoundBox = sdRoundedBox(p, size, cornerRadius); 56 return subtract(outerRoundBox, innerRoundBox); 57 } 58 """ 59 60 // Used non-trigonometry parametrization and Halley's method (iterative) for root finding. 61 // This is more expensive than the regular circle SDF, recommend to use the circle SDF if 62 // possible. 63 const val ELLIPSE_SDF = 64 """float sdEllipse(vec2 p, vec2 wh) { 65 wh *= 0.5; 66 67 // symmetry 68 (wh.x > wh.y) ? wh = wh.yx, p = abs(p.yx) : p = abs(p); 69 70 vec2 u = wh*p, v = wh*wh; 71 72 float U1 = u.y/2.0; 73 float U2 = v.y-v.x; 74 float U3 = u.x-U2; 75 float U4 = u.x+U2; 76 float U5 = 4.0*U1; 77 float U6 = 6.0*U1; 78 float U7 = 3.0*U3; 79 80 float t = 0.5; 81 for (int i = 0; i < 3; i ++) { 82 float F1 = t*(t*t*(U1*t+U3)+U4)-U1; 83 float F2 = t*t*(U5*t+U7)+U4; 84 float F3 = t*(U6*t+U7); 85 86 t += (F1*F2)/(F1*F3-F2*F2); 87 } 88 89 t = clamp(t, 0.0, 1.0); 90 91 float d = distance(p, wh*vec2(1.0-t*t,2.0*t)/(t*t+1.0)); 92 d /= wh.y; 93 94 return (dot(p/wh,p/wh)>1.0) ? d : -d; 95 } 96 97 float ellipseRing(vec2 p, vec2 wh) { 98 vec2 thicknessHalf = wh * 0.25; 99 100 float outerEllipse = sdEllipse(p, wh + thicknessHalf); 101 float innerEllipse = sdEllipse(p, wh); 102 103 return subtract(outerEllipse, innerEllipse); 104 } 105 """ 106 107 const val SHADER_SDF_OPERATION_LIB = 108 """ 109 float soften(float d, float blur) { 110 float blurHalf = blur * 0.5; 111 return smoothstep(-blurHalf, blurHalf, d); 112 } 113 114 float subtract(float outer, float inner) { 115 return max(outer, -inner); 116 } 117 """ 118 } 119 } 120