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 17struct Rain { 18 highp float dropMask; 19 highp vec2 cellUv; 20}; 21 22/** 23 * Pouring rain. 24 * 25 * @param uv the UV of the fragment where we will display the rain effect. 26 * @param screenAspectRatio the aspect ratio of the fragment where we will display the effect. 27 * @param time the elapsed time. 28 * @param rainGridSize the size of the grid, where each cell contains a main drop and some 29 * dropplets. 30 * @param rainIntensity how many of the cells will contain drops. Value from 0 (no rain) to 1 31 * (each cell contains a drop). 32 * 33 * @returns float with the rain info. 34 */ 35Rain generateRain( 36 // UVs of the target fragment (normalized). 37 in vec2 uv, 38 in float screenAspectRatio, 39 in float time, 40 in vec2 rainGridSize, 41 in float rainIntensity 42) { 43 /* Grid. */ 44 // Number of rows and columns (each one is a cell, a drop). 45 float cellAspectRatio = rainGridSize.x / rainGridSize.y; 46 // Aspect ratio impacts visible cells. 47 rainGridSize.y /= screenAspectRatio; 48 // scale the UV to allocate number of rows and columns. 49 vec2 gridUv = uv * rainGridSize; 50 // Invert y (otherwise it goes from 0=top to 1=bottom). 51 gridUv.y = 1. - gridUv.y; 52 float verticalGridPos = 0.4 * time; 53 // Move grid vertically down. 54 gridUv.y += verticalGridPos; 55 // Generate column id, to offset columns vertically (so rain is not aligned). 56 float columnId = idGenerator(floor(gridUv.x)); 57 gridUv.y += columnId * 2.6; 58 59 /* Cell. */ 60 // Get the cell ID based on the grid position. Value from 0 to 1. 61 float cellId = idGenerator(floor(gridUv)); 62 // For each cell, we set the internal UV from -0.5 (left, bottom) to 0.5 (right, top). 63 vec2 cellUv = fract(gridUv) - 0.5; 64 65 float intensity = idGenerator(floor(vec2(cellId * 8.16, 27.2))); 66 if (intensity < 1. - rainIntensity) { 67 return Rain(0.0, cellUv); 68 } 69 70 /* Cell-id-based variations. */ 71 // Adjust time based on columnId. 72 time += columnId * 7.1203; 73 // Adjusts scale of each drop (higher is smaller). 74 float scaleVariation = 1.0 - 0.3 * cellId; 75 float opacityVariation = (1. - 0.9 * cellId); 76 77 /* Cell drop. */ 78 // Define the start based on the cell id. 79 float horizontalStart = 0.8 * (cellId - 0.5); 80 81 // Calculate drop. 82 vec2 dropPos = cellUv; 83 dropPos.y += -0.052; 84 dropPos.x += horizontalStart; 85 dropPos *= scaleVariation * vec2(14.2, 2.728); 86 // Create the drop. 87 float dropMask = smoothstep( 88 0., 89 // Adjust the opacity. 90 .80 + 3. * cellId, 91 // Adjust the shape. 92 1. - length(vec2(dropPos.x, (dropPos.y - dropPos.x * dropPos.x))) 93 ); 94 95 return Rain(dropMask, cellUv); 96} 97