如何仅在图像上应用Sobel滤波器或Frei-Chen滤波器?

时间:2015-01-28 19:49:53

标签: javascript filter three.js post-processing sobel

我用一个需要可视化图像层的例子来测试Three.js:

enter image description here

当我使用'THREE.EdgeShader'或'THREE.EdgeShader2'时,我获得了图像过滤器下一张图片显示了获得的结果:

enter image description here

我的问题出现了,因为场景也被修改了。所以,我只需要为图像应用滤镜。另外,我要求在应用滤镜后,所有导致黑色的像素都是透明的。你能帮帮我吗?

代码是:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Webgl - postprocessing</title>
        <meta charset="utf-8">
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
        <meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link rel=stylesheet href="css/base.css"/>
    </head>
    <body>

        <script src="js/three.min.js"></script>
        <script src="js/Detector.js"></script>
        <script src="js/OrbitControls.js"></script>
        <script src="js/THREEx.FullScreen.js"></script>
        <script src="js/THREEx.KeyboardState.js"></script>
        <script src="js/THREEx.WindowResize.js"></script>

        <script src="js/libs/stats.min.js"></script>
        <script type='text/javascript' src='js/libs/dat.gui.min.js'></script>

        <script src="js/postprocessing/EffectComposer.js"></script>
        <script src="js/shaders/CopyShader.js"></script>
        <script src="js/postprocessing/RenderPass.js"></script>
        <script src="js/postprocessing/MaskPass.js"></script>
        <script src="js/postprocessing/ShaderPass.js"></script>

        <script src="js/shaders/EdgeShader.js"></script>
        <script src="js/shaders/EdgeShader2.js"></script>

        <script src="js/shaders/BokehShader2.js"></script>

        <script id="vertexShader" type="x-shader/x-vertex">
            uniform vec3 viewVector;
            uniform float c;
            uniform float p;
            varying float intensity;
            void main()
            {
                vec3 vNormal = normalize( normalMatrix * normal );
                vec3 vNormel = normalize( normalMatrix * viewVector );
                intensity = pow( c - dot(vNormal, vNormel), p );

                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            }
        </script>

        <!-- fragment shader a.k.a. pixel shader -->
        <script id="fragmentShader" type="x-shader/x-vertex">
            uniform vec3 glowColor;
            varying float intensity;
            void main()
            {
                vec3 glow = glowColor * intensity;
                gl_FragColor = vec4( glow, 1.0 );
            }
        </script>

        <div id="Test3D" style="position: absolute; left:0px; top:0px"></div>    

        <script>

            var myImage;
            var container, scene, camera, renderer, controls, stats;
            var composer, object, light, View_Angle;
            var keyboard = new THREEx.KeyboardState();
            var clock = new THREE.Clock();
            var  Screen_Width, Screen_Height;

            var edgeEffect, edgeEffect2;

            var gui, parameters;

            initScene();
            animateScene();

            function setScene() {
                // Create the scene
                scene = new THREE.Scene();
            }

            function setContainer(renderer) {
                container = document.getElementById( 'Test3D' ).appendChild( renderer.domElement );
            }

            function renderer() {
                if ( Detector.webgl )
                    renderer = new THREE.WebGLRenderer( ); //{antialias:true} );
                else
                    renderer = new THREE.CanvasRenderer();

                renderer.setSize(Screen_Width, Screen_Height);  
                setContainer(renderer);
            }

            function setCamera(x, y, z)  {
                // Get the size of the inner window (content area) to create a full size renderer
                Screen_Width = window.innerWidth, Screen_Height = window.innerHeight;
                View_Angle = 45, ASPECT = Screen_Width / Screen_Height, NEAR = 0.1, FAR = 20000;

                // Create the camera
                camera = new THREE.PerspectiveCamera( View_Angle, ASPECT, NEAR, FAR);
                camera.position.set(x,y,z);
                scene.add(camera);
                camera.lookAt(scene.position);
            }

            function setEvents() {  
                THREEx.WindowResize(renderer, camera);
                THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
            }

            function setOrbitControls() {
                controls = new THREE.OrbitControls( camera, renderer.domElement );
            }

            function setStats() {
                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.bottom = '0px';
                stats.domElement.style.zIndex = 100;
                container.appendChild( stats.domElement );
            }

            function setFloor(image) {
                var floorTexture = new THREE.ImageUtils.loadTexture( image );
                floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; 
                floorTexture.repeat.set( 1, 1 );
                var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
                var floorGeometry = new THREE.PlaneBufferGeometry(1000, 1000, 10, 10);
                var floor = new THREE.Mesh(floorGeometry, floorMaterial);
                floor.position.y = 5;
                floor.rotation.x = Math.PI / 2;
                scene.add(floor);
            }

            function setSkyBox_FOG(isFog, color) {
                var skyBoxGeometry = new THREE.BoxGeometry( 10000, 10000, 10000 );
                var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: color, side: THREE.BackSide } );
                var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
                scene.add(skyBox);
                if (isFog) {
                    scene.fog = new THREE.FogExp2( color, 0.00025 );
                }
            }

            function setAmbientLight(color) {
                light = new THREE.AmbientLight( color );
                scene.add( light );
            }

            function initScene() {                
                setScene() //scene = new THREE.Scene();
                setCamera(500, 0, 600);
                renderer();
                setEvents();
                setOrbitControls();
                setStats() // STATS
                setSkyBox_FOG(false, 0xB0C4DE); // SKYBOX/FOG

                CreateImages();
                PostProcessing();
                setAmbientLight(0xeeeeee);

                initGUI(); // GUI
            }

            function createMaterial() {
                /*
                var materialCameraPosition = camera.position.clone();
                var material = new THREE.ShaderMaterial(
                {
                    uniforms: {
                        "c": { type: "f", value: 128.0 },
                        "p": { type: "f", value: 3 },
                        glowColor: { type: "c", value: new THREE.Color(0x84ccff) },
                        viewVector: { type: "v3", value: materialCameraPosition }
                    },
                    vertexShader: document.getElementById('vertexShader').textContent,
                    fragmentShader: document.getElementById('fragmentShader').textContent,
                    //shading: THREE.FlatShading,
                    //side: THREE.FrontSide,
                    side: THREE.DoubleSide,
                    blending: THREE.AdditiveBlending,
                    transparent: true,
                    //opacity: 0.5,
                    depthWrite: false
                });
                */

                var material = new THREE.MeshPhongMaterial({
                    shading: THREE.FlatShading,
                    side: THREE.DoubleSide 
                });
                return material;
            }

            function createImage(x, y, imageName, posX)  {                
                var material = createMaterial();
                var geometry = new THREE.PlaneBufferGeometry( x, y );
                material.map = THREE.ImageUtils.loadTexture(imageName);

                var mesh = new THREE.Mesh( geometry, material );
                mesh.position.z = posX;

                scene.add( mesh );
                return mesh;
            }

            function CreateImages() {
                for ( var i = 0; i < 5; i ++ ) {
                    createImage(512,246, 'beach.jpg', i*30 + 100);
                }
            }

            function PostProcessing() {

                // basic renderer that renders the scene, and uses the
                // effectCopy shader to output the image to the defined
                // rendertarget.
                composer = new THREE.EffectComposer( renderer );                 
                composer.addPass( new THREE.RenderPass(scene, camera) );

                edgeEffect = new THREE.ShaderPass( THREE.EdgeShader );
                edgeEffect.uniforms[ 'aspect' ].value.set(window.innerWidth, window.innerHeight);
                composer.addPass( edgeEffect );

                edgeEffect2 = new THREE.ShaderPass( THREE.EdgeShader2 );
                edgeEffect2.uniforms[ 'aspect' ].value.set(window.innerWidth, window.innerHeight);
                composer.addPass( edgeEffect2 );

                var effectCopy = new THREE.ShaderPass( THREE.CopyShader);
                effectCopy.renderToScreen = true;
                composer.addPass( effectCopy );

                window.addEventListener( 'resize', onWindowResize, false );

                initializeParameters(false, false, false, false);


                //http://www.html5rocks.com/en/tutorials/canvas/imagefilters/

/*              
                Filters.threshold = function(pixels, threshold) {
                    var d = pixels.data;
                    for (var i=0; i<d.length; i+=4) {
                        var r = d[i];
                        var g = d[i+1];
                        var b = d[i+2];
                        var v = (0.2126*r + 0.7152*g + 0.0722*b >= threshold) ? 255 : 0;
                        d[i] = d[i+1] = d[i+2] = v
                    }
                    return pixels;
                };


                var grayscale = Filters.filterImage(Filter.grayscale, image);
                // Note that ImageData values are clamped between 0 and 255, so we need
                // to use a Float32Array for the gradient values because they
                // range between -255 and 255.
                var vertical = Filters.convoluteFloat32(grayscale,
                  [ -1, 0, 1,
                    -2, 0, 2,
                    -1, 0, 1 ]);
                var horizontal = Filters.convoluteFloat32(grayscale,
                  [ -1, -2, -1,
                     0,  0,  0,
                     1,  2,  1 ]);
                var final_image = Filters.createImageData(vertical.width, vertical.height);
                    for (var i=0; i<final_image.data.length; i+=4) {
                        // make the vertical gradient red
                        var v = Math.abs(vertical.data[i]);
                        final_image.data[i] = v;
                        // make the horizontal gradient green
                        var h = Math.abs(horizontal.data[i]);
                        final_image.data[i+1] = h;
                        // and mix in some blue for aesthetics
                        final_image.data[i+2] = (v+h)/4;
                        final_image.data[i+3] = 255; // opaque alpha
                    }
*/

            }


            function initializeParameters(EdgeDetection, EdgeDetection2) {
                edgeEffect.enabled = EdgeDetection;
                edgeEffect2.enabled = EdgeDetection2;
            }

            function initGUI() {

                gui = new dat.GUI({
                    height : 5 * 32 - 1
                });

                parameters = {
                    EdgeDetection: false,   // Edge Detection (Frei-Chen Filter)
                    EdgeDetection2: false,  // Edge Detection (Sobel Filter)
                    EdgeAspect: 512,
                    Threshold: 0.5,
                    reset: function() { 
                        parameters.EdgeDetection = false;   
                        parameters.EdgeDetection2 = false;
                        parameters.EdgeAspect = 512;
                        parameters.Threshold =  0.5;
                        initializeParameters(false, false, false, false);
                    }
                };

                var filters = gui.addFolder('Filters');
                filters.add( parameters, 'EdgeDetection').name('Frei-Chen Filter').listen().onChange( 
                    function(value) { 
                        edgeEffect.enabled = value;
                    });
                filters.add( parameters, 'EdgeDetection2').name('Sobel Filter').listen().onChange( 
                    function(value) { 
                        edgeEffect2.enabled = value;
                    });
                filters.open();

                var edgeAspect = gui.add( parameters, "EdgeAspect", 128, 2048 ).listen().onChange( 
                    function(value) {
                        //
                        edgeEffect.uniforms.aspect.value = new THREE.Vector2(value, value);
                    });
                var threshold = gui.add( parameters, "Threshold", 0, 1, 0.001 ).listen().onChange( 
                    function(value) {
                        //
                    });

                gui.add( parameters, 'reset' ).name("Reset Parameters");

                gui.open();
            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

                edgeEffect.uniforms[ 'aspect' ].value.set(window.innerWidth, window.innerHeight);
                edgeEffect2.uniforms[ 'aspect' ].value.set(window.innerWidth, window.innerHeight);
            }

            function update() {
                controls.update();
                stats.update();
            }

            function animateScene() {
                // render using requestAnimationFrame
                requestAnimationFrame( animateScene );
                renderer.autoClear = false;
                renderer.clear();                
                composer.render();
                update();
            }

        </script>
    </body>
</html>

0 个答案:

没有答案