Loading iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +19 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.FloatProperty; import android.util.Log; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; Loading @@ -46,6 +47,7 @@ import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags; public class FastBitmapDrawable extends Drawable implements Drawable.Callback { private static final String TAG = "FastBitmapDrawable"; private static final Interpolator ACCEL = new AccelerateInterpolator(); private static final Interpolator DEACCEL = new DecelerateInterpolator(); private static final Interpolator HOVER_EMPHASIZED_DECELERATE_INTERPOLATOR = Loading @@ -67,7 +69,8 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { private boolean mAnimationEnabled = true; protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); public final BitmapInfo mBitmapInfo; // b/404578798 - mBitmapInfo isn't expected to be null, but it is in some cases. @Nullable public final BitmapInfo mBitmapInfo; @Nullable private ColorFilter mColorFilter; Loading Loading @@ -109,6 +112,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { } public FastBitmapDrawable(BitmapInfo info) { if (info == null) { Log.e(TAG, "BitmapInfo should not be null.", new Exception()); } mBitmapInfo = info; setFilterBitmap(true); } Loading Loading @@ -152,6 +158,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { } protected void drawInternal(Canvas canvas, Rect bounds) { if (mBitmapInfo == null) { return; } canvas.drawBitmap(mBitmapInfo.icon, null, bounds, mPaint); } Loading @@ -160,6 +169,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { */ public int getIconColor() { int whiteScrim = setColorAlphaBound(Color.WHITE, WHITE_SCRIM_ALPHA); if (mBitmapInfo == null) { return whiteScrim; } return ColorUtils.compositeColors(whiteScrim, mBitmapInfo.color); } Loading Loading @@ -227,11 +239,17 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { @Override public int getIntrinsicWidth() { if (mBitmapInfo == null) { return 0; } return mBitmapInfo.icon.getWidth(); } @Override public int getIntrinsicHeight() { if (mBitmapInfo == null) { return 0; } return mBitmapInfo.icon.getHeight(); } Loading iconloaderlib/src/com/android/launcher3/icons/mono/ThemedIconDrawable.kt +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ class ThemedIconDrawable(constantState: ThemedConstantState) : override fun getIconColor() = colorFg class ThemedConstantState( bitmapInfo: BitmapInfo, bitmapInfo: BitmapInfo?, val mono: Bitmap, val whiteShadowLayer: Bitmap, val colorBg: Int, Loading weathereffects/graphics/assets/shaders/snow.agsl +21 −54 Original line number Diff line number Diff line Loading @@ -19,15 +19,12 @@ struct Snow { highp vec2 cellUv; }; const mat2 rot45 = mat2( 0.7071067812, 0.7071067812, // First column. -0.7071067812, 0.7071067812 // second column. ); const vec2 snowFlakeShape = vec2(0.28, 0.26); // decreasedFactor should match minDescreasedFactor * 2, minDescreasedFactor is defined in snow_flake_samples.agsl const float decreasedFactor = 1.0 / 0.28; uniform half intensity; const float farthestSnowLayerWiggleSpeed = 2.18; const float closestSnowLayerWiggleSpeed = 0.9; uniform half snowFlakeSamplesSize; /** * Generates snow flakes. Loading @@ -53,18 +50,14 @@ Snow generateSnow( in float minLayerIndex, in float maxLayerIndex ) { // Normalize the layer index. 0 is closest, 1 is farthest. half normalizedLayerIndex = map(layerIndex, minLayerIndex, maxLayerIndex, 0, 1); /* Grid. */ // Increase the last number to make each layer more separate from the previous one. float depth = 0.65 + layerIndex * 0.555; float depth = 0.65 + layerIndex * 0.755; float speedAdj = 1. + layerIndex * 0.225; float layerR = idGenerator(layerIndex); snowGridSize *= depth; time += layerR * 58.3; // Number of rows and columns (each one is a cell, a drop). float cellAspectRatio = snowGridSize.x / snowGridSize.y; // Aspect ratio impacts visible cells. uv.y /= screenAspectRatio; // Skew uv.x so it goes to left or right Loading @@ -81,60 +74,34 @@ Snow generateSnow( // Have time affect the position of each column as well. gridUv.y += columnId * 2.6 + time * 0.19 * (1 - columnId); /* Cell. */ // Get the cell ID based on the grid position. Value from 0 to 1. float cellId = idGenerator(floor(gridUv)); // For each cell, we set the internal UV from -0.5 (left, bottom) to 0.5 (right, top). // Calclulate the grid this pixel belonging to, and also the offset in the cell. vec2 gridIdx = floor(gridUv); vec2 cellUv = fract(gridUv) - 0.5; cellUv.y *= -1.; /* * Disable snow flakes with some probabilty. This is done by 1) assigning a random intensity * value to the cell 2) then compare it with the given intensity. */ half cellIntensity = idGenerator(floor(vec2(cellId * 856.16, 272.2))); if (cellIntensity < 1. - intensity) { // Remove snow flakes by seeting flake mask to 0. // The bigger the decreasedFactor, the smaller the snow flake. vec2 snowFlakePos = vec2(cellUv.x, cellUv.y * (snowGridSize.x / snowGridSize.y - 1.0 / snowGridSize.y) + uv.y - 0.5 / screenAspectRatio) * decreasedFactor; if (abs(snowFlakePos.y) > 0.5 || abs(snowFlakePos.x) > 0.5 ) { return Snow(/* flakeMask= */ 0, cellUv); } vec4 color = snowFlakeSamples.eval(snowFlakeSamplesSize * (gridIdx - 0.5 + snowFlakePos)); /* Cell-id-based variations. */ // 0 = snow flake invisible, 1 = snow flake visible. float baseMask = color.r; half cellIntensity = color.g; float cellId = color.b; if (cellIntensity <= 1. - intensity) { // Remove snow flakes by seting flake mask to 0. return Snow(/* flakeMask= */ 0, cellUv); } float visibilityFactor = smoothstep( cellIntensity, max(cellIntensity - (0.02 + 0.18 * intensity), 0.0), 1 - intensity); // Adjust the size of each snow flake (higher is smaller) based on cell ID. float decreaseFactor = 2.0 + map(cellId, 0., 1., -0.1, 2.8) + 5. * (1 - visibilityFactor); // Adjust the opacity of the particle based on the cell id and distance from the camera. float farLayerFadeOut = map(normalizedLayerIndex, 0.7, 1, 1, 0.4); float closeLayerFadeOut = map(normalizedLayerIndex, 0, 0.2, 0.6, 1); float opacityVariation = (1. - 0.9 * cellId)* visibilityFactor * closeLayerFadeOut * farLayerFadeOut; /* Cell snow flake. */ // Calculate snow flake. vec2 snowFlakeShape = vec2(0.28, 0.26); vec2 snowFlakePos = vec2(cellUv.x, cellUv.y * cellAspectRatio); snowFlakePos -= vec2( 0., (uv.y - 0.5 / screenAspectRatio) - cellUv.y / snowGridSize.y ) * screenAspectRatio; snowFlakePos *= snowFlakeShape * decreaseFactor; vec2 snowFlakeShapeVariation = vec2(0.055) * // max variation vec2((cellId * 2. - 1.), // random A based on cell ID (fract((cellId + 0.03521) * 34.21) * 2. - 1.)); // random B based on cell ID vec2 snowFlakePosR = 1.016 * abs(rot45 * (snowFlakePos + snowFlakeShapeVariation)); snowFlakePos = abs(snowFlakePos); // Create the snowFlake mask. float flakeMask = smoothstep( 0.3, 0.200 - 0.3 * opacityVariation, snowFlakePos.x + snowFlakePos.y + snowFlakePosR.x + snowFlakePosR.y ) * opacityVariation; visibilityFactor * farLayerFadeOut * closeLayerFadeOut; float flakeMask = baseMask * opacityVariation; return Snow(flakeMask, cellUv); } weathereffects/graphics/assets/shaders/snow_effect.agsl +6 −2 Original line number Diff line number Diff line Loading @@ -21,8 +21,10 @@ uniform float2 gridSize; uniform float time; uniform float screenAspectRatio; uniform float2 screenSize; uniform float cellAspectRatio; uniform mat3 transformMatrixBitmap; uniform mat3 transformMatrixWeather; uniform shader snowFlakeSamples; #include "shaders/constants.agsl" #include "shaders/utils.agsl" Loading @@ -30,11 +32,13 @@ uniform mat3 transformMatrixWeather; // Snow tint. const vec4 snowColor = vec4(1., 1., 1., 0.95); // Background tint const vec4 bgdTint = vec4(0.8, 0.8, 0.8, 0.07); // Indices of the different snow layers. const float farthestSnowLayerIndex = 6; const float farthestSnowLayerIndex = 4; const float midSnowLayerIndex = 2; const float closestSnowLayerIndex = 0; Loading weathereffects/graphics/assets/shaders/snow_flake_samples.agsl 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ uniform float2 canvasSize; uniform float snowFlakeSamplesSize; #include "shaders/constants.agsl" #include "shaders/utils.agsl" const vec2 snowFlakeShape = vec2(0.28, 0.26); // Used in generate snow flake samples, and sampling it afterwards, to make sure snow flakes // will not go beyond bounding box const float minDecreaseFactor = 0.5 / 0.28; const float layerIndex = 0; const mat2 rot45 = mat2( 0.7071067812, 0.7071067812, // First column. -0.7071067812, 0.7071067812 // second column. ); /** * This shader generates snow flake samples per cell. It stores the flake mask in the red channel, * and pre-calculated `cellIntensity` and `cellId` in the green and blue channels for optimized access. */ vec4 main(float2 fragCoord) { // Calculate uv for snow based on transformed coordinates float2 uv = fragCoord / canvasSize; float layerR = idGenerator(layerIndex); // Number of rows and columns (each one is a cell, a snowflake). vec2 gridSize = floor(canvasSize / snowFlakeSamplesSize); float cellAspectRatio = gridSize.x / gridSize.y; // Aspect ratio impacts visible cells. vec2 gridUv = uv * gridSize; /* Cell. */ // Get the cell ID based on the grid position. Value from 0 to 1. float cellId = idGenerator(floor(gridUv)); // For each cell, we set the internal UV from -0.5 (left, bottom) to 0.5 (right, top). vec2 cellUv = fract(gridUv) - 0.5; cellUv.y *= -1.; /* * Disable snow flakes with some probabilty. This is done by 1) assigning a random intensity * value to the cell 2) then compare it with the given intensity. */ half cellIntensity = idGenerator(floor(vec2(cellId * 856.16, 272.2))); /* Cell snow flake. */ // Calculate snow flake. // With decreaseFactor <= minSnowShapeScale, we can make sure snow flakes not going out its // snowFlakeSamplesSize * snowFlakeSamplesSize bounding box float decreaseFactor = clamp(2.0 + map(cellId, 0., 1., 1., 1 + 5. * (1 - cellIntensity)), minDecreaseFactor, 4); // snowFlake center should be (0,0) in the cell when generating snowflake samples vec2 snowFlakePos = vec2(cellUv.x, cellUv.y); snowFlakePos *= snowFlakeShape * decreaseFactor; vec2 snowFlakeShapeVariation = vec2(0.055) * // max variation vec2((cellId * 2. - 1.), // random A based on cell ID (fract((cellId + 0.03521) * 34.21) * 2. - 1.)); // random B based on cell ID vec2 snowFlakePosR = 1.016 * abs(rot45 * (snowFlakePos + snowFlakeShapeVariation)); snowFlakePos = abs(snowFlakePos); // Create the snowFlake mask. float baseMask = 1 - clamp(snowFlakePos.x + snowFlakePos.y + snowFlakePosR.x + snowFlakePosR.y, 0, 1); return vec4(baseMask, cellIntensity, cellId , 1); } Loading
iconloaderlib/src/com/android/launcher3/icons/FastBitmapDrawable.java +19 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.FloatProperty; import android.util.Log; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; Loading @@ -46,6 +47,7 @@ import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags; public class FastBitmapDrawable extends Drawable implements Drawable.Callback { private static final String TAG = "FastBitmapDrawable"; private static final Interpolator ACCEL = new AccelerateInterpolator(); private static final Interpolator DEACCEL = new DecelerateInterpolator(); private static final Interpolator HOVER_EMPHASIZED_DECELERATE_INTERPOLATOR = Loading @@ -67,7 +69,8 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { private boolean mAnimationEnabled = true; protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); public final BitmapInfo mBitmapInfo; // b/404578798 - mBitmapInfo isn't expected to be null, but it is in some cases. @Nullable public final BitmapInfo mBitmapInfo; @Nullable private ColorFilter mColorFilter; Loading Loading @@ -109,6 +112,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { } public FastBitmapDrawable(BitmapInfo info) { if (info == null) { Log.e(TAG, "BitmapInfo should not be null.", new Exception()); } mBitmapInfo = info; setFilterBitmap(true); } Loading Loading @@ -152,6 +158,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { } protected void drawInternal(Canvas canvas, Rect bounds) { if (mBitmapInfo == null) { return; } canvas.drawBitmap(mBitmapInfo.icon, null, bounds, mPaint); } Loading @@ -160,6 +169,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { */ public int getIconColor() { int whiteScrim = setColorAlphaBound(Color.WHITE, WHITE_SCRIM_ALPHA); if (mBitmapInfo == null) { return whiteScrim; } return ColorUtils.compositeColors(whiteScrim, mBitmapInfo.color); } Loading Loading @@ -227,11 +239,17 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback { @Override public int getIntrinsicWidth() { if (mBitmapInfo == null) { return 0; } return mBitmapInfo.icon.getWidth(); } @Override public int getIntrinsicHeight() { if (mBitmapInfo == null) { return 0; } return mBitmapInfo.icon.getHeight(); } Loading
iconloaderlib/src/com/android/launcher3/icons/mono/ThemedIconDrawable.kt +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ class ThemedIconDrawable(constantState: ThemedConstantState) : override fun getIconColor() = colorFg class ThemedConstantState( bitmapInfo: BitmapInfo, bitmapInfo: BitmapInfo?, val mono: Bitmap, val whiteShadowLayer: Bitmap, val colorBg: Int, Loading
weathereffects/graphics/assets/shaders/snow.agsl +21 −54 Original line number Diff line number Diff line Loading @@ -19,15 +19,12 @@ struct Snow { highp vec2 cellUv; }; const mat2 rot45 = mat2( 0.7071067812, 0.7071067812, // First column. -0.7071067812, 0.7071067812 // second column. ); const vec2 snowFlakeShape = vec2(0.28, 0.26); // decreasedFactor should match minDescreasedFactor * 2, minDescreasedFactor is defined in snow_flake_samples.agsl const float decreasedFactor = 1.0 / 0.28; uniform half intensity; const float farthestSnowLayerWiggleSpeed = 2.18; const float closestSnowLayerWiggleSpeed = 0.9; uniform half snowFlakeSamplesSize; /** * Generates snow flakes. Loading @@ -53,18 +50,14 @@ Snow generateSnow( in float minLayerIndex, in float maxLayerIndex ) { // Normalize the layer index. 0 is closest, 1 is farthest. half normalizedLayerIndex = map(layerIndex, minLayerIndex, maxLayerIndex, 0, 1); /* Grid. */ // Increase the last number to make each layer more separate from the previous one. float depth = 0.65 + layerIndex * 0.555; float depth = 0.65 + layerIndex * 0.755; float speedAdj = 1. + layerIndex * 0.225; float layerR = idGenerator(layerIndex); snowGridSize *= depth; time += layerR * 58.3; // Number of rows and columns (each one is a cell, a drop). float cellAspectRatio = snowGridSize.x / snowGridSize.y; // Aspect ratio impacts visible cells. uv.y /= screenAspectRatio; // Skew uv.x so it goes to left or right Loading @@ -81,60 +74,34 @@ Snow generateSnow( // Have time affect the position of each column as well. gridUv.y += columnId * 2.6 + time * 0.19 * (1 - columnId); /* Cell. */ // Get the cell ID based on the grid position. Value from 0 to 1. float cellId = idGenerator(floor(gridUv)); // For each cell, we set the internal UV from -0.5 (left, bottom) to 0.5 (right, top). // Calclulate the grid this pixel belonging to, and also the offset in the cell. vec2 gridIdx = floor(gridUv); vec2 cellUv = fract(gridUv) - 0.5; cellUv.y *= -1.; /* * Disable snow flakes with some probabilty. This is done by 1) assigning a random intensity * value to the cell 2) then compare it with the given intensity. */ half cellIntensity = idGenerator(floor(vec2(cellId * 856.16, 272.2))); if (cellIntensity < 1. - intensity) { // Remove snow flakes by seeting flake mask to 0. // The bigger the decreasedFactor, the smaller the snow flake. vec2 snowFlakePos = vec2(cellUv.x, cellUv.y * (snowGridSize.x / snowGridSize.y - 1.0 / snowGridSize.y) + uv.y - 0.5 / screenAspectRatio) * decreasedFactor; if (abs(snowFlakePos.y) > 0.5 || abs(snowFlakePos.x) > 0.5 ) { return Snow(/* flakeMask= */ 0, cellUv); } vec4 color = snowFlakeSamples.eval(snowFlakeSamplesSize * (gridIdx - 0.5 + snowFlakePos)); /* Cell-id-based variations. */ // 0 = snow flake invisible, 1 = snow flake visible. float baseMask = color.r; half cellIntensity = color.g; float cellId = color.b; if (cellIntensity <= 1. - intensity) { // Remove snow flakes by seting flake mask to 0. return Snow(/* flakeMask= */ 0, cellUv); } float visibilityFactor = smoothstep( cellIntensity, max(cellIntensity - (0.02 + 0.18 * intensity), 0.0), 1 - intensity); // Adjust the size of each snow flake (higher is smaller) based on cell ID. float decreaseFactor = 2.0 + map(cellId, 0., 1., -0.1, 2.8) + 5. * (1 - visibilityFactor); // Adjust the opacity of the particle based on the cell id and distance from the camera. float farLayerFadeOut = map(normalizedLayerIndex, 0.7, 1, 1, 0.4); float closeLayerFadeOut = map(normalizedLayerIndex, 0, 0.2, 0.6, 1); float opacityVariation = (1. - 0.9 * cellId)* visibilityFactor * closeLayerFadeOut * farLayerFadeOut; /* Cell snow flake. */ // Calculate snow flake. vec2 snowFlakeShape = vec2(0.28, 0.26); vec2 snowFlakePos = vec2(cellUv.x, cellUv.y * cellAspectRatio); snowFlakePos -= vec2( 0., (uv.y - 0.5 / screenAspectRatio) - cellUv.y / snowGridSize.y ) * screenAspectRatio; snowFlakePos *= snowFlakeShape * decreaseFactor; vec2 snowFlakeShapeVariation = vec2(0.055) * // max variation vec2((cellId * 2. - 1.), // random A based on cell ID (fract((cellId + 0.03521) * 34.21) * 2. - 1.)); // random B based on cell ID vec2 snowFlakePosR = 1.016 * abs(rot45 * (snowFlakePos + snowFlakeShapeVariation)); snowFlakePos = abs(snowFlakePos); // Create the snowFlake mask. float flakeMask = smoothstep( 0.3, 0.200 - 0.3 * opacityVariation, snowFlakePos.x + snowFlakePos.y + snowFlakePosR.x + snowFlakePosR.y ) * opacityVariation; visibilityFactor * farLayerFadeOut * closeLayerFadeOut; float flakeMask = baseMask * opacityVariation; return Snow(flakeMask, cellUv); }
weathereffects/graphics/assets/shaders/snow_effect.agsl +6 −2 Original line number Diff line number Diff line Loading @@ -21,8 +21,10 @@ uniform float2 gridSize; uniform float time; uniform float screenAspectRatio; uniform float2 screenSize; uniform float cellAspectRatio; uniform mat3 transformMatrixBitmap; uniform mat3 transformMatrixWeather; uniform shader snowFlakeSamples; #include "shaders/constants.agsl" #include "shaders/utils.agsl" Loading @@ -30,11 +32,13 @@ uniform mat3 transformMatrixWeather; // Snow tint. const vec4 snowColor = vec4(1., 1., 1., 0.95); // Background tint const vec4 bgdTint = vec4(0.8, 0.8, 0.8, 0.07); // Indices of the different snow layers. const float farthestSnowLayerIndex = 6; const float farthestSnowLayerIndex = 4; const float midSnowLayerIndex = 2; const float closestSnowLayerIndex = 0; Loading
weathereffects/graphics/assets/shaders/snow_flake_samples.agsl 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ uniform float2 canvasSize; uniform float snowFlakeSamplesSize; #include "shaders/constants.agsl" #include "shaders/utils.agsl" const vec2 snowFlakeShape = vec2(0.28, 0.26); // Used in generate snow flake samples, and sampling it afterwards, to make sure snow flakes // will not go beyond bounding box const float minDecreaseFactor = 0.5 / 0.28; const float layerIndex = 0; const mat2 rot45 = mat2( 0.7071067812, 0.7071067812, // First column. -0.7071067812, 0.7071067812 // second column. ); /** * This shader generates snow flake samples per cell. It stores the flake mask in the red channel, * and pre-calculated `cellIntensity` and `cellId` in the green and blue channels for optimized access. */ vec4 main(float2 fragCoord) { // Calculate uv for snow based on transformed coordinates float2 uv = fragCoord / canvasSize; float layerR = idGenerator(layerIndex); // Number of rows and columns (each one is a cell, a snowflake). vec2 gridSize = floor(canvasSize / snowFlakeSamplesSize); float cellAspectRatio = gridSize.x / gridSize.y; // Aspect ratio impacts visible cells. vec2 gridUv = uv * gridSize; /* Cell. */ // Get the cell ID based on the grid position. Value from 0 to 1. float cellId = idGenerator(floor(gridUv)); // For each cell, we set the internal UV from -0.5 (left, bottom) to 0.5 (right, top). vec2 cellUv = fract(gridUv) - 0.5; cellUv.y *= -1.; /* * Disable snow flakes with some probabilty. This is done by 1) assigning a random intensity * value to the cell 2) then compare it with the given intensity. */ half cellIntensity = idGenerator(floor(vec2(cellId * 856.16, 272.2))); /* Cell snow flake. */ // Calculate snow flake. // With decreaseFactor <= minSnowShapeScale, we can make sure snow flakes not going out its // snowFlakeSamplesSize * snowFlakeSamplesSize bounding box float decreaseFactor = clamp(2.0 + map(cellId, 0., 1., 1., 1 + 5. * (1 - cellIntensity)), minDecreaseFactor, 4); // snowFlake center should be (0,0) in the cell when generating snowflake samples vec2 snowFlakePos = vec2(cellUv.x, cellUv.y); snowFlakePos *= snowFlakeShape * decreaseFactor; vec2 snowFlakeShapeVariation = vec2(0.055) * // max variation vec2((cellId * 2. - 1.), // random A based on cell ID (fract((cellId + 0.03521) * 34.21) * 2. - 1.)); // random B based on cell ID vec2 snowFlakePosR = 1.016 * abs(rot45 * (snowFlakePos + snowFlakeShapeVariation)); snowFlakePos = abs(snowFlakePos); // Create the snowFlake mask. float baseMask = 1 - clamp(snowFlakePos.x + snowFlakePos.y + snowFlakePosR.x + snowFlakePosR.y, 0, 1); return vec4(baseMask, cellIntensity, cellId , 1); }