1/*
2 * Copyright (C) 2024 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
17uniform shader texture;
18uniform float time;
19uniform float screenAspectRatio;
20uniform float2 screenSize;
21uniform half intensity;
22
23#include "shaders/constants.agsl"
24#include "shaders/utils.agsl"
25#include "shaders/glass_rain.agsl"
26#include "shaders/rain_constants.agsl"
27
28vec4 main(float2 fragCoord) {
29    // 0. Add a bit of noise so that the droplets are not perfect circles.
30    fragCoord += vec2(valueNoise(fragCoord) * 0.015 - 0.0025);
31
32    float2 uv = fragCoord / screenSize;
33
34    // 1. Generate small glass rain.
35    GlassRain smallDrippingRain = generateGlassRain(
36         uv,
37         screenAspectRatio,
38         time,
39         /* Grid size = */ vec2(4.0, 2.0),
40         intensity);
41    float dropMask = smallDrippingRain.dropMask;
42    float droppletsMask = smallDrippingRain.droppletsMask;
43    float trailMask = smallDrippingRain.trailMask;
44    vec2 dropUvMasked = smallDrippingRain.drop * dropMask;
45    vec2 droppletsUvMasked = smallDrippingRain.dropplets * droppletsMask;
46
47    // 2. Generate medium size glass rain.
48    GlassRain medDrippingRain = generateGlassRain(
49          uv,
50          screenAspectRatio,
51          time * 1.267,
52          /* Grid size = */ vec2(3.5, 1.5),
53          intensity);
54
55    // 3. Combine those two glass rains.
56    dropMask = max(medDrippingRain.dropMask, dropMask);
57    droppletsMask = max(medDrippingRain.droppletsMask, droppletsMask);
58    trailMask = max(medDrippingRain.trailMask, trailMask);
59    dropUvMasked = mix(dropUvMasked,
60        medDrippingRain.drop * medDrippingRain.dropMask, medDrippingRain.dropMask);
61    droppletsUvMasked = mix(droppletsUvMasked,
62        medDrippingRain.dropplets * medDrippingRain.droppletsMask, medDrippingRain.droppletsMask);
63
64    // 4. Add static rain droplets on the glass surface. (They stay in place and dissapate.)
65    vec3 staticRain = generateStaticGlassRain(uv, screenAspectRatio, time, intensity);
66    dropMask = max(dropMask, staticRain.z);
67    dropUvMasked = mix(dropUvMasked, staticRain.xy * staticRain.z, staticRain.z);
68
69    // 5. Distort uv for the rain drops and dropplets.
70    float distortionDrop = -0.1;
71    vec2 uvDiffractionOffsets =
72        distortionDrop * dropUvMasked;
73    vec2 s = screenSize;
74    // Ensure the diffracted image in drops is not inverted.
75    s.y *= -1;
76
77    vec4 color = texture.eval(fragCoord);
78    vec3 sampledColor = texture.eval(fragCoord + uvDiffractionOffsets * s).rgb;
79    color.rgb = mix(color.rgb, sampledColor, max(dropMask, droppletsMask));
80
81    // 6. Add color tint to the rain drops.
82    color.rgb = mix(
83        color.rgb,
84        dropTint,
85        dropTintIntensity * smoothstep(0.7, 1., max(dropMask, droppletsMask)));
86
87    // 7. Add highlight to the drops.
88    color.rgb = mix(
89        color.rgb,
90        highlightColor,
91        highlightIntensity
92            * smoothstep(0.05, 0.08, max(dropUvMasked * 1.7, droppletsUvMasked * 2.6)).x);
93
94    // 8. Add shadows to the drops.
95    color.rgb = mix(
96        color.rgb,
97        contactShadowColor,
98        dropShadowIntensity *
99            smoothstep(0.055, 0.1, max(length(dropUvMasked * 1.7),
100                length(droppletsUvMasked * 1.9))));
101
102    return color;
103}