awayjs / renderer

Interface for scene and material modules
75 stars 20 forks source link

BitmapData: Reflection with canvas #20

Closed FabianPP closed 11 years ago

FabianPP commented 11 years ago

canvas_correct Hi, I tried to make a reflection of a plane on another plane (with gradient to tranparent)

just like this: http://mrdoob.github.io/three.js/examples/canvas_materials_video.html

I tried 2 ways...but couldn´t get it working:

  1. using away.display.BitmapData.canvas
  2. create my own document.createElement( "canvas" ); After doing the gradient stuff I use it the following way: var bmpTex = new away.textures.BitmapTexture(flippedBitmap, false); var reflMatTx: away.materials.TextureMaterial = new away.materials.TextureMaterial( bmpTex);

both won´t work the way I expected.

The canvas itself (2D) looks fine. I tried many settings, but the result on the 3d plane never shows the gradient to alpha=0;

Here is what I do after loading an image:

var flipMatrix:away.geom.Matrix = new away.geom.Matrix(); flipMatrix.scale(1, -1); flipMatrix.translate(0, image.height); flippedBitmap = new away.display.BitmapData(image.width, image.height, true, 0); flippedBitmap.draw(image, flipMatrix);

        var flippedContext = flippedBitmap.canvas.getContext("2d");
        // document.body.appendChild(flippedBitmap.canvas);

        // add gradient
        var gradient = flippedContext.createLinearGradient(0, 0, 0, image.height);
        gradient.addColorStop(0.8, "rgba(255, 255, 255, 1.0)");
        gradient.addColorStop(1, "rgba(255, 255, 255, 0.5)");
        flippedContext.fillStyle = gradient;
        flippedContext.rect(0, 0, image.width, image.height);
        flippedContext.globalCompositeOperation = "destination-out";
        flippedContext.fill();

Here is how it works in threejs:

image = document.createElement( 'canvas' ); image.width = 480; image.height = 204;

            imageContext = image.getContext( '2d' );
            imageContext.fillStyle = '#000000';
            imageContext.fillRect( 0, 0, 480, 204 );

            texture = new THREE.Texture( image );
            texture.minFilter = THREE.LinearFilter;
            texture.magFilter = THREE.LinearFilter;

            var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );

            imageReflection = document.createElement( 'canvas' );
            imageReflection.width = 480;
            imageReflection.height = 204;

            imageReflectionContext = imageReflection.getContext( '2d' );
            imageReflectionContext.fillStyle = '#000000';
            imageReflectionContext.fillRect( 0, 0, 480, 204 );

            imageReflectionGradient = imageReflectionContext.createLinearGradient( 0, 0, 0, 204 );
            imageReflectionGradient.addColorStop( 0.2, 'rgba(240, 240, 240, 1)' );
            imageReflectionGradient.addColorStop( 1, 'rgba(240, 240, 240, 0.8)' );

            textureReflection = new THREE.Texture( imageReflection );
            textureReflection.minFilter = THREE.LinearFilter;
            textureReflection.magFilter = THREE.LinearFilter;

            var materialReflection = new THREE.MeshBasicMaterial( { map: textureReflection, side: THREE.BackSide, overdraw: true } );

--- end code ---

karimbeyrouti commented 11 years ago

Hi Fabian, do you have a code sample online - so I can take a look ?

FabianPP commented 11 years ago

Hi Karim,

not yet...but i´ll put something together asap

FabianPP commented 11 years ago

Here is the flat canvas code of the image above. Can you setup a prototype to use this as a texture?

http://www.mischen-impossible.de/away3d/canvasTest.html

karimbeyrouti commented 11 years ago

demo: http://kurst.co.uk/samples/awayts/reflectionTest/ source: http://kurst.co.uk/samples/awayts/ReflectionTest.ts

not much free time today - so not very pretty but should help :-)

FabianPP commented 11 years ago

wow! That was fast! THank you so much! Great help!

The reason why I couldn´t find any way was: material.alphaBlending = true;

karimbeyrouti commented 11 years ago

You welcome... would love to see what you come up with.

Adding source here for reference: // ///

