Loading weathereffects/graphics/assets/shaders/sun_effect.agsl +15 −6 Original line number Diff line number Diff line Loading @@ -30,8 +30,8 @@ uniform mat3 transformMatrixWeather; #include "shaders/lens_flare.agsl" const vec2 sunCenter = vec2(0.57, -0.8); const vec3 godRaysColor = vec3(1., 0.857, 0.71428); const vec2 sunCenter = vec2(0.67, -1.0); float calculateRay(float angle, float time) { /* Loading Loading @@ -94,16 +94,25 @@ float checkBrightnessGodRaysAtCenter( } vec4 main(float2 fragCoord) { float2 aspectRatioAdj = vec2(1.); if (screenAspectRatio > 1) { aspectRatioAdj.x = screenAspectRatio; } else { aspectRatioAdj.y = 1. / screenAspectRatio; } // Apply transform matrix to fragCoord float2 adjustedUv = transformPoint(transformMatrixBitmap, fragCoord); float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize; uv -= vec2(0.5, 0.5); uv.y /= screenAspectRatio; vec2 sunVariation = vec2(0.1 * sin(time * 0.3), 0.14 * cos(time * 0.5)); sunVariation += 0.1 * (0.5 * sin(time * 0.456) + 0.5) * sunCenter / vec2(1., screenAspectRatio); vec2 sunPos = sunVariation + sunCenter / vec2(1., screenAspectRatio); //TODO(b/375214506): fix the uv position of the sun uv *= aspectRatioAdj; // Random sun variation based on sin/cos signal. vec2 sunVariation = 0.08 * vec2(sin(time * 0.3), cos(time * 0.5)); // Variation that moves sun on the same direction than the vector that goes from (0,0) // to sunCenter, but scaling distance. sunVariation += 0.1 * (0.5 * sin(time * 0.456) + 0.5) * sunCenter; vec2 sunPos = sunVariation + sunCenter; sunPos *= aspectRatioAdj; vec4 colorForeground = foreground.eval(adjustedUv); vec4 color = background.eval(adjustedUv); Loading weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/WeatherEffectBase.kt +32 −8 Original line number Diff line number Diff line Loading @@ -24,9 +24,9 @@ import android.graphics.RuntimeShader import android.graphics.Shader import android.util.SizeF import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.calculateTransformDifference import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.calculateTranslationDifference import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.centerCropMatrix import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScale import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScaleFromMatrixValues import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.invertAndTransposeMatrix import kotlin.random.Random Loading @@ -42,13 +42,22 @@ abstract class WeatherEffectBase( surfaceSize, SizeF(background.width.toFloat(), background.height.toFloat()), ) set(value) { field = value value.getValues(centerCropMatrixValues) } protected var parallaxMatrix = Matrix(centerCropMatrix) private val centerCropMatrixValues: FloatArray = FloatArray(9).apply { centerCropMatrix.getValues(this) } private val parallaxMatrixValues: FloatArray = FloatArray(9).apply { parallaxMatrix.getValues(this) } // Currently, we use same transform for both foreground and background protected open val transformMatrixBitmap: FloatArray = FloatArray(9) // Apply to weather components not rely on image textures // Should be identity matrix in editor, and only change when parallax applied in homescreen private val transformMatrixWeather: FloatArray = FloatArray(9) protected var bitmapScale = getScale(centerCropMatrix) protected var bitmapScale = getScaleFromMatrixValues(centerCropMatrixValues) protected var elapsedTime: Float = 0f abstract val shader: RuntimeShader Loading @@ -57,14 +66,19 @@ abstract class WeatherEffectBase( abstract val colorGradingIntensity: Float override fun setMatrix(matrix: Matrix) { this.parallaxMatrix.set(matrix) bitmapScale = getScale(parallaxMatrix) this.parallaxMatrix.setAndUpdateFloatArray(matrix, parallaxMatrixValues) bitmapScale = getScaleFromMatrixValues(parallaxMatrixValues) adjustCropping(surfaceSize) } /** This function will be called every time parallax changes, don't do heavy things here */ open fun adjustCropping(newSurfaceSize: SizeF) { invertAndTransposeMatrix(parallaxMatrix, transformMatrixBitmap) calculateTransformDifference(centerCropMatrix, parallaxMatrix, transformMatrixWeather) calculateTranslationDifference( centerCropMatrixValues, parallaxMatrixValues, transformMatrixWeather, ) shader.setFloatUniform("transformMatrixBitmap", transformMatrixBitmap) shader.setFloatUniform("transformMatrixWeather", transformMatrixWeather) shader.setFloatUniform("screenSize", newSurfaceSize.width, newSurfaceSize.height) Loading @@ -75,6 +89,11 @@ abstract class WeatherEffectBase( override fun resize(newSurfaceSize: SizeF) { surfaceSize = newSurfaceSize centerCropMatrix = centerCropMatrix( surfaceSize, SizeF(background.width.toFloat(), background.height.toFloat()), ) adjustCropping(newSurfaceSize) updateGridSize(newSurfaceSize) } Loading Loading @@ -113,8 +132,8 @@ abstract class WeatherEffectBase( surfaceSize, SizeF(background.width.toFloat(), background.height.toFloat()), ) parallaxMatrix.set(centerCropMatrix) bitmapScale = getScale(centerCropMatrix) parallaxMatrix.setAndUpdateFloatArray(centerCropMatrix, parallaxMatrixValues) bitmapScale = getScaleFromMatrixValues(centerCropMatrixValues) shader.setInputBuffer( "background", BitmapShader(this.background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR), Loading @@ -139,6 +158,11 @@ abstract class WeatherEffectBase( ) } private fun Matrix.setAndUpdateFloatArray(src: Matrix, targetFloatArray: FloatArray) { set(src) src.getValues(targetFloatArray) } companion object { // When extracting the scale from the parallax matrix, there will be a very small difference // due to floating-point precision. Loading weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/utils/MatrixUtils.kt +51 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,10 @@ object MatrixUtils { return matrixValues[0] } fun getScaleFromMatrixValues(matrixValuesArray: FloatArray): Float { return matrixValuesArray[0] } /** * Calculates the transformation matrix that, when applied to `originMatrix`, results in * `targetMatrix`. Current use case: Calculating parallax effect for the homescreen compared Loading @@ -77,6 +81,53 @@ object MatrixUtils { return transposeMatrixArray(matrixValues, outArray) } /** * Calculates the difference in translation between two transformation matrices, represented as * FloatArrays (`centerCropMatrixValues` and `parallaxMatrixValues`), after scaling * `parallaxMatrixValues` to match the scale of `centerCropMatrixValues`. The resulting * translation difference is then stored in the provided `outArray` as a 3x3 translation matrix * (in column-major order). * * @param centerCropMatrixValues A FloatArray of length 9 representing the reference * transformation matrix (center-cropped view) in row-major order. * @param parallaxMatrixValues A FloatArray of length 9 representing the transformation matrix * whose translation difference relative to `centerCropMatrixValues` is to be calculated, also * in row-major order. This array will be scaled to match the scale of * `centerCropMatrixValues`. * @param outArray A FloatArray of length 9 to store the resulting 3x3 translation matrix. The * translation components (deltaX, deltaY) will be placed in the appropriate positions for a * column-major matrix. */ fun calculateTranslationDifference( centerCropMatrixValues: FloatArray, parallaxMatrixValues: FloatArray, outArray: FloatArray, ): FloatArray { val scaleX = centerCropMatrixValues[0] / parallaxMatrixValues[0] val scaleY = centerCropMatrixValues[4] / parallaxMatrixValues[4] val scaledParallaxTransX = parallaxMatrixValues[2] * scaleX val scaledParallaxTransY = parallaxMatrixValues[5] * scaleY val originTransX = centerCropMatrixValues[2] val originTransY = centerCropMatrixValues[5] val deltaTransX = originTransX - scaledParallaxTransX val deltaTransY = originTransY - scaledParallaxTransY outArray[0] = 1f outArray[1] = 0f outArray[2] = 0f outArray[3] = 0f outArray[4] = 1f outArray[5] = 0f outArray[6] = deltaTransX outArray[7] = deltaTransY outArray[8] = 1f return outArray } // Transpose 3x3 matrix values as a FloatArray[9], write results to outArray private fun transposeMatrixArray(inMatrixArray: FloatArray, outArray: FloatArray): FloatArray { for (i in 0 until 3) { Loading Loading
weathereffects/graphics/assets/shaders/sun_effect.agsl +15 −6 Original line number Diff line number Diff line Loading @@ -30,8 +30,8 @@ uniform mat3 transformMatrixWeather; #include "shaders/lens_flare.agsl" const vec2 sunCenter = vec2(0.57, -0.8); const vec3 godRaysColor = vec3(1., 0.857, 0.71428); const vec2 sunCenter = vec2(0.67, -1.0); float calculateRay(float angle, float time) { /* Loading Loading @@ -94,16 +94,25 @@ float checkBrightnessGodRaysAtCenter( } vec4 main(float2 fragCoord) { float2 aspectRatioAdj = vec2(1.); if (screenAspectRatio > 1) { aspectRatioAdj.x = screenAspectRatio; } else { aspectRatioAdj.y = 1. / screenAspectRatio; } // Apply transform matrix to fragCoord float2 adjustedUv = transformPoint(transformMatrixBitmap, fragCoord); float2 uv = transformPoint(transformMatrixWeather, fragCoord) / screenSize; uv -= vec2(0.5, 0.5); uv.y /= screenAspectRatio; vec2 sunVariation = vec2(0.1 * sin(time * 0.3), 0.14 * cos(time * 0.5)); sunVariation += 0.1 * (0.5 * sin(time * 0.456) + 0.5) * sunCenter / vec2(1., screenAspectRatio); vec2 sunPos = sunVariation + sunCenter / vec2(1., screenAspectRatio); //TODO(b/375214506): fix the uv position of the sun uv *= aspectRatioAdj; // Random sun variation based on sin/cos signal. vec2 sunVariation = 0.08 * vec2(sin(time * 0.3), cos(time * 0.5)); // Variation that moves sun on the same direction than the vector that goes from (0,0) // to sunCenter, but scaling distance. sunVariation += 0.1 * (0.5 * sin(time * 0.456) + 0.5) * sunCenter; vec2 sunPos = sunVariation + sunCenter; sunPos *= aspectRatioAdj; vec4 colorForeground = foreground.eval(adjustedUv); vec4 color = background.eval(adjustedUv); Loading
weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/WeatherEffectBase.kt +32 −8 Original line number Diff line number Diff line Loading @@ -24,9 +24,9 @@ import android.graphics.RuntimeShader import android.graphics.Shader import android.util.SizeF import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.calculateTransformDifference import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.calculateTranslationDifference import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.centerCropMatrix import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScale import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.getScaleFromMatrixValues import com.google.android.wallpaper.weathereffects.graphics.utils.MatrixUtils.invertAndTransposeMatrix import kotlin.random.Random Loading @@ -42,13 +42,22 @@ abstract class WeatherEffectBase( surfaceSize, SizeF(background.width.toFloat(), background.height.toFloat()), ) set(value) { field = value value.getValues(centerCropMatrixValues) } protected var parallaxMatrix = Matrix(centerCropMatrix) private val centerCropMatrixValues: FloatArray = FloatArray(9).apply { centerCropMatrix.getValues(this) } private val parallaxMatrixValues: FloatArray = FloatArray(9).apply { parallaxMatrix.getValues(this) } // Currently, we use same transform for both foreground and background protected open val transformMatrixBitmap: FloatArray = FloatArray(9) // Apply to weather components not rely on image textures // Should be identity matrix in editor, and only change when parallax applied in homescreen private val transformMatrixWeather: FloatArray = FloatArray(9) protected var bitmapScale = getScale(centerCropMatrix) protected var bitmapScale = getScaleFromMatrixValues(centerCropMatrixValues) protected var elapsedTime: Float = 0f abstract val shader: RuntimeShader Loading @@ -57,14 +66,19 @@ abstract class WeatherEffectBase( abstract val colorGradingIntensity: Float override fun setMatrix(matrix: Matrix) { this.parallaxMatrix.set(matrix) bitmapScale = getScale(parallaxMatrix) this.parallaxMatrix.setAndUpdateFloatArray(matrix, parallaxMatrixValues) bitmapScale = getScaleFromMatrixValues(parallaxMatrixValues) adjustCropping(surfaceSize) } /** This function will be called every time parallax changes, don't do heavy things here */ open fun adjustCropping(newSurfaceSize: SizeF) { invertAndTransposeMatrix(parallaxMatrix, transformMatrixBitmap) calculateTransformDifference(centerCropMatrix, parallaxMatrix, transformMatrixWeather) calculateTranslationDifference( centerCropMatrixValues, parallaxMatrixValues, transformMatrixWeather, ) shader.setFloatUniform("transformMatrixBitmap", transformMatrixBitmap) shader.setFloatUniform("transformMatrixWeather", transformMatrixWeather) shader.setFloatUniform("screenSize", newSurfaceSize.width, newSurfaceSize.height) Loading @@ -75,6 +89,11 @@ abstract class WeatherEffectBase( override fun resize(newSurfaceSize: SizeF) { surfaceSize = newSurfaceSize centerCropMatrix = centerCropMatrix( surfaceSize, SizeF(background.width.toFloat(), background.height.toFloat()), ) adjustCropping(newSurfaceSize) updateGridSize(newSurfaceSize) } Loading Loading @@ -113,8 +132,8 @@ abstract class WeatherEffectBase( surfaceSize, SizeF(background.width.toFloat(), background.height.toFloat()), ) parallaxMatrix.set(centerCropMatrix) bitmapScale = getScale(centerCropMatrix) parallaxMatrix.setAndUpdateFloatArray(centerCropMatrix, parallaxMatrixValues) bitmapScale = getScaleFromMatrixValues(centerCropMatrixValues) shader.setInputBuffer( "background", BitmapShader(this.background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR), Loading @@ -139,6 +158,11 @@ abstract class WeatherEffectBase( ) } private fun Matrix.setAndUpdateFloatArray(src: Matrix, targetFloatArray: FloatArray) { set(src) src.getValues(targetFloatArray) } companion object { // When extracting the scale from the parallax matrix, there will be a very small difference // due to floating-point precision. Loading
weathereffects/graphics/src/main/java/com/google/android/wallpaper/weathereffects/graphics/utils/MatrixUtils.kt +51 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,10 @@ object MatrixUtils { return matrixValues[0] } fun getScaleFromMatrixValues(matrixValuesArray: FloatArray): Float { return matrixValuesArray[0] } /** * Calculates the transformation matrix that, when applied to `originMatrix`, results in * `targetMatrix`. Current use case: Calculating parallax effect for the homescreen compared Loading @@ -77,6 +81,53 @@ object MatrixUtils { return transposeMatrixArray(matrixValues, outArray) } /** * Calculates the difference in translation between two transformation matrices, represented as * FloatArrays (`centerCropMatrixValues` and `parallaxMatrixValues`), after scaling * `parallaxMatrixValues` to match the scale of `centerCropMatrixValues`. The resulting * translation difference is then stored in the provided `outArray` as a 3x3 translation matrix * (in column-major order). * * @param centerCropMatrixValues A FloatArray of length 9 representing the reference * transformation matrix (center-cropped view) in row-major order. * @param parallaxMatrixValues A FloatArray of length 9 representing the transformation matrix * whose translation difference relative to `centerCropMatrixValues` is to be calculated, also * in row-major order. This array will be scaled to match the scale of * `centerCropMatrixValues`. * @param outArray A FloatArray of length 9 to store the resulting 3x3 translation matrix. The * translation components (deltaX, deltaY) will be placed in the appropriate positions for a * column-major matrix. */ fun calculateTranslationDifference( centerCropMatrixValues: FloatArray, parallaxMatrixValues: FloatArray, outArray: FloatArray, ): FloatArray { val scaleX = centerCropMatrixValues[0] / parallaxMatrixValues[0] val scaleY = centerCropMatrixValues[4] / parallaxMatrixValues[4] val scaledParallaxTransX = parallaxMatrixValues[2] * scaleX val scaledParallaxTransY = parallaxMatrixValues[5] * scaleY val originTransX = centerCropMatrixValues[2] val originTransY = centerCropMatrixValues[5] val deltaTransX = originTransX - scaledParallaxTransX val deltaTransY = originTransY - scaledParallaxTransY outArray[0] = 1f outArray[1] = 0f outArray[2] = 0f outArray[3] = 0f outArray[4] = 1f outArray[5] = 0f outArray[6] = deltaTransX outArray[7] = deltaTransY outArray[8] = 1f return outArray } // Transpose 3x3 matrix values as a FloatArray[9], write results to outArray private fun transposeMatrixArray(inMatrixArray: FloatArray, outArray: FloatArray): FloatArray { for (i in 0 until 3) { Loading