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

Commit 0c4174de authored by Yein Jo's avatar Yein Jo
Browse files

Refactor rain effect

Separate out shaders as layer based: rain shower, glass rain, and color
grading. Blurred background logic is removed as it is not used anymore.
This is not the final effect. Please refer to the comment to find the
reference prototype CL.

Bug: 325090421
Test: gradle, m
Flag: NA
Change-Id: I53223215caf38e5c088c4e0543bf780c50cd95d8
parent bb969804
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -240,9 +240,9 @@ class WallpaperEffectsDebugActivity : TorusViewerActivity() {
        // TODO(b/300991599): Add debug assets.
        private const val FOREGROUND_IMAGE_1 = "test-foreground.png"
        private const val BACKGROUND_IMAGE_1 = "test-background.png"
        private const val FOREGROUND_IMAGE_2 = "test-background2.png"
        private const val FOREGROUND_IMAGE_2 = "test-foreground2.png"
        private const val BACKGROUND_IMAGE_2 = "test-background2.png"
        private const val FOREGROUND_IMAGE_3 = "test-background3.png"
        private const val FOREGROUND_IMAGE_3 = "test-foreground3.png"
        private const val BACKGROUND_IMAGE_3 = "test-background3.png"
        private const val SET_WALLPAPER_REQUEST_CODE = 2
    }
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ struct GlassRain {
};

/**
 * Generates information to show some rain running down a foggy glass surface.
 * Generates a single layer of rain running down on a foggy glass surface.
 *
 * @param uv the UV of the fragment where we will display the rain effect.
 * @param screenAspectRatio the aspect ratio of the fragment where we will display the effect.
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

 /* Color and intensity constants. */
 // The color of the highlight of each drop.
 const vec3 highlightColor = vec3(1.); // white
 // The color of the contact ambient occlusion shadow.
 const vec3 contactShadowColor = vec3(0.); // black
 // The tint color of the drop.
 const vec3 dropTint = vec3(1.); // white

 // The multiplier for the tint in the drops.
 const float dropTintIntensity = 0.09;
 // The multiplier for the highlight of the drops.
 const float highlightIntensity = 0.7;
 // The multiplier for the contact shadow of the drops.
 const float dropShadowIntensity = 0.5;
 No newline at end of file
+0 −197
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 shader foreground;
uniform shader background;
uniform shader blurredBackground;
uniform float2 uvOffsetFgd;
uniform float2 uvScaleFgd;
uniform float2 uvOffsetBgd;
uniform float2 uvScaleBgd;
uniform float time;
uniform float screenAspectRatio;
uniform float2 screenSize;
uniform half intensity;

#include "shaders/constants.agsl"
#include "shaders/utils.agsl"
#include "shaders/glass_rain.agsl"
#include "shaders/rain.agsl"

/* Constants that can be modified. */
// The color of the highlight of each drop.
const vec4 highlightColor = vec4(vec3(1.), 1.); // white
// The color of the contact ambient occlusion shadow.
const vec4 contactShadowColor = vec4(vec3(0.), 1.); // black
// The color of the contact ambient occlusion shadow.
const vec4 dropTint = vec4(vec3(1.), 1.); // white
// Glass tint.
const vec4 glassTint = vec4(vec3(0.5), 1.); // gray
// rain tint.
const vec4 rainTint = vec4(vec3(0.5), 1.); // gray

// How much of tint we want in the drops.
const float dropTintIntensity = 0.09;
// How much of highlight we want.
const float uHighlightIntensity = 0.7;
// How much of contact shadow we want.
const float uDropShadowIntensity = 0.5;
// rain visibility (how visible it is).
const float rainVisibility = 0.4;
// How heavy it rains. 1: heavy showers; 0: no rain.
const float rainIntensity = 0.21;

