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 float2 uvOffsetFgd; 24uniform float2 uvScaleFgd; 25uniform float2 uvOffsetBgd; 26uniform float2 uvScaleBgd; 27uniform half4 time; 28uniform half screenAspectRatio; 29uniform half2 screenSize; 30uniform half pixelDensity; 31uniform half intensity; 32 33#include "shaders/constants.agsl" 34#include "shaders/utils.agsl" 35#include "shaders/simplex2d.agsl" 36 37const vec3 fogColor = vec3(1.); 38 39vec4 main(float2 fragCoord) { 40 float2 uv = fragCoord / screenSize; 41 uv.y /= screenAspectRatio; 42 43 vec2 timeForeground = vec2(time.x, time.y); 44 vec2 timeBackground = vec2(time.z, time.w); 45 46 /** 47 * The shader is composed by two image textures (foreground and background) and four layers of 48 * fog. The rendering order (back to front) is the following: 49 * - Background 50 * - bgdFogFar (layer 1) / bgdFogClose (layer 2) 51 * - Foreground 52 * - fgdFogFar (layer 1) / fgdFogClose (layer 2) 53 */ 54 55 // Load foreground and blend it with constant solid fog color. 56 vec4 fgd = foreground.eval(fragCoord * uvScaleFgd + uvOffsetFgd); 57 fgd.rgb = mix(fgd.rgb, fogColor, 0.32 * intensity * fgd.a); 58 59 // Load background and blend it with constant solid fog color. 60 vec4 bgd = background.eval(fragCoord * uvScaleBgd + uvOffsetBgd); 61 bgd.rgb = mix(bgd.rgb, fogColor, 0.15 * intensity * bgd.a); 62 63 /* Add first layer: background. */ 64 // set background color as the starting layer. 65 vec4 color = bgd; 66 67 /* Prepare fog layers. */ 68 // Dither to be applied to background noise. 69 float bgdDither = triangleNoise((fragCoord + 0.0002 * timeBackground) * pixelDensity) * 0.1; 70 71 // The furthest fog layer in the background. 72 vec4 bgdFogFar = fog.eval( 73 fogSize * uv + 74 // Moves UV based on time. 75 vec2(timeBackground * 1.5) + 76 // Adds sampling dithering. 77 vec2(bgdDither * 7)); 78 79 // The furthest fog layer in the background. 80 vec4 bgdFogClose = fog.eval( 81 0.5 * fogSize * uv + 82 // Moves UV based on time. 83 vec2(timeBackground * 5.5) + 84 // Adds sampling dithering. 85 vec2(bgdDither * 22)); 86 87 float fgdDither = triangleNoise((fragCoord + 0.003 * timeForeground) * pixelDensity) * 0.07; 88 vec4 fgdFogFar = clouds.eval( 89 0.5 * cloudsSize * uv + 90 // Moves UV based on time. 91 vec2(timeForeground * 10.) + 92 // Adds distosions based on noise. 93 vec2(bgdFogFar.b * 70., bgdFogFar.g * 10) + 94 // Adds sampling dithering. 95 vec2(fgdDither * 10)); 96 vec4 fgdFogClose = clouds.eval( 97 0.5 * cloudsSize * uv + 98 // moves UV based on time. 99 vec2(timeForeground * 72.) + 100 // Adds distosions based on noise. 101 vec2(bgdFogFar.g * 50., bgdFogFar.b * 80) + 102 // Adds sampling dithering. 103 vec2(fgdDither * 8)); 104 105 /* Add second layer: background fog (far or 1, and close or 2). */ 106 // background, layer 1. 107 float bgdFogLayer1 = 108 map(bgdFogFar.r, 0.2, 1., fgdFogFar.g, 0.8) * 109 bgdFogFar.r * 110 (1. - 0.7 * bgdDither); 111 // Blend with background. 112 color.rgb = normalBlendWithWhiteSrc(color.rgb, bgdFogLayer1 * intensity); 113 114 // background, layer 2. 115 float fbmSimplexWorley = bgdFogClose.g * 0.625 + bgdFogClose.b * 0.3755; 116 float bgdFogLayer2 = 117 0.85 * 118 smoothstep(0.88 * fbmSimplexWorley, 1., bgdFogClose.r) * 119 (1.- 0.4 * bgdDither); 120 // Blend with background. 121 color.rgb = normalBlendWithWhiteSrc(color.rgb, bgdFogLayer2 * intensity); 122 123 /* Add third layer: foreground. */ 124 // Add the foreground. Any effect from here will be in front of the subject. 125 color.rgb = normalBlend(color.rgb, fgd.rgb, fgd.a); 126 127 /* Add fourth layer: foreground fog (far or 1, and close or 2). */ 128 // foreground fog, layer 1. 129 float fgdFogLayer1 = 130 fgdFogFar.r * 131 0.5 * (1. - fgdDither); 132 color.rgb = normalBlendWithWhiteSrc(color.rgb, fgdFogLayer1 * intensity); 133 134 // Foreground fog, layer 2. 135 float fgdFogLayer2 = 136 fgdFogClose.g * 137 0.4 * (1. - fgdDither); 138 color.rgb = normalBlendWithWhiteSrc(color.rgb, fgdFogLayer2 * intensity); 139 140 return color; 141}