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

Javascript 如何仅在图像上应用Sobel过滤器或Frei Chen过滤器?,javascript,filter,three.js,post-processing,sobel,Javascript,Filter,Three.js,Post Processing,Sobel,我用一个需要可视化图像层的示例测试Three.js,如下所示: 当我使用“THREE.EdgeShader”或“THREE.EdgeShader 2”时,我获得图像的过滤器,下一幅图像显示获得的结果: 我的问题出现了,因为场景也被修改了。所以,我只需要对图像应用过滤器。此外,我要求在应用过滤器后,所有产生黑色的像素都是透明的。你能帮我吗 代码是: <!DOCTYPE html> <html lang="en"> <head> <

我用一个需要可视化图像层的示例测试Three.js,如下所示:

当我使用“THREE.EdgeShader”或“THREE.EdgeShader 2”时,我获得图像的过滤器,下一幅图像显示获得的结果:

我的问题出现了,因为场景也被修改了。所以,我只需要对图像应用过滤器。此外,我要求在应用过滤器后,所有产生黑色的像素都是透明的。你能帮我吗

代码是:

<!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>

Webgl-后处理
均匀vec3视向量;
均匀浮点数c;
均匀浮动p;
浮动强度变化;
void main()
{
vec3 vNormal=规格化(normalMatrix*normal);
vec3 vNormel=规格化(normalMatrix*viewVector);
强度=功率(c-点(vNormal,vNormal),p);
gl_位置=projectionMatrix*modelViewMatrix*vec4(位置,1.0);
}
颜色均匀;
浮动强度变化;
void main()
{
vec3发光=发光颜色*强度;
gl_FragColor=vec4(辉光,1.0);
}
var-myImage;
var容器、场景、摄影机、渲染器、控件、统计信息;
变量生成器、对象、灯光、视角;
var keyboard=new THREEx.KeyboardState();
var clock=新的三个时钟();
可变屏幕宽度、屏幕高度;
var edgeEffect,edgeEffect2;
var-gui,参数;
初始化场景();
animateScene();
函数setScene(){
//创建场景
场景=新的三个。场景();
}
函数集合容器(渲染器){
container=document.getElementById('Test3D').appendChild(renderer.doElement);
}
函数渲染器(){
if(Detector.webgl)
renderer=new THREE.WebGLRenderer();//{antialas:true});
其他的
renderer=new THREE.CanvasRenderer();
设置大小(屏幕宽度、屏幕高度);
setContainer(渲染器);
}
功能设置摄像头(x、y、z){
//获取内部窗口(内容区域)的大小以创建全尺寸渲染器
屏幕宽度=window.innerWidth,屏幕高度=window.innerHeight;
视角=45,纵横比=屏幕宽度/屏幕高度,近距离=0.1,远距离=20000;
//创建摄影机
摄像机=新的三个透视摄像机(视角、方向、近距离、远距离);
摄像机位置设置(x,y,z);
场景。添加(摄影机);
摄像机。注视(场景。位置);
}
函数setEvents(){
三倍。窗口大小调整(渲染器、相机);
THREEx.FullScreen.bindKey({charCode:'m'.charCodeAt(0)});
}
函数setOrbitControls(){
控件=新的三个.轨道控件(摄影机、渲染器.doElement);
}
函数setStats(){
统计数据=新统计数据();
stats.domElement.style.position='绝对';
stats.domeElement.style.bottom='0px';
stats.domElement.style.zIndex=100;
container.appendChild(stats.domeElement);
}
功能设置楼层(图像){
var floorTexture=new THREE.ImageUtils.loadTexture(图像);
floorTexture.wrapps=floorTexture.wrapT=THREE.RepeatWrapping;
地板结构。重复。设置(1,1);
var floorMaterial=新的三个.MeshBasicMaterial({map:floorTexture,side:THREE.DoubleSide});
var地板测量法=新的三个平面几何(1000,1000,10,10);
var地板=新的三层网格(地板测量、地板材料);
楼层位置y=5;
floor.rotation.x=Math.PI/2;
场景。添加(楼层);
}
功能设置SkyBox_FOG(isFog,彩色){
var skyBoxGeometry=新的三个.BoxGeometry(10000、10000、10000);
var skyBoxMaterial=new THREE.MeshBasicMaterial({color:color,side:THREE.BackSide});
var skyBox=new THREE.Mesh(skyBoxGeometry,skyBoxMaterial);
场景.添加(skyBox);
如果(isFog){
scene.fog=新的三个.fogep2(颜色,0.00025);
}
}
功能设置环境光(颜色){
光=新的三个。环境光(颜色);
场景。添加(灯光);
}
函数initScene(){
setScene()//scene=new THREE.scene();
设置摄像机(500、0600);
渲染器();
setEvents();
setOrbitControls();
setStats()//STATS
setSkyBox_FOG(false,0xB0C4DE);//SKYBOX/FOG
CreateImages();
后处理();
设置环境光(0xEEEE);
initGUI();//GUI
}
函数createMaterial(){
/*
var materialCameraPosition=camera.position.clone();
var material=新的3.ShaderMaterial(
{
制服:{
“c”:{类型:“f”,值:128.0},
“p”:{类型:“f”,值:3},