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
17/** Noise */
18highp float idGenerator(vec2 point) {
19    vec2 p = fract(point * vec2(723.123, 236.209));
20    p += dot(p, p + 17.1512);
21    return fract(p.x * p.y);
22}
23
24highp float idGenerator(float value) {
25    return idGenerator(vec2(value, 1.412));
26}
27
28// Noise range of [-1.0, 1.0[ with triangle distribution.
29float triangleNoise(vec2 n) {
30    n  = fract(n * vec2(5.3987, 5.4421));
31    n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
32    float xy = n.x * n.y;
33    // compute in [0..2[ and remap to [-1.0..1.0[
34    return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
35}
36
37// Noise range of [0, 1].
38float valueNoise(vec2 fragCoord) {
39    float scale = 0.021;
40    float2 i = floor(fragCoord * scale);
41    vec2 f = fract(fragCoord * scale);
42
43    float a = idGenerator(i);
44    float b = idGenerator(i + vec2(1.0, 0.0));
45    float c = idGenerator(i + vec2(0.0, 1.0));
46    float d = idGenerator(i + vec2(1.0, 1.0));
47
48    vec2 u = smoothstep(0. ,1. , f);
49
50    float noise = mix(a, b, u.x) +
51                  (c - a) * u.y * (1.0 - u.x) +
52                  (d - b) * u.x * u.y;
53    // Remap the range back to [0,3].
54    return noise / 3.;
55}
56
57/** Transfrom */
58mat2 rotationMat(float angleRad) {
59  float c = cos(angleRad);
60  float s = sin(angleRad);
61  // |  c  -s  |
62  // |  s   c  |
63  return mat2(
64    c, s, // First column.
65    -s, c // second column.
66  );
67}
68
69vec2 rotateAroundPoint(vec2 point, vec2 centerPoint, float angleRad) {
70    return (point - centerPoint) * rotationMat(angleRad) + centerPoint;
71}
72
73/** SDF */
74float sdfCircle(vec2 p, float r) {
75    return length(p) - r;
76}
77
78/** Blend */
79/*
80 * This is the normal blend mode in which the foreground is painted on top of the background based
81 * on the foreground opacity.
82 *
83 * @param b the background color.
84 * @param f the foreground color.
85 * @param o the mask or the foreground alpha.
86 *
87 * Note: this blending function expects the foreground to have premultiplied alpha.
88 */
89vec3 normalBlend(vec3 b, vec3 f, float o) {
90    return b * (1. - o) + f;
91}
92
93float screenBlend(float bgd, float fgd) {
94    return mix(bgd, 1., fgd);
95}
96
97vec3 screenBlend(vec3 bgd, float fgd) {
98    return mix(bgd, vec3(1.), fgd);
99}
100
101vec3 screenBlend(vec3 bgd, vec3 fgd) {
102    return mix(bgd, vec3(1.), fgd);
103}
104
105/*
106 * This is the normal blend mode in which the foreground is painted on top of the background based
107 * on the foreground opacity.
108 *
109 * @param b the background color.
110 * @param f the foreground color.
111 * @param o the mask or the foreground alpha.
112 *
113 * Note: this blending function expects the foreground to NOT have premultiplied alpha.
114 */
115vec3 normalBlendNotPremultiplied(vec3 b, vec3 f, float o) {
116    return mix(b, f, o);
117}
118
119float relativeLuminance(vec3 color) {
120    return dot(vec3(0.2126, 0.7152, 0.0722), color);
121}
122
123/* Adjusts the image color range and black level. */
124vec3 imageRangeConversion(
125    vec3 color, float rangeCompression, float blackLevel, float noise, float intensity) {
126    color *= mix(1., rangeCompression + noise, intensity);
127    color += blackLevel * intensity;
128    return color;
129}
130
131/** Math Utils */
132// function created on Grapher (equation decided by testing in Grapher).
133float wiggle(float time, float wiggleSpeed) {
134    return sin(wiggleSpeed * time + 0.5 * sin(wiggleSpeed * 5. * time))
135           * sin(wiggleSpeed * time) - 0.5;
136}
137
138float map(float value, float inMin, float inMax, float outMin, float outMax) {
139    float v = clamp(value, inMin, inMax);
140    float p = (v - inMin) / (inMax - inMin);
141    return p * (outMax - outMin) + outMin;
142}
143
144// Adjusts the UVs to have the expected rect of the image.
145float2 transformPoint(mat3 transformMatrix, float2 point) {
146    // Convert the point to homogeneous coordinates (x, y, 1)
147    vec3 homogeneousPoint = vec3(point, 1.0);
148    // Multiply the matrix by the point
149    vec3 transformedPoint = transformMatrix * homogeneousPoint;
150    // Convert back to Cartesian coordinates (x, y)
151    return transformedPoint.xy / transformedPoint.z;
152}
153