module misc{

export class ReflectionTest
{
    private view : away.containers.View3D;
    private raf  : away.utils.RequestAnimationFrame;
    private reflectionMesh : away.entities.Mesh;

    constructor()
    {
        this.view   = new away.containers.View3D();
        this.raf    = new away.utils.RequestAnimationFrame( this.render , this );

        away.library.AssetLibrary.enableParser( away.loaders.ImageParser );

        var token : away.loaders.AssetLoaderToken = away.library.AssetLibrary.load( new away.net.URLRequest('assets/dots.png'));
            token.addEventListener(away.events.LoaderEvent.RESOURCE_COMPLETE , this.onResourceComplete , this );

        window.onresize = () => this.resize();

    }

    private onResourceComplete( e : away.events.LoaderEvent) : void
    {
        //var loader : AssetLoader = e.target as AssetLoader;
        var loader : away.loaders.AssetLoader   = <away.loaders.AssetLoader> e.target;
        var l       : number                    = loader.baseDependency.assets.length;

        for ( var c : number = 0 ; c < l ; c ++ )
        {

            var asset : away.library.IAsset = loader.baseDependency.assets[c];

            switch (asset.assetType)
            {

                case away.library.AssetType.TEXTURE:

                    var geom    : away.primitives.PlaneGeometry = new away.primitives.PlaneGeometry(500  , 500 , 1 , 1 , false );

                    var tx      : away.textures.HTMLImageElementTexture = <away.textures.HTMLImageElementTexture> asset;
                    var bitmap  : away.display.BitmapData = new away.display.BitmapData(  1024, 1024 , true )
                    bitmap.fillRect(bitmap.rect , 0x000000 )
                    bitmap.context.translate(0, 1024);
                    bitmap.context.scale(1, -1);
                    bitmap.context.drawImage(tx.htmlImageElement, 0, 0, 1024, 1024);

                    var gradient = bitmap.context.createLinearGradient(0, 0, 0, 1024);
                        gradient.addColorStop(0.8, "rgba(255, 255, 255, 1.0)");
                        gradient.addColorStop(1, "rgba(255, 255, 255, 0.5)");

                    bitmap.context.fillStyle = gradient;
                    bitmap.context.rect(0, 0, 1024, 1024);
                    bitmap.context.globalCompositeOperation = "destination-out";
                    bitmap.context.fill();

                    //document.body.appendChild(bitmap.canvas );

                    var bmpTX : away.textures.BitmapTexture = new away.textures.BitmapTexture( bitmap , false  );// Note: MipMaps are not yet supported - so image wont apear if false is not specified...

                    var material : away.materials.TextureMaterial = new away.materials.TextureMaterial( bmpTX );
                        material.bothSides = true;
                        material.alphaBlending = true;

                    this.reflectionMesh= new away.entities.Mesh( geom , material );

                    this.view.scene.addChild(this.reflectionMesh);

                    break;

            }

        }

        this.raf.start();
        this.resize();

    }

    private resize()
    {
        this.view.width = window.innerWidth;
        this.view.height= window.innerHeight;
    }

    private render()
    {
        this.reflectionMesh.rotationY +=.5;

        this.view.render();
    }

}

} window.onload = function () {

var test = new misc.ReflectionTest();

}

karimbeyrouti commented 11 years ago

Hi Fabian - there is an big with bitmapdata textures and globalCompositeOperation in Away3D TS. Not sure what it is yet - however - try without it ( by making your gradient fade to black / background colour instead of transparent ) . That is if you need to use it within the Away3D TS framework .

the issue is with that line: bitmap.context.globalCompositeOperation = "destination-out";

and logged here: https://github.com/away3d/away3d-core-ts/issues/21

FabianPP commented 11 years ago

Hi Karim,

I can´t see the bug. For me it works fine. I also thought about it earlier, to use the background color to achieve what I was looking for. But that is no alternative for me because my bg is not static. So I need the bitmap.context.globalCompositeOperation = "destination-out"; But like I said, it works for me.

karimbeyrouti commented 11 years ago

Thank you for the feedback - visual glitch is only when it used as texture in 3D ( Away3D TS ) .