如何使用Three.js OutlinePass与React?

时间:2018-01-19 16:29:37

标签: javascript node.js reactjs three.js

我正在尝试使用React服务器端呈现来使Post-processing Outline Thee.js example工作。我的主要问题是这些行(47& 280)(来自示例):

<script src="js/postprocessing/OutlinePass.js"></script>

outlinePass = new THREE.OutlinePass( new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera );
                composer.addPass( outlinePass );

因为我不确定如何在React中包含OutlinePass。我安装了包postprocessingnpm profile)但它没有OutlinePass。

我也尝试在ComponentDidMountComponentWillMount中导入脚本,如下所示:

const script = document.createElement("script");
        script.src = require('!!url-loader!../../../assets/webgl/js/OutlinePass.js');
        script.async = true;
        document.body.appendChild(script);

但它显示错误:Uncaught ReferenceError: THREE is not defined

我也尝试过(一次一个):

import OutlinePass from '../../../assets/webgl/js/OutlinePass.js';
const OutlinePass = require('../../../assets/webgl/js/OutlinePass.js');
const OutlinePass = require('../../../assets/webgl/js/OutlinePass.js')(THREE);

这不起作用。

我的jsx(部分):

import * as THREE from 'three';
import * as OBJLoader from 'three-obj-loader';

componentWillMount() {
        const width = window.innerWidth;
        const height = window.innerHeight;

        this.setState({
            windowW: width,
            windowH: height
        });

        // LOAD SCRIPTS
        const script = document.createElement("script");
        script.src = require('!!url-loader!../../../assets/webgl/js/OutlinePass.js');
        script.async = true;
        document.body.appendChild(script);
    }

componentDidMount() {
        const { windowH, windowW } = this.state;

        const { THREE } = this;
        const TrackballControls = require('three-trackballcontrols');

        OBJLoader(THREE);


        // WINDOW RESIZE
        // window.addEventListener( 'resize', onWindowResize, false );


        // POST-PROCESSING
        const outlinePass = new THREE.OutlinePass( new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera );


        // Code for this not included to clear space
        this.camera = camera;
        this.controls = controls;
        this.scene = scene;
        this.renderer = renderer;

        this.mount.appendChild(this.renderer.domElement);
        this.start();
    }

componentWillUnmount() {
        this.stop();
        this.mount.removeChild(this.renderer.domElement);
    }

    start() {
        if (!this.frameId) {
            this.frameId = requestAnimationFrame(this.animate);
        }
    }

    stop() {
        cancelAnimationFrame(this.frameId);
    }

    animate() {
        this.renderScene();
        this.frameId = window.requestAnimationFrame(this.animate);
        this.controls.update();
    }

    renderScene() {
        this.renderer.render(this.scene, this.camera);
    }

2 个答案:

答案 0 :(得分:0)

从我所看到的代码中,您使用的是ES6模块,对于一个重要的模块,模块需要采用正确的格式,换句话说,它需要具有导出默认值....更多信息 这http://exploringjs.com/es6/ch_modules.html#sec_basics-of-es6-modules

您尝试将不符合此格式的模块重要用于您的代码,这就是您遇到问题的原因,您可以使用脚本代码并使用窗口引用代码< / p>

<script src="js/postprocessing/OutlinePass.js"></script>

然后用window.THREE.OutlinePass

引用

答案 1 :(得分:0)

我做到了!问题是我试图在加载脚本之前使用THREE.OutlinePass ,所以,我添加了一个按钮来加载触发loadScene()的场景:

componentWillMount() {
        const width = window.innerWidth;
        const height = window.innerHeight;

        this.setState({
            windowW: width,
            windowH: height
        });

        // LOAD SCRIPTS    
        const scriptOP = document.createElement("script");
        scriptOP.src = require('!!url-loader!../../../assets/webgl/js/OutlinePass.js');
        scriptOP.async = true;
        document.body.appendChild(scriptOP);
    }

componentDidMount() {
        const { windowH, windowW } = this.state;

        const { THREE } = window;
        const TrackballControls = require('three-trackballcontrols');

        OBJLoader(THREE);
        MTLLoader(THREE);

        // CAMERA
        var  camera = new THREE.PerspectiveCamera( 45, windowW / windowH, 1, 10000 );
        camera.position.set( 0, 0, 1 );
        // camera.lookAt(scene.position);
        // camera.up = new THREE.Vector3(0, 0, 1);


        // CONTROLS
        const controls = new TrackballControls( camera );
        controls.rotateSpeed = 1.0;
        controls.zoomSpeed = 1.2;
        controls.panSpeed = 0.8;
        controls.noZoom = false;
        controls.noPan = false;
        controls.staticMoving = true;
        controls.dynamicDampingFactor = 0.3;
        controls.keys = [ 65, 83, 68 ];


        // SCENE
        const scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xcccccc );
        scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );

        // RENDERER
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( windowW, windowH );
        renderer.setClearColor('#000000');

        // POST-PROCESSING
        const composer = null; <- this is important

        this.camera = camera;
        this.controls = controls;
        this.scene = scene;
        this.composer = composer;
        this.renderer = renderer;

        this.mount.appendChild(this.renderer.domElement);
        this.start();
    }

renderScene() {
        this.renderer.autoClear = true;
        this.renderer.setClearColor( 0xfff0f0 );
        this.renderer.setClearAlpha( 0.0 );
        if ( this.composer ) {
            this.composer.render();
        } else {
            this.renderer.render(this.scene, this.camera);
        }
    }

loadScene() {
        const { THREE, innerWidth, innerHeight } = window;

        // POST-PROCESSING
        this.composer = new THREE.EffectComposer( this.renderer );

        const renderPass = new THREE.RenderPass( this.scene, this.camera );
        this.composer.addPass( renderPass );

        const outlinePass = new THREE.OutlinePass( new THREE.Vector2( innerWidth, innerHeight ), this.scene, this.camera);

        // LOAD OBJECT
        const onProgress = xhr => {
            console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
        }

        const onError = error => {
            console.log("Error! ", error);
        }

        const loader = new THREE.OBJLoader();
        loader.load( obj,
            object => {
                this.scene.add(object);
                const tempMat = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x050505 } );
                object.traverse( function( child ) {
                    if ( child instance of THREE.Mesh ) {
                        child.material = tempMat.clone();

                        outlinePass.selectedObjects.push( child );
                    }
                } );
            },
            onProgress,
            onError
        );

        const effectFXAA = new THREE.ShaderPass(THREE.FXAAShader);
        effectFXAA.uniforms['resolution'].value.set(1 / innerWidth, 1 / innerHeight );
        effectFXAA.renderToScreen = true;
        this.composer.addPass( effectFXAA );
    }

我希望这有助于某人!