Best way to implement full-screen fade to black?

In my current project, the user has the ability to move from one predefined position to another with the use of navigation buttons.
Once the button is clicked, the whole screen fades to black, the camera gets moved to the new position and the screen fades back in.

Right now I am doing this using a DIV overlay and CSS transitions. Unfortunately, that doesn’t work when using VR. My best idea for an alternative would be using a custom post process, but I wanted to see if there is a simpler solution that I’m missing.

The postprocess effect is the best option here:
https://www.babylonjs-playground.com/#1AP18W#3

The code is in comments but it is easy to restore

(Was also used in here: Website/babylon.demo.js at master · BabylonJS/Website · GitHub for the Sponza demo)

3 Likes

https://www.babylonjs-playground.com/#40Y6CY#68

3 Likes

a pure BJS way to do it simply : https://www.babylonjs-playground.com/#1AP18W#16

3 Likes

Haha. Ingenius, Jerome! Whenever a Jerome playground arrives, we always expect advanced math and fancy terms like “barycenter”. This time…

scene.registerBeforeRender(function() {
    light.intensity -=0.02
    scene.clearColor.r -=0.01;
    scene.clearColor.g -=0.01;
    scene.clearColor.b -=0.01;
})

This code is SO wingnut-ish! Nice. I wonder if it works on scenes with GUI.

I suppose… just add: advancedDynamicTexture._mainTexture.level -= 0.01;

Heavy-CPU experimental PG here. (Wingnut having issues with the coding.)

Also, issues with post-processes, too, it seems. Perhaps a new scene.level property? :yum:

3 Likes

You can even use the GUI: https://www.babylonjs-playground.com/#1AP18W#18 :wink:

3 Likes

Man, love all the ideas!

Unfortunately changing clearColor and light doesn’t work for me, since I have meshes with an emissive color and then things get kinda weird: https://www.babylonjs-playground.com/#1AP18W#19

Since my project is pretty big already, I didn’t want to add GUI as well, but that’s a really clever idea!

I ended up adding the pixelFade to my post processes with a minor change:

        precision highp float;

        varying vec2 vUV;
		uniform sampler2D textureSampler;
		uniform float fadeLevel;

		void main(void){
			vec4 baseColor = texture2D(textureSampler, vUV);
			gl_FragColor = mix(baseColor, vec4(0., 0., 0., 1.), fadeLevel);
		}

Since my page background isn’t black, just changing the alpha channel didn’t work for me.

2 Likes

gl_FragColor = baseColor*(1.-fadeLevel) + vec4(0., 0., 0., 1.)* fadeLevel;

@nasimiasl you could rely on mix here instead :slight_smile:

really i dont know that
i need read more

mix - OpenGL 4 Reference Pages and The Book of Shaders: mix

gl_FragColor = mix(baseColor, vec4(0., 0., 0., 1.), fadeLevel);

2 Likes

The Book of Shaders is really a godsend. Such a good resource to get into GLSL.

2 Likes

Not “the best way”, but I’ll just add an alternative.

For fade to black:

made body style=‘background: black;’ and used jquery to

$(‘canvas’).fadeOut(3000);

loadScene()

$(‘canvas’).fadeIn(3000);

Didn’t know about the options above. Good to know now.

2 Likes

In the end, it’s always a quad with an alpha texture drawn on top of your scene. There’s is no “better” way, since it will always cost a full screen overdraw.

2 Likes

Makes sense. ? 9Apps VidMate apk

If you are using PBR, then animating the property scene.pbrIntensity, I think that is the name, every mesh will darken evenly. You would also need to do the same for any lights. I have not been using lights with PBR so far.

Would some regular HTML element work?

<script>
var cover = document.createElement('div')
cover.classList.add('fade-in')
document.getElementById('canvas-container').appendChild(cover)
</script>

.fade-in {
    background:black;
    -webkit-animation: fadein 2s; /* Safari, Chrome and Opera > 12.1 */
       -moz-animation: fadein 2s; /* Firefox < 16 */
        -ms-animation: fadein 2s; /* Internet Explorer */
         -o-animation: fadein 2s; /* Opera < 12.1 */
            animation: fadein 2s;
}

@keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Firefox < 16 */
@-moz-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}
/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Internet Explorer */
@-ms-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Opera < 12.1 */
@-o-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

?

Or you could do a fullscreen plane over the camera and animate its opacity.
https://www.babylonjs-playground.com/#LMJ5M7#0

2 Likes

LIKE - “fullscreen plane over the camera and animate its opacity”

Very cool how to set 2D size the same as canvas AND place in front of cam.

Looks like ANM is not far off. Like the shader very much.

Someday we will try to experiment more with this concept.