Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f467307 authored by “Sherry's avatar “Sherry Committed by Sherry Zhou
Browse files

Reuse WeatherEffect in WeatherEffectFactory

Flag: EXEMPT change is only in MagicPortrait
Test: manually test MagicPortrait and SamsungWallpaper app and observe
weather effects display properly
Bug: 356932471

Change-Id: I6ecab238a455b4facf8b14f0e93041e79ce70f77
parent 5bb65d93
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.google.android.wallpaper.weathereffects.graphics

import android.graphics.Bitmap
import android.graphics.Canvas
import android.util.SizeF
import androidx.annotation.FloatRange
@@ -59,4 +60,16 @@ interface WeatherEffect {
     * @param intensity [0, 1] the intensity of the weather effect.
     */
    fun setIntensity(@FloatRange(from = 0.0, to = 1.0) intensity: Float)

    /**
     * Reuse current shader but change background, foreground
     *
     * @param foreground A bitmap containing the foreground of the image
     * @param background A bitmap containing the background of the image
     */
    fun setBitmaps(foreground: Bitmap, background: Bitmap)

    companion object {
        val DEFAULT_INTENSITY = 1f
    }
}
+28 −9
Original line number Diff line number Diff line
@@ -16,24 +16,28 @@

package com.google.android.wallpaper.weathereffects.graphics.fog

import android.graphics.Bitmap
import android.graphics.BitmapShader
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Shader
import android.util.SizeF
import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect
import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect.Companion.DEFAULT_INTENSITY
import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils
import com.google.android.wallpaper.weathereffects.graphics.utils.ImageCrop
import com.google.android.wallpaper.weathereffects.graphics.utils.TimeUtils
import java.util.concurrent.TimeUnit
import kotlin.math.sin
import kotlin.random.Random

/** Defines and generates the fog weather effect animation. */
class FogEffect(
    private val fogConfig: FogEffectConfig,
    private var foreground: Bitmap,
    private var background: Bitmap,
    private var intensity: Float = DEFAULT_INTENSITY,
    /** The initial size of the surface where the effect will be shown. */
    surfaceSize: SizeF
    private var surfaceSize: SizeF
) : WeatherEffect {

    private val fogPaint = Paint().also { it.shader = fogConfig.colorGradingShader }
@@ -44,12 +48,13 @@ class FogEffect(
        adjustCropping(surfaceSize)
        prepareColorGrading()
        updateFogGridSize(surfaceSize)
        setIntensity(fogConfig.intensity)
        setIntensity(intensity)
    }

    override fun resize(newSurfaceSize: SizeF) {
        adjustCropping(newSurfaceSize)
        updateFogGridSize(newSurfaceSize)
        surfaceSize = newSurfaceSize
    }

    override fun update(deltaMillis: Long, frameTimeNanos: Long) {
@@ -98,13 +103,27 @@ class FogEffect(
        )
    }

    override fun setBitmaps(foreground: Bitmap, background: Bitmap) {
        this.foreground = foreground
        this.background = background
        fogConfig.shader.setInputBuffer(
            "background",
            BitmapShader(background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        )
        fogConfig.shader.setInputBuffer(
            "foreground",
            BitmapShader(foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        )
        adjustCropping(surfaceSize)
    }

    private fun adjustCropping(surfaceSize: SizeF) {
        val imageCropFgd =
            ImageCrop.centerCoverCrop(
                surfaceSize.width,
                surfaceSize.height,
                fogConfig.foreground.width.toFloat(),
                fogConfig.foreground.height.toFloat()
                foreground.width.toFloat(),
                foreground.height.toFloat()
            )
        fogConfig.shader.setFloatUniform(
            "uvOffsetFgd",
@@ -120,8 +139,8 @@ class FogEffect(
            ImageCrop.centerCoverCrop(
                surfaceSize.width,
                surfaceSize.height,
                fogConfig.background.width.toFloat(),
                fogConfig.background.height.toFloat()
                background.width.toFloat(),
                background.height.toFloat()
            )
        fogConfig.shader.setFloatUniform(
            "uvOffsetBgd",
@@ -143,12 +162,12 @@ class FogEffect(
    private fun updateTextureUniforms() {
        fogConfig.shader.setInputBuffer(
            "foreground",
            BitmapShader(fogConfig.foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
            BitmapShader(foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        )

        fogConfig.shader.setInputBuffer(
            "background",
            BitmapShader(fogConfig.background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
            BitmapShader(background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        )

        fogConfig.shader.setInputBuffer(
+4 −19
Original line number Diff line number Diff line
@@ -40,14 +40,8 @@ data class FogEffectConfig(
     * tileable, and at least 16-bit per channel for render quality.
     */
    val fogTexture: Bitmap,
    /** A bitmap containing the foreground of the image. */
    val foreground: Bitmap,
    /** A bitmap containing the background of the image. */
    val background: Bitmap,
    /** Pixel density of the display. Used for dithering. */
    val pixelDensity: Float,
    /** The amount of the fog. This contributes to the color grading as well. */
    @FloatRange(from = 0.0, to = 1.0) val intensity: Float,
    /** The intensity of the color grading. 0: no color grading, 1: color grading in full effect. */
    @FloatRange(from = 0.0, to = 1.0) val colorGradingIntensity: Float,
) {
@@ -55,30 +49,22 @@ data class FogEffectConfig(
     * Constructor for [FogEffectConfig].
     *
     * @param assets the application [AssetManager].
     * @param foreground a bitmap containing the foreground of the image.
     * @param background a bitmap containing the background of the image.
     * @param pixelDensity pixel density of the display.
     * @param intensity initial intensity that affects the amount of fog and color grading. Expected
     *   range is [0, 1]. You can always change the intensity dynamically. Defaults to 1.
     */
    constructor(
        assets: AssetManager,
        foreground: Bitmap,
        background: Bitmap,
        pixelDensity: Float,
        intensity: Float = DEFAULT_INTENSITY,
    ) : this(
        shader = GraphicsUtils.loadShader(assets, SHADER_PATH),
        colorGradingShader = GraphicsUtils.loadShader(assets, COLOR_GRADING_SHADER_PATH),
        lut = GraphicsUtils.loadTexture(assets, LOOKUP_TABLE_TEXTURE_PATH),
        cloudsTexture = GraphicsUtils.loadTexture(assets, CLOUDS_TEXTURE_PATH)
        cloudsTexture =
            GraphicsUtils.loadTexture(assets, CLOUDS_TEXTURE_PATH)
                ?: throw RuntimeException("Clouds texture is missing."),
        fogTexture = GraphicsUtils.loadTexture(assets, FOG_TEXTURE_PATH)
        fogTexture =
            GraphicsUtils.loadTexture(assets, FOG_TEXTURE_PATH)
                ?: throw RuntimeException("Fog texture is missing."),
        foreground,
        background,
        pixelDensity,
        intensity,
        COLOR_GRADING_INTENSITY
    )

@@ -88,7 +74,6 @@ data class FogEffectConfig(
        private const val LOOKUP_TABLE_TEXTURE_PATH = "textures/lut_rain_and_fog.png"
        private const val CLOUDS_TEXTURE_PATH = "textures/clouds.png"
        private const val FOG_TEXTURE_PATH = "textures/fog.png"
        private const val DEFAULT_INTENSITY = 1f
        private const val COLOR_GRADING_INTENSITY = 0.7f
    }
}
+6 −2
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect
import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils

/** Simply draws foreground and background images with no weather effect. */
class NoEffect(val foreground: Bitmap, val background: Bitmap, private var surfaceSize: SizeF) :
class NoEffect(var foreground: Bitmap, var background: Bitmap, private var surfaceSize: SizeF) :
    WeatherEffect {
    override fun resize(newSurfaceSize: SizeF) {
        surfaceSize = newSurfaceSize
@@ -40,7 +40,6 @@ class NoEffect(val foreground: Bitmap, val background: Bitmap, private var surfa
            ),
            null
        )

        canvas.drawBitmap(
            foreground,
            MatrixUtils.centerCropMatrix(
@@ -56,4 +55,9 @@ class NoEffect(val foreground: Bitmap, val background: Bitmap, private var surfa
    override fun release() {}

    override fun setIntensity(intensity: Float) {}

    override fun setBitmaps(foreground: Bitmap, background: Bitmap) {
        this.foreground = foreground
        this.background = background
    }
}
+32 −12
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.google.android.wallpaper.weathereffects.graphics.rain

import android.graphics.Bitmap
import android.graphics.BitmapShader
import android.graphics.Canvas
import android.graphics.Color
@@ -25,20 +26,23 @@ import android.graphics.Shader
import android.util.SizeF
import com.google.android.wallpaper.weathereffects.graphics.FrameBuffer
import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect
import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect.Companion.DEFAULT_INTENSITY
import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils
import com.google.android.wallpaper.weathereffects.graphics.utils.ImageCrop
import com.google.android.wallpaper.weathereffects.graphics.utils.SolidColorShader
import com.google.android.wallpaper.weathereffects.graphics.utils.TimeUtils
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import kotlin.random.Random

/** Defines and generates the rain weather effect animation. */
class RainEffect(
    /** The config of the rain effect. */
    private val rainConfig: RainEffectConfig,
    private var foreground: Bitmap,
    private var background: Bitmap,
    private var intensity: Float = DEFAULT_INTENSITY,
    /** The initial size of the surface where the effect will be shown. */
    surfaceSize: SizeF,
    private var surfaceSize: SizeF,
    private val mainExecutor: Executor
) : WeatherEffect {

@@ -46,8 +50,8 @@ class RainEffect(

    // Set blur effect to reduce the outline noise. No need to set blur effect every time we
    // re-generate the outline buffer.
    private val outlineBuffer =
        FrameBuffer(rainConfig.background.width, rainConfig.background.height).apply {
    private var outlineBuffer =
        FrameBuffer(background.width, background.height).apply {
            setRenderEffect(RenderEffect.createBlurEffect(2f, 2f, Shader.TileMode.CLAMP))
        }
    private val outlineBufferPaint = Paint().also { it.shader = rainConfig.outlineShader }
@@ -59,12 +63,13 @@ class RainEffect(
        adjustCropping(surfaceSize)
        prepareColorGrading()
        updateRainGridSize(surfaceSize)
        setIntensity(rainConfig.intensity)
        setIntensity(intensity)
    }

    override fun resize(newSurfaceSize: SizeF) {
        adjustCropping(newSurfaceSize)
        updateRainGridSize(newSurfaceSize)
        surfaceSize = newSurfaceSize
    }

    override fun update(deltaMillis: Long, frameTimeNanos: Long) {
@@ -104,13 +109,27 @@ class RainEffect(
        createOutlineBuffer()
    }

    override fun setBitmaps(foreground: Bitmap, background: Bitmap) {
        this.foreground = foreground
        this.background = background
        outlineBuffer =
            FrameBuffer(background.width, background.height).apply {
                setRenderEffect(RenderEffect.createBlurEffect(2f, 2f, Shader.TileMode.CLAMP))
            }
        adjustCropping(surfaceSize)
        updateTextureUniforms()

        // Need to recreate the outline buffer as the outlineBuffer has changed due to background
        createOutlineBuffer()
    }

    private fun adjustCropping(surfaceSize: SizeF) {
        val imageCropFgd =
            ImageCrop.centerCoverCrop(
                surfaceSize.width,
                surfaceSize.height,
                rainConfig.foreground.width.toFloat(),
                rainConfig.foreground.height.toFloat()
                foreground.width.toFloat(),
                foreground.height.toFloat()
            )
        rainConfig.rainShowerShader.setFloatUniform(
            "uvOffsetFgd",
@@ -127,8 +146,8 @@ class RainEffect(
            ImageCrop.centerCoverCrop(
                surfaceSize.width,
                surfaceSize.height,
                rainConfig.background.width.toFloat(),
                rainConfig.background.height.toFloat()
                background.width.toFloat(),
                background.height.toFloat()
            )
        rainConfig.rainShowerShader.setFloatUniform(
            "uvOffsetBgd",
@@ -159,13 +178,13 @@ class RainEffect(

    private fun updateTextureUniforms() {
        val foregroundBuffer =
            BitmapShader(rainConfig.foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
            BitmapShader(foreground, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        rainConfig.rainShowerShader.setInputBuffer("foreground", foregroundBuffer)
        rainConfig.outlineShader.setInputBuffer("texture", foregroundBuffer)

        rainConfig.rainShowerShader.setInputBuffer(
            "background",
            BitmapShader(rainConfig.background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
            BitmapShader(background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        )
    }

@@ -198,7 +217,8 @@ class RainEffect(
    }

    private fun updateRainGridSize(surfaceSize: SizeF) {
        val widthScreenScale = GraphicsUtils.computeDefaultGridSize(surfaceSize, rainConfig.pixelDensity)
        val widthScreenScale =
            GraphicsUtils.computeDefaultGridSize(surfaceSize, rainConfig.pixelDensity)
        rainConfig.rainShowerShader.setFloatUniform("gridScale", widthScreenScale)
        rainConfig.glassRainShader.setFloatUniform("gridScale", widthScreenScale)
    }
Loading