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 fog; 20uniform shader clouds; 21uniform half2 fogSize; 22uniform half2 cloudsSize; 23uniform half4 time; 24uniform half screenAspectRatio; 25uniform half2 screenSize; 26uniform half pixelDensity; 27uniform half intensity; 28uniform mat3 transformMatrixBitmap; 29uniform mat3 transformMatrixWeather; 30 31#include "shaders/constants.agsl" 32#include "shaders/utils.agsl" 33#include "shaders/simplex2d.agsl" 34 35const vec3 fogScrimColor = vec3(0.20); 36const vec3 fogColor = vec3(1.0); 37 38vec4 main(float2 fragCoord) { 39 vec2 timeForeground = vec2(time.x, time.y); 40 vec2 timeBackground = vec2(time.z, time.w); 41 42 /** 43 * The shader is composed by two image textures (foreground and background) and four layers of 44 * fog. The rendering order (back to front) is the following: 45 * - Background 46 * - bgdFogFar (layer 1) / bgdFogClose (layer 2) 47 * - Foreground 48 * - fgdFogFar (layer 1) / fgdFogClose (layer 2) 49 */ 50 float2 adjustedCoord = transformPoint(transformMatrixBitmap, fragCoord); 51 float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize; 52 uv.y /= screenAspectRatio; 53 54 // Load background and foreground. 55 vec4 fgd = foreground.eval(adjustedCoord); 56 vec4 bgd = background.eval(adjustedCoord); 57 58 // Adjusts contrast and brightness. 59 float noise = 0.025 * triangleNoise(fragCoord.xy + vec2(12.31, 1024.1241)); 60 bgd.rgb = imageRangeConversion(bgd.rgb, 0.8, 0.02, noise, intensity); 61 fgd.rgb = imageRangeConversion(fgd.rgb, 0.8, 0.02, noise, intensity); 62 63 // Blend them with constant solid fog color. 64 bgd.rgb = mix(bgd.rgb, fogScrimColor, 0.14 * intensity * bgd.a); 65 fgd.rgb = mix(fgd.rgb, fogScrimColor, 0.12 * intensity * fgd.a); 66 /* Add first layer: background. */ 67 // set background color as the starting layer. 68 vec4 color = bgd; 69 70 /* Prepare fog layers. */ 71 // Dither to be applied to background noise. 72 float bgdDither = triangleNoise((fragCoord + 0.0002 * timeBackground) * pixelDensity) * 0.075; 73 74 // The furthest fog layer in the background. 75 vec4 bgdFogFar = fog.eval( 76 fogSize * uv + 77 // Moves UV based on time. 78 vec2(timeBackground * 1.5) + 79 // Adds sampling dithering. 80 vec2(bgdDither * 14)); 81 82 // The furthest fog layer in the background. 83 vec4 bgdFogClose = fog.eval( 84 0.5 * fogSize * uv + 85 // Moves UV based on time. 86 vec2(timeBackground * 5.5) + 87 // Adds sampling dithering. 88 vec2(bgdDither * 40)); 89 90 float fgdDither = triangleNoise((fragCoord + 0.003 * timeForeground) * pixelDensity) * 0.09; 91 vec4 fgdFogFar = clouds.eval( 92 0.5 * cloudsSize * uv + 93 // Moves UV based on time. 94 vec2(timeForeground * 15.) + 95 // Adds distosions based on noise. 96 vec2(bgdFogFar.b * 20., bgdFogFar.g * 2) + 97 // Adds sampling dithering. 98 vec2(fgdDither * 12)); 99 vec4 fgdFogClose = clouds.eval( 100 0.5 * cloudsSize * uv + 101 // moves UV based on time. 102 vec2(timeForeground * 32.) + 103 // Adds distosions based on noise. 104 vec2(bgdFogFar.g * 2., bgdFogFar.b * 10) + 105 // Adds sampling dithering. 106 vec2(fgdDither * 22)); 107 108 // Undo aspect ratio adjustment. 109 uv.y *= screenAspectRatio; 110 111 /* Add second layer: background fog (far or 1, and close or 2). */ 112 // background, layer 1. 113 float fogHeightVariation; 114 if (uv.y < 0.38) { 115 fogHeightVariation = 0.03 * cos(uv.x * 2.5 + timeBackground.x * 0.07); 116 float bgFogFarCombined = map(bgdFogFar.r, 0.74, 0.9, fgdFogFar.g, 0.95) * bgdFogFar.r; 117 float bgdFogLayer1 = 118 bgFogFarCombined * 119 smoothstep(-0.1, 0.05, uv.y + fogHeightVariation) * 120 (1. - smoothstep(0.15, 0.35, uv.y + fogHeightVariation)); 121 bgdFogLayer1 *= 1.1; 122 bgdFogLayer1 += 0.55 * bgdDither; 123 bgdFogLayer1 = clamp(bgdFogLayer1, 0., 1.); 124 // Blend with background. 125 color.rgb = 126 normalBlendNotPremultiplied(color.rgb, fogColor * 0.8, bgdFogLayer1 * intensity); 127 } 128 129 if (uv.y > 0.23 && uv.y < 0.87) { 130 // background, layer 2. 131 float fbmSimplexWorley = bgdFogClose.g * 0.625 + bgdFogClose.b * 0.3755; 132 float bgFogloseCombined = smoothstep(0.88 * fbmSimplexWorley, 1., bgdFogClose.r); 133 fogHeightVariation = 0.02 * sin(uv.x * 2.5 + timeBackground.x * 0.09); 134 float bgdFogLayer2 = 135 bgFogloseCombined * 136 smoothstep(0.25, 0.55, uv.y + fogHeightVariation) * 137 (1. - smoothstep(0.7, 0.85, uv.y + fogHeightVariation)); 138 bgdFogLayer2 *= 1.2; 139 bgdFogLayer2 += 0.6 * bgdDither; 140 bgdFogLayer2 = clamp(bgdFogLayer2, 0., 1.); 141 // Blend with background. 142 color.rgb = 143 normalBlendNotPremultiplied(color.rgb, fogColor * 0.85, bgdFogLayer2 * intensity); 144 } 145 146 /* Add third layer: foreground. */ 147 // Add the foreground. Any effect from here will be in front of the subject. 148 color.rgb = normalBlend(color.rgb, fgd.rgb, fgd.a); 149 150 /* Add fourth layer: foreground fog (far or 1, and close or 2). */ 151 // foreground fog, layer 1. 152 if (uv.y > 0.32) { 153 fogHeightVariation = 0.1 * cos(uv.x * 2.5 + timeForeground.x * 0.085); 154 float fgdFogLayer1 = 155 mix( 156 fgdFogFar.r, 157 1., 158 0.5 * intensity * smoothstep(0.72, 0.92, uv.y + fogHeightVariation)) * 159 smoothstep(0.42, 0.82, uv.y + fogHeightVariation); 160 fgdFogLayer1 *= 1.3; 161 fgdFogLayer1 += 0.6 * fgdDither; 162 fgdFogLayer1 = clamp(fgdFogLayer1, 0., 1.); 163 color.rgb = 164 normalBlendNotPremultiplied(color.rgb, fogColor * 0.9, fgdFogLayer1 * intensity); 165 } 166 if (uv.y > 0.25) { 167 // Foreground fog, layer 2. 168 fogHeightVariation = 0.05 * sin(uv.x * 2. + timeForeground.y * 0.5); 169 float fgdFogLayer2 = 170 mix( 171 fgdFogClose.g, 172 1., 173 0.65 * intensity * smoothstep(0.85, 1.3, uv.y + fogHeightVariation)) * 174 smoothstep(0.30, 0.90, uv.y + uv.x * 0.09); 175 fgdFogLayer2 *= 1.4; 176 fgdFogLayer2 += 0.6 * fgdDither; 177 fgdFogLayer2 = clamp(fgdFogLayer2, 0., 1.); 178 color.rgb = normalBlendNotPremultiplied(color.rgb, fogColor, fgdFogLayer2 * intensity); 179 } 180 return color; 181}