Loading weathereffects/graphics/assets/shaders/snow.agsl +3 −31 Original line number Diff line number Diff line Loading @@ -58,8 +58,8 @@ Snow generateSnow( /* Grid. */ // Increase the last number to make each layer more separate from the previous one. float depth = 0.65 + layerIndex * 0.37; float speedAdj = 1. + layerIndex * 0.15; float depth = 0.65 + layerIndex * 0.555; float speedAdj = 1. + layerIndex * 0.225; float layerR = idGenerator(layerIndex); snowGridSize *= depth; time += layerR * 58.3; Loading Loading @@ -116,37 +116,9 @@ Snow generateSnow( farLayerFadeOut; /* Cell snow flake. */ // Horizontal movement: Wiggle (Adjust the wiggle speed based on the distance). float wiggleSpeed = map( normalizedLayerIndex, 0.2, 0.7, closestSnowLayerWiggleSpeed, farthestSnowLayerWiggleSpeed); // Adjust wiggle based on layer number (0 = closer to screen => we want less movement). float wiggleAmp = 0.6 + 0.4 * smoothstep(0.5, 2.5, layerIndex); // Define the start based on the cell id. float horizontalStartAmp = 0.5; // Add the wiggle (equation decided by testing in Grapher). float horizontalWiggle = wiggle( // Current uv position. uv.y // Adjustment so the shape is not skewed. - cellUv.y / snowGridSize.y // variation based on cell ID. + cellId * 2.1, wiggleSpeed * speedAdj); // Add the start and wiggle and make that when we are closer to the edge, we don't wiggle much // (so the drop doesn't go outside it's cell). horizontalWiggle = horizontalStartAmp * wiggleAmp * horizontalWiggle; // Calculate main cell drop. float snowFlakePosUncorrected = (cellUv.x - horizontalWiggle); // Calculate snow flake. vec2 snowFlakeShape = vec2(0.28, 0.26); vec2 snowFlakePos = vec2(snowFlakePosUncorrected, cellUv.y * cellAspectRatio); vec2 snowFlakePos = vec2(cellUv.x, cellUv.y * cellAspectRatio); snowFlakePos -= vec2( 0., (uv.y - 0.5 / screenAspectRatio) - cellUv.y / snowGridSize.y Loading weathereffects/graphics/assets/shaders/snow_accumulation.agsl +1 −3 Original line number Diff line number Diff line Loading @@ -37,10 +37,8 @@ vec4 main(float2 fragCoord) { float dY = (aN - aS) * 0.5; dY = max(dY, 0.0); float accumulatedSnow = smoothstep(0.1, 1.8, dY * 5.0); vec4 color = vec4(0., 0., 0., 1.); color.r = accumulatedSnow; color.r = dY * 10.0; color.g = random(uv); color.b = variation; return color; } weathereffects/graphics/assets/shaders/snow_effect.agsl +29 −26 Original line number Diff line number Diff line Loading @@ -35,8 +35,8 @@ const vec4 snowColor = vec4(1., 1., 1., 0.95); const vec4 bgdTint = vec4(0.8, 0.8, 0.8, 0.07); // Indices of the different snow layers. const float farthestSnowLayerIndex = 9; const float midSnowLayerIndex = 3; const float farthestSnowLayerIndex = 6; const float midSnowLayerIndex = 2; const float closestSnowLayerIndex = 0; vec4 main(float2 fragCoord) { Loading @@ -52,7 +52,6 @@ vec4 main(float2 fragCoord) { // Apply transform matrix to fragCoord float2 adjustedUv = transformPoint(transformMatrixBitmap, fragCoord); // Calculate uv for snow based on transformed coordinates float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize; float2 uvAdjusted = vec2(uv.x, uv.y / screenAspectRatio); Loading @@ -74,6 +73,7 @@ vec4 main(float2 fragCoord) { color.rgb = normalBlendNotPremultiplied(color.rgb, bgdTint.rgb, bgdTint.a); // 2. Generate snow layers behind the subject. if (colorForeground.a == 0) { for (float i = farthestSnowLayerIndex; i > midSnowLayerIndex; i--) { Snow snow = generateSnow( uv, Loading @@ -87,6 +87,7 @@ vec4 main(float2 fragCoord) { color.rgb = normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * snow.flakeMask); } } // 3. Add the foreground layer. Any effect from here will be in front of the subject. color.rgb = normalBlend(color.rgb, colorForeground.rgb, colorForeground.a); Loading @@ -100,7 +101,8 @@ vec4 main(float2 fragCoord) { // Get the accumulated snow buffer. r contains its mask, g contains some random noise. vec2 accSnow = accumulatedSnow.eval(adjustedUv).rg; // Sharpen the mask of the accumulated snow, but not in excess. float accSnowMask = smoothstep(0.1, 0.9, /* mask= */ accSnow.r); float accSnowMask = smoothstep( (1.-intensity), 1.0, /* mask= */accSnow.r); if (accSnowMask > 0) { // Makes the edges of the snow layer accumulation rougher. accSnowMask = map(accSnowMask, 1. - cloudsNoise.b - 0.3 * dither, 1., 0., 1.); // Load snow texture and dither. Make it have gray-ish values. Loading @@ -111,6 +113,7 @@ vec4 main(float2 fragCoord) { accSnowMask = map(accSnowMask, 0., 1., 0., 1.- 0.6 * accSnowTexture - 0.35 * dither); color.rgb = normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * accSnowMask); } // 5. Generate snow in front of the subject. for (float i = midSnowLayerIndex; i >= closestSnowLayerIndex; i--) { Loading weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/snow/SnowEffect.kt +43 −16 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect.Compan import com.google.android.wallpaper.weathereffects.graphics.WeatherEffectBase import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils import com.google.android.wallpaper.weathereffects.graphics.utils.MathUtils import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScale import com.google.android.wallpaper.weathereffects.graphics.utils.TimeUtils import java.util.concurrent.Executor Loading @@ -54,7 +55,11 @@ class SnowEffect( init { frameBuffer.setRenderEffect( RenderEffect.createBlurEffect(4f / bitmapScale, 4f / bitmapScale, Shader.TileMode.CLAMP) RenderEffect.createBlurEffect( BLUR_RADIUS / bitmapScale, BLUR_RADIUS / bitmapScale, Shader.TileMode.CLAMP, ) ) updateTextureUniforms() adjustCropping(surfaceSize) Loading Loading @@ -88,23 +93,26 @@ class SnowEffect( * Increase effect speed as weather intensity decreases. This compensates for the floaty * appearance when there are fewer particles at the original speed. */ if (this.intensity != intensity) { snowSpeed = MathUtils.map(intensity, 0f, 1f, 2.5f, 1.7f) this.intensity = intensity // Regenerate accumulated snow since the uniform changed. generateAccumulatedSnow() } } override fun setBitmaps(foreground: Bitmap?, background: Bitmap): Boolean { if (!super.setBitmaps(foreground, background)) { return false } frameBuffer.close() frameBuffer = FrameBuffer(background.width, background.height).apply { setRenderEffect( frameBuffer = FrameBuffer(background.width, background.height) val newScale = getScale(parallaxMatrix) if (bitmapScale != newScale) { bitmapScale = newScale frameBuffer.setRenderEffect( RenderEffect.createBlurEffect( 4f / bitmapScale, 4f / bitmapScale, BLUR_RADIUS / bitmapScale, BLUR_RADIUS / bitmapScale, Shader.TileMode.CLAMP, ) ) Loading @@ -128,9 +136,19 @@ class SnowEffect( get() = snowConfig.colorGradingIntensity override fun setMatrix(matrix: Matrix) { val oldScale = bitmapScale super.setMatrix(matrix) if (bitmapScale != oldScale) { frameBuffer.setRenderEffect( RenderEffect.createBlurEffect( BLUR_RADIUS / bitmapScale, BLUR_RADIUS / bitmapScale, Shader.TileMode.CLAMP, ) ) generateAccumulatedSnow() } } override fun updateTextureUniforms() { super.updateTextureUniforms() Loading @@ -155,13 +173,14 @@ class SnowEffect( snowConfig.accumulatedSnowShader.setFloatUniform("scale", bitmapScale) snowConfig.accumulatedSnowShader.setFloatUniform( "snowThickness", snowConfig.maxAccumulatedSnowThickness * intensity / bitmapScale, SNOW_THICKNESS / bitmapScale, ) snowConfig.accumulatedSnowShader.setFloatUniform("screenWidth", surfaceSize.width) snowConfig.accumulatedSnowShader.setInputBuffer( "foreground", BitmapShader(foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR), ) renderingCanvas.drawPaint(frameBufferPaint) frameBuffer.endDrawing() Loading @@ -180,4 +199,12 @@ class SnowEffect( val gridSize = GraphicsUtils.computeDefaultGridSize(newSurfaceSize, snowConfig.pixelDensity) snowConfig.shader.setFloatUniform("gridSize", 7 * gridSize, 2f * gridSize) } companion object { val BLUR_RADIUS = 4f // Use blur effect for both blurring the snow accumulation and generating a gradient edge // so that intensity can control snow thickness by cut the gradient edge in snow_effect // shader. val SNOW_THICKNESS = 6f } } weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/snow/SnowEffectConfig.kt +3 −3 Original line number Diff line number Diff line Loading @@ -64,16 +64,16 @@ data class SnowEffectConfig( lut = GraphicsUtils.loadTexture(assets, LOOKUP_TABLE_TEXTURE_PATH), pixelDensity, COLOR_GRADING_INTENSITY, MAX_SNOW_THICKNESS MAX_SNOW_THICKNESS, ) private companion object { companion object { private const val SHADER_PATH = "shaders/snow_effect.agsl" private const val ACCUMULATED_SNOW_SHADER_PATH = "shaders/snow_accumulation.agsl" private const val COLOR_GRADING_SHADER_PATH = "shaders/color_grading_lut.agsl" private const val NOISE_TEXTURE_PATH = "textures/clouds.png" private const val LOOKUP_TABLE_TEXTURE_PATH = "textures/snow_lut.png" private const val COLOR_GRADING_INTENSITY = 0.25f private const val MAX_SNOW_THICKNESS = 10f const val MAX_SNOW_THICKNESS = 10f } } Loading
weathereffects/graphics/assets/shaders/snow.agsl +3 −31 Original line number Diff line number Diff line Loading @@ -58,8 +58,8 @@ Snow generateSnow( /* Grid. */ // Increase the last number to make each layer more separate from the previous one. float depth = 0.65 + layerIndex * 0.37; float speedAdj = 1. + layerIndex * 0.15; float depth = 0.65 + layerIndex * 0.555; float speedAdj = 1. + layerIndex * 0.225; float layerR = idGenerator(layerIndex); snowGridSize *= depth; time += layerR * 58.3; Loading Loading @@ -116,37 +116,9 @@ Snow generateSnow( farLayerFadeOut; /* Cell snow flake. */ // Horizontal movement: Wiggle (Adjust the wiggle speed based on the distance). float wiggleSpeed = map( normalizedLayerIndex, 0.2, 0.7, closestSnowLayerWiggleSpeed, farthestSnowLayerWiggleSpeed); // Adjust wiggle based on layer number (0 = closer to screen => we want less movement). float wiggleAmp = 0.6 + 0.4 * smoothstep(0.5, 2.5, layerIndex); // Define the start based on the cell id. float horizontalStartAmp = 0.5; // Add the wiggle (equation decided by testing in Grapher). float horizontalWiggle = wiggle( // Current uv position. uv.y // Adjustment so the shape is not skewed. - cellUv.y / snowGridSize.y // variation based on cell ID. + cellId * 2.1, wiggleSpeed * speedAdj); // Add the start and wiggle and make that when we are closer to the edge, we don't wiggle much // (so the drop doesn't go outside it's cell). horizontalWiggle = horizontalStartAmp * wiggleAmp * horizontalWiggle; // Calculate main cell drop. float snowFlakePosUncorrected = (cellUv.x - horizontalWiggle); // Calculate snow flake. vec2 snowFlakeShape = vec2(0.28, 0.26); vec2 snowFlakePos = vec2(snowFlakePosUncorrected, cellUv.y * cellAspectRatio); vec2 snowFlakePos = vec2(cellUv.x, cellUv.y * cellAspectRatio); snowFlakePos -= vec2( 0., (uv.y - 0.5 / screenAspectRatio) - cellUv.y / snowGridSize.y Loading
weathereffects/graphics/assets/shaders/snow_accumulation.agsl +1 −3 Original line number Diff line number Diff line Loading @@ -37,10 +37,8 @@ vec4 main(float2 fragCoord) { float dY = (aN - aS) * 0.5; dY = max(dY, 0.0); float accumulatedSnow = smoothstep(0.1, 1.8, dY * 5.0); vec4 color = vec4(0., 0., 0., 1.); color.r = accumulatedSnow; color.r = dY * 10.0; color.g = random(uv); color.b = variation; return color; }
weathereffects/graphics/assets/shaders/snow_effect.agsl +29 −26 Original line number Diff line number Diff line Loading @@ -35,8 +35,8 @@ const vec4 snowColor = vec4(1., 1., 1., 0.95); const vec4 bgdTint = vec4(0.8, 0.8, 0.8, 0.07); // Indices of the different snow layers. const float farthestSnowLayerIndex = 9; const float midSnowLayerIndex = 3; const float farthestSnowLayerIndex = 6; const float midSnowLayerIndex = 2; const float closestSnowLayerIndex = 0; vec4 main(float2 fragCoord) { Loading @@ -52,7 +52,6 @@ vec4 main(float2 fragCoord) { // Apply transform matrix to fragCoord float2 adjustedUv = transformPoint(transformMatrixBitmap, fragCoord); // Calculate uv for snow based on transformed coordinates float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize; float2 uvAdjusted = vec2(uv.x, uv.y / screenAspectRatio); Loading @@ -74,6 +73,7 @@ vec4 main(float2 fragCoord) { color.rgb = normalBlendNotPremultiplied(color.rgb, bgdTint.rgb, bgdTint.a); // 2. Generate snow layers behind the subject. if (colorForeground.a == 0) { for (float i = farthestSnowLayerIndex; i > midSnowLayerIndex; i--) { Snow snow = generateSnow( uv, Loading @@ -87,6 +87,7 @@ vec4 main(float2 fragCoord) { color.rgb = normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * snow.flakeMask); } } // 3. Add the foreground layer. Any effect from here will be in front of the subject. color.rgb = normalBlend(color.rgb, colorForeground.rgb, colorForeground.a); Loading @@ -100,7 +101,8 @@ vec4 main(float2 fragCoord) { // Get the accumulated snow buffer. r contains its mask, g contains some random noise. vec2 accSnow = accumulatedSnow.eval(adjustedUv).rg; // Sharpen the mask of the accumulated snow, but not in excess. float accSnowMask = smoothstep(0.1, 0.9, /* mask= */ accSnow.r); float accSnowMask = smoothstep( (1.-intensity), 1.0, /* mask= */accSnow.r); if (accSnowMask > 0) { // Makes the edges of the snow layer accumulation rougher. accSnowMask = map(accSnowMask, 1. - cloudsNoise.b - 0.3 * dither, 1., 0., 1.); // Load snow texture and dither. Make it have gray-ish values. Loading @@ -111,6 +113,7 @@ vec4 main(float2 fragCoord) { accSnowMask = map(accSnowMask, 0., 1., 0., 1.- 0.6 * accSnowTexture - 0.35 * dither); color.rgb = normalBlendNotPremultiplied(color.rgb, snowColor.rgb, snowColor.a * accSnowMask); } // 5. Generate snow in front of the subject. for (float i = midSnowLayerIndex; i >= closestSnowLayerIndex; i--) { Loading
weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/snow/SnowEffect.kt +43 −16 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect.Compan import com.google.android.wallpaper.weathereffects.graphics.WeatherEffectBase import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils import com.google.android.wallpaper.weathereffects.graphics.utils.MathUtils import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScale import com.google.android.wallpaper.weathereffects.graphics.utils.TimeUtils import java.util.concurrent.Executor Loading @@ -54,7 +55,11 @@ class SnowEffect( init { frameBuffer.setRenderEffect( RenderEffect.createBlurEffect(4f / bitmapScale, 4f / bitmapScale, Shader.TileMode.CLAMP) RenderEffect.createBlurEffect( BLUR_RADIUS / bitmapScale, BLUR_RADIUS / bitmapScale, Shader.TileMode.CLAMP, ) ) updateTextureUniforms() adjustCropping(surfaceSize) Loading Loading @@ -88,23 +93,26 @@ class SnowEffect( * Increase effect speed as weather intensity decreases. This compensates for the floaty * appearance when there are fewer particles at the original speed. */ if (this.intensity != intensity) { snowSpeed = MathUtils.map(intensity, 0f, 1f, 2.5f, 1.7f) this.intensity = intensity // Regenerate accumulated snow since the uniform changed. generateAccumulatedSnow() } } override fun setBitmaps(foreground: Bitmap?, background: Bitmap): Boolean { if (!super.setBitmaps(foreground, background)) { return false } frameBuffer.close() frameBuffer = FrameBuffer(background.width, background.height).apply { setRenderEffect( frameBuffer = FrameBuffer(background.width, background.height) val newScale = getScale(parallaxMatrix) if (bitmapScale != newScale) { bitmapScale = newScale frameBuffer.setRenderEffect( RenderEffect.createBlurEffect( 4f / bitmapScale, 4f / bitmapScale, BLUR_RADIUS / bitmapScale, BLUR_RADIUS / bitmapScale, Shader.TileMode.CLAMP, ) ) Loading @@ -128,9 +136,19 @@ class SnowEffect( get() = snowConfig.colorGradingIntensity override fun setMatrix(matrix: Matrix) { val oldScale = bitmapScale super.setMatrix(matrix) if (bitmapScale != oldScale) { frameBuffer.setRenderEffect( RenderEffect.createBlurEffect( BLUR_RADIUS / bitmapScale, BLUR_RADIUS / bitmapScale, Shader.TileMode.CLAMP, ) ) generateAccumulatedSnow() } } override fun updateTextureUniforms() { super.updateTextureUniforms() Loading @@ -155,13 +173,14 @@ class SnowEffect( snowConfig.accumulatedSnowShader.setFloatUniform("scale", bitmapScale) snowConfig.accumulatedSnowShader.setFloatUniform( "snowThickness", snowConfig.maxAccumulatedSnowThickness * intensity / bitmapScale, SNOW_THICKNESS / bitmapScale, ) snowConfig.accumulatedSnowShader.setFloatUniform("screenWidth", surfaceSize.width) snowConfig.accumulatedSnowShader.setInputBuffer( "foreground", BitmapShader(foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR), ) renderingCanvas.drawPaint(frameBufferPaint) frameBuffer.endDrawing() Loading @@ -180,4 +199,12 @@ class SnowEffect( val gridSize = GraphicsUtils.computeDefaultGridSize(newSurfaceSize, snowConfig.pixelDensity) snowConfig.shader.setFloatUniform("gridSize", 7 * gridSize, 2f * gridSize) } companion object { val BLUR_RADIUS = 4f // Use blur effect for both blurring the snow accumulation and generating a gradient edge // so that intensity can control snow thickness by cut the gradient edge in snow_effect // shader. val SNOW_THICKNESS = 6f } }
weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/snow/SnowEffectConfig.kt +3 −3 Original line number Diff line number Diff line Loading @@ -64,16 +64,16 @@ data class SnowEffectConfig( lut = GraphicsUtils.loadTexture(assets, LOOKUP_TABLE_TEXTURE_PATH), pixelDensity, COLOR_GRADING_INTENSITY, MAX_SNOW_THICKNESS MAX_SNOW_THICKNESS, ) private companion object { companion object { private const val SHADER_PATH = "shaders/snow_effect.agsl" private const val ACCUMULATED_SNOW_SHADER_PATH = "shaders/snow_accumulation.agsl" private const val COLOR_GRADING_SHADER_PATH = "shaders/color_grading_lut.agsl" private const val NOISE_TEXTURE_PATH = "textures/clouds.png" private const val LOOKUP_TABLE_TEXTURE_PATH = "textures/snow_lut.png" private const val COLOR_GRADING_INTENSITY = 0.25f private const val MAX_SNOW_THICKNESS = 10f const val MAX_SNOW_THICKNESS = 10f } }