vec4 main(float2 fragCoord) {
    float2 uv = fragCoord / screenSize;
    // Adjusts the UVs to have the expected rect of the image.
    float2 uvTextureBgd = fragCoord * uvScaleBgd + uvOffsetBgd;
    vec4 colorForeground = foreground.eval(fragCoord * uvScaleFgd + uvOffsetFgd);
    vec4 color = vec4(0., 0., 0., 1.);

    // Generate small glass rain.
    GlassRain drippingRain = generateGlassRain(
         uv,
         screenAspectRatio,
         time,
         /* Grid size = */ vec2(4.0, 2.0),
         intensity);
    float dropMask = drippingRain.dropMask;
    float droppletsMask = drippingRain.droppletsMask;
    float trailMask = drippingRain.trailMask;
    vec2 dropUvMasked = drippingRain.drop * drippingRain.dropMask;
    vec2 droppletsUvMasked = drippingRain.dropplets * drippingRain.droppletsMask;

    // Generate medium glass rain and combine with small one.
    drippingRain = generateGlassRain(
          uv,
          screenAspectRatio,
          time * 1.267,
          /* Grid size = */ vec2(3.0, 1.0),
          intensity);
    dropMask = max(drippingRain.dropMask, dropMask);
    droppletsMask = max(drippingRain.droppletsMask, droppletsMask);
    trailMask = max(drippingRain.trailMask, trailMask);
    dropUvMasked = mix(dropUvMasked,
        drippingRain.drop * drippingRain.dropMask, drippingRain.dropMask);
    droppletsUvMasked = mix(droppletsUvMasked,
        drippingRain.dropplets * drippingRain.droppletsMask, drippingRain.droppletsMask);

    /* Generate distortion UVs. */
    // UV distortion for the drop and dropplets.
    float distortionDrop = 1.0;
    float distortionDropplets = 0.6;
    vec2 uvDiffractionOffsets =
        distortionDrop * dropUvMasked + distortionDropplets * droppletsUvMasked;

    // Get color of the background texture.
    color = background.eval(uvTextureBgd + uvDiffractionOffsets * screenSize);

    // Add some slight tint to the fog glass. Since we use gray, we reduce the contrast.
    vec3 blurredImage = mix(blurredBackground.eval(uvTextureBgd).rgb, glassTint.rgb, 0.07);
    // The blur mask (when we will show the regular background).
    float blurMask = smoothstep(0.5, 1., max(trailMask, max(dropMask, droppletsMask)));
    color.rgb = mix(blurredImage, color.rgb, blurMask);

    /*
     * Drop coloring. This section is important to make the drops visible when we have a solid
     * color as a background (since we rely normally on the UV distortion).
     */
    // Tint the rain drops.
    color.rgb = mix(
        color.rgb,
        dropTint.rgb,
        dropTintIntensity * smoothstep(0.7, 1., max(dropMask, droppletsMask)));
    // add highlight to drops.
    color.rgb = mix(
        color.rgb,
        highlightColor.rgb,
        uHighlightIntensity
            // Adjust this scalars to make it visible.
            * smoothstep(0.05, 0.08, max(dropUvMasked * 1.4, droppletsUvMasked * 1.7)).x);
    // add shadows to drops.
    color.rgb = mix(
        color.rgb,
        contactShadowColor.rgb,
        uDropShadowIntensity *
            // Adjust this scalars to make it visible.
            smoothstep(0.055, 0.1, max(length(dropUvMasked * 1.7),
                length(droppletsUvMasked * 1.9))));

    // Add rotation for the rain (as a default sin(time * 0.05) can be used).
    float variation = wiggle(time - uv.y * 1.1, 0.10);
    uv = rotateAroundPoint(uv, vec2(0.5, -1.42), variation * PI / 9.);

    // Generate rain behind the subject.
    Rain rain = generateRain(
          uv,
          screenAspectRatio,
          time * 18.,
          /* Grid size = */ vec2(20.0, 2.0),
          intensity);

    color.rgb = mix(color.rgb, highlightColor.rgb, rainVisibility * rain.dropMask);

    // Mid layer
    // Generate rain behind the subject.
    rain = generateRain(
          uv,
          screenAspectRatio,
          time * 21.4,
          /* Grid size = */ vec2(30.0, 4.0),
          intensity);

    color.rgb = mix(color.rgb, highlightColor.rgb, rainVisibility * rain.dropMask);

    // Add the foreground. Any effect from here will be in front of the subject.
    color.rgb = normalBlend(color.rgb, colorForeground.rgb, colorForeground.a);

    // Generate rain in front of the subject (bigger and faster).
    rain = generateRain(
          uv,
          screenAspectRatio,
          time * 27.,
          /* Grid size = */ vec2(8.0, 3.0),
          intensity);

    // The rain that is closer, make it less visible
    color.rgb = mix(color.rgb, highlightColor.rgb, 0.7 * rainVisibility * rain.dropMask);

    /* Debug rain drops on glass */
    // resets color.
    // color.rgb *= 0.;
    // Shows the UV of each cell.
    // color.rg = drippingRain.cellUv.xy;
    // Shows the grid.
    // if (drippingRain.cellUv.x > 0.49 || drippingRain.cellUv.y > 0.49) color.r = 1.0;
    // Shows the main drop mask.
    // color.rgb += drippingRain.dropMask;
    // Shows the dropplets mask.
    // color.rgb += drippingRain.droppletsMask;
    // Shows the trail.
    // color.rgb += drippingRain.trailMask * 0.3;
    // background blurMask.
    // color.rgb += blurMask;
    // tears uv.
    // color.rg += -droppletsUvMasked;

    /* Debug rain */
    // resets color.
    // color.rgb *= 0.;
    // color.rgb += rain.dropMask;
    // if (rain.cellUv.x > 0.49 || rain.cellUv.y > 0.49) color.r = 1.0;

    return color;
}
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 shader texture;
uniform float time;
uniform float screenAspectRatio;
uniform float2 screenSize;
uniform half intensity;

#include "shaders/constants.agsl"
#include "shaders/utils.agsl"
#include "shaders/glass_rain.agsl"
#include "shaders/rain_constants.agsl"

vec4 main(float2 fragCoord) {
    float2 uv = fragCoord / screenSize;

    // 1. Generate small glass rain.
    GlassRain smallDrippingRain = generateGlassRain(
         uv,
         screenAspectRatio,
         time,
         /* Grid size = */ vec2(4.0, 2.0),
         intensity);
    float dropMask = smallDrippingRain.dropMask;
    float droppletsMask = smallDrippingRain.droppletsMask;
    float trailMask = smallDrippingRain.trailMask;
    vec2 dropUvMasked = smallDrippingRain.drop * dropMask;
    vec2 droppletsUvMasked = smallDrippingRain.dropplets * droppletsMask;

    // 2. Generate medium size glass rain.
    GlassRain medDrippingRain = generateGlassRain(
          uv,
          screenAspectRatio,
          time * 1.267,
          /* Grid size = */ vec2(3.5, 1.5),
          intensity);

    // 3. Combine those two glass rains.
    dropMask = max(medDrippingRain.dropMask, dropMask);
    droppletsMask = max(medDrippingRain.droppletsMask, droppletsMask);
    trailMask = max(medDrippingRain.trailMask, trailMask);
    dropUvMasked = mix(dropUvMasked,
        medDrippingRain.drop * medDrippingRain.dropMask, medDrippingRain.dropMask);
    droppletsUvMasked = mix(droppletsUvMasked,
        medDrippingRain.dropplets * medDrippingRain.droppletsMask, medDrippingRain.droppletsMask);

    // 4. Distort uv for the rain drops and dropplets.
    float distortionDrop = -0.1;
    vec2 uvDiffractionOffsets =
        distortionDrop * dropUvMasked;
    vec2 s = screenSize;
    // Ensure the diffracted image in drops is not inverted.
    s.y *= -1;

    vec4 color = texture.eval(fragCoord);
    vec3 sampledColor = texture.eval(fragCoord + uvDiffractionOffsets * s).rgb;
    color.rgb = mix(color.rgb, sampledColor, max(dropMask, droppletsMask));

    // 5. Add color tint to the rain drops.
    color.rgb = mix(
        color.rgb,
        dropTint,
        dropTintIntensity * smoothstep(0.7, 1., max(dropMask, droppletsMask)));

    // 6. Add highlight to the drops.
    color.rgb = mix(
        color.rgb,
        highlightColor,
        highlightIntensity
            * smoothstep(0.05, 0.08, max(dropUvMasked * 1.7, droppletsUvMasked * 2.6)).x);

    // 7. Add shadows to the drops.
    color.rgb = mix(
        color.rgb,
        contactShadowColor,
        dropShadowIntensity *
            smoothstep(0.055, 0.1, max(length(dropUvMasked * 1.7),
                length(droppletsUvMasked * 1.9))));

    return color;
}
 No newline at end of file
Loading