• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
17uniform shader foreground;
18uniform shader background;
19uniform shader accumulatedSnow;
20uniform shader noise;
21uniform float2 gridSize;
22uniform float time;
23uniform float screenAspectRatio;
24uniform float2 screenSize;
25uniform mat3 transformMatrixBitmap;
26uniform mat3 transformMatrixWeather;
27
28#include "shaders/constants.agsl"
29#include "shaders/utils.agsl"
30#include "shaders/snow.agsl"
31
32// Snow tint.
33const vec4 snowColor = vec4(1., 1., 1., 0.95);
34// Background tint
35const vec4 bgdTint = vec4(0.8, 0.8, 0.8, 0.07);
36
37// Indices of the different snow layers.
38const float farthestSnowLayerIndex = 6;
39const float midSnowLayerIndex = 2;
40const float closestSnowLayerIndex = 0;
41
42vec4 main(float2 fragCoord) {
43    /**
44     * The effect is consisted of 2 image textures (foreground and background) + 10 layers of
45     * snow + 1 layer of snow accumulation. Below describes the rendering order (back to front):
46     * 1. Background
47     * 2. Background snow layers (from farthest layer to mid layer)
48     * 3. Foreground
49     * 4. Snow accumulation layer (on subject)
50     * 5. Foreground snow layers (from mid layer to closest layer)
51     */
52
53    // Apply transform matrix to fragCoord
54    float2 adjustedUv = transformPoint(transformMatrixBitmap, fragCoord);
55    // Calculate uv for snow based on transformed coordinates
56    float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize;
57    float2 uvAdjusted = vec2(uv.x, uv.y / screenAspectRatio);
58
59    vec4 colorForeground = foreground.eval(adjustedUv);
60    vec4 colorBackground = background.eval(adjustedUv);
61
62     // Adjusts contrast and brightness.
63    float noiseT = triangleNoise(fragCoord.xy + vec2(12.31, 1024.1241));
64    colorBackground.rgb =
65        imageRangeConversion(colorBackground.rgb, 0.88, 0.02, noiseT * 0.025, intensity);
66    colorForeground.rgb =
67        imageRangeConversion(colorForeground.rgb, 0.88, 0.02, noiseT * 0.025, intensity);
68
69    // 1. Draw background.
70    vec4 color = colorBackground;
71
72    // Add slight tint to the background.
73    color.rgb = normalBlendNotPremultiplied(color.rgb, bgdTint.rgb, bgdTint.a);
74
75    // 2. Generate snow layers behind the subject.
76    if (colorForeground.a == 0) {
77        for (float i = farthestSnowLayerIndex; i > midSnowLayerIndex; i--) {
78            Snow snow = generateSnow(
79                uv,
80                screenAspectRatio,
81                time,
82                gridSize,
83                /* layer number = */ i,
84                closestSnowLayerIndex,
85                farthestSnowLayerIndex);
86
87            color.rgb =
88                normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * snow.flakeMask);
89        }
90    }
91
92    // 3. Add the foreground layer. Any effect from here will be in front of the subject.
93    color.rgb = normalBlend(color.rgb, colorForeground.rgb, colorForeground.a);
94
95    // 4. Add accumulated snow layer.
96    // Load noise texture to give "fluffy-ness" to the snow. Displace the sampling of the noise.
97    vec3 cloudsNoise = noise.eval(uvAdjusted * 7000 + vec2(fragCoord.y, -fragCoord.x)).rgb;
98    // Add dither to give texture to the snow and ruffle the edges.
99    float dither = abs(triangleNoise(fragCoord * 0.01));
100
101    // Get the accumulated snow buffer. r contains its mask, g contains some random noise.
102    vec2 accSnow = accumulatedSnow.eval(adjustedUv).rg;
103    // Sharpen the mask of the accumulated snow, but not in excess.
104    float accSnowMask = smoothstep( (1.-intensity), 1.0, /* mask= */accSnow.r);
105    if (accSnowMask > 0) {
106        // Makes the edges of the snow layer accumulation rougher.
107        accSnowMask = map(accSnowMask, 1. - cloudsNoise.b - 0.3 * dither, 1., 0., 1.);
108        // Load snow texture and dither. Make it have gray-ish values.
109        float accSnowTexture = smoothstep(0.2, 0.7, /* noise= */ accSnow.g) * 0.7;
110        accSnowTexture = map(accSnowTexture, dither - 1, 1, 0, 1);
111        // Adjust snow texture coverage/shape.
112        accSnowTexture = map(accSnowTexture, 0.67, 0.8, 0, 1);
113        accSnowMask = map(accSnowMask, 0., 1., 0., 1.- 0.6 * accSnowTexture - 0.35 * dither);
114
115        color.rgb = normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * accSnowMask);
116    }
117
118    // 5. Generate snow in front of the subject.
119    for (float i = midSnowLayerIndex; i >= closestSnowLayerIndex; i--) {
120        Snow snow = generateSnow(
121            uv,
122            screenAspectRatio,
123            time,
124            gridSize,
125            /* layer number = */ i,
126            closestSnowLayerIndex,
127            farthestSnowLayerIndex);
128
129        color.rgb =
130            normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * snow.flakeMask);
131    }
132
133    return color;
134}
135