Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support rendering raindrops layer only #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

SardineFish
Copy link
Owner

Add an option to support rendering raindrops layer only without background.
Useful for blending raindrops layer with custom HTML elements.

Usage

const raindropFx = new RaindropFX({
    canvas: canvas,
    background: "/assets/img/84765992_p0.jpg",
    raindropLayerOnly: true,
});

Add an example /examples/detached-background

May solve the issue #2

@UstymUkhman
Copy link

Hi! I've tested this solution with a three.js canvas as a background, but in my case raindrop color is still black. Could you please check what I've been missing or if this PR isn't aimed to fix this problem. I'll be very gratefull! Awesome library by the way, I really ❤️ it! 😄

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Raindrop Effect</title>

    <link rel="stylesheet" href="./assets/css/style.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" integrity="sha512-dLxUelApnYxpLt6K2iomGngnHO83iUvZytA3YjDUCjT0HDOHKXnVYdf3hU4JjM8uEhxf9nD1/ey98U3t2vZ0qQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="./bundle/index.js"></script>
</head>

<body>
    <div id="root">
        <canvas id="canvas" style="position: absolute; left: 0; top: 0;"></canvas>
        <p id="loading">Loading...</p>
    </div>
    <script>
        const canvas = document.querySelector("#canvas");
        const rect = canvas.getBoundingClientRect();
        canvas.width = rect.width;
        canvas.height = rect.height;

        let camera, scene, renderer;
        let geometry, material, mesh;

        init();

        function init() {

            camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
            camera.position.z = 1;

            scene = new THREE.Scene();

            geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
            material = new THREE.MeshNormalMaterial();

            mesh = new THREE.Mesh( geometry, material );
            scene.add( mesh );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setSize( window.innerWidth, window.innerHeight );
            renderer.setClearColor(0xEEEEEE, 1);
            renderer.setAnimationLoop( animation );
            document.getElementById('root').prepend(renderer.domElement);

            const raindropFx = new RaindropFX({
                canvas: canvas,
                // backgroundBlurSteps: 0,
                // mistBlurStep: 0,
                // mist: false,
                background: renderer.domElement
            });

            raindropFx.start();

        }

        function animation( time ) {

            mesh.rotation.x = time / 2000;
            mesh.rotation.y = time / 1000;

            renderer.render( scene, camera );

        }

        window.onresize = () =>
        {
            const rect = canvas.getBoundingClientRect();
            raindropFx.resize(rect.width, rect.height);
        }
    </script>
</body>

</html>

And I've changed the render method in render.ts as follows:

render(raindrops: RainDrop[], time: Time)
{
    this.drawDroplet(time);
    this.drawMist(time.dt);
    this.drawRaindrops(raindrops);

    this.renderer.setRenderTarget(RenderTarget.CanvasTarget);
    this.renderer.clear(Color.black.transparent());
    // this.renderer.clear(Color.black);

    if (this.options.mist)
    {
        this.matrlMistCompose.mistTex = this.mistTexture;
        this.matrlMistCompose.texture = null;
        this.matrlMistCompose.mistColor = new Color(...this.options.mistColor);
        this.matrlMistCompose.mistColor.a = 0.1;
        this.renderer.blit(this.mistBackground, RenderTarget.CanvasTarget, this.matrlMistCompose);
    }

    // this.drawBackground();

    this.matrlCompose.background = this.blurryBackground;
    this.matrlCompose.backgroundSize = vec4(this.options.width, this.options.height, 1 / this.options.width, 1 / this.options.height);
    this.matrlCompose.raindropTex = this.raindropComposeTex;
    this.matrlCompose.dropletTex = this.dropletTexture;
    this.matrlCompose.mistTex = this.mistTexture;
    this.matrlCompose.smoothRaindrop = vec2(...this.options.smoothRaindrop);
    this.matrlCompose.refractParams = vec2(this.options.refractBase, this.options.refractScale);
    this.matrlCompose.lightPos = vec4(...this.options.raindropLightPos);
    this.matrlCompose.diffuseLight = new Color(...this.options.raindropDiffuseLight, this.options.raindropShadowOffset);
    this.matrlCompose.specularParams = vec4(...this.options.raindropSpecularLight, this.options.raindropSpecularShininess);
    this.matrlCompose.bump = this.options.raindropLightBump;

    this.renderer.blit(null, RenderTarget.CanvasTarget, this.matrlCompose);
}

Result:

result

@SardineFish
Copy link
Owner Author

If you want to use a another canvas as the background, in your case, the canvas created by three.js. You need to call raindropFx.setBackground(<threeJsCanvas>) every frame after threeJs complete the rendering. Since the background is fetched and stored staticly. And make sure the canvas created by threeJs enabled preserveDrawingBuffer to allow the framebuffer be fetched from canvas element.

@UstymUkhman
Copy link

@SardineFish Yep, that worked. Originaly I was using raindropFx.setBackground(<threeJsCanvas>) every frame in my render loop, but I haven't set preserveDrawingBuffer to true so that's why my test wasn't working. Thanks for the tip! May I suggest to add it into the Readme of this project?

I still have one more question though: I'm trying to add just the raindrops to my canvas with no blur and no mist effects. So basicaly, I want to configure RaindropFX like this:

raindropFx = new RaindropFX({
    canvas: canvas,
    backgroundBlurSteps: 0,
    mistBlurStep: 0,
    mist: false
});

but with this configuration raindrops (and/or the blur effect) are still black. I have to set backgroundBlurSteps and mistBlurStep to 1 in order to see some transparency. Is there a way to achieve raindrops transparency with no blur and no mist effects? Thank you so much!

@SardineFish
Copy link
Owner Author

@UstymUkhman

May I suggest to add it into the Readme of this project?

Thanks for that, I will update it soon, or feel free to make a PR.

Is there a way to achieve raindrops transparency with no blur and no mist effects?

Oh, I forgot this. Will be fixed soon, If you need right now, you can just change this line src/renderer.ts#L356 into

if (this.options.blurStep == 0)
   this.matrlCompose.background = this.background; // Use the original background without blur
else 
  this.matrlCompose.background = this.blurryBackground;

I haven't tested but this should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants