首页 > 解决方案 > Three.js“THREE.EffectComposer 依赖于 THREE.ShaderPass”问题

问题描述

嗨,我是 three.js 的大新手,我正在尝试使用效果合成器功能,以便我可以使用 UnrealBloomPass.js 在我的对象上实现绽放效果。不幸的是,我遇到了几个与效果器中的 THREE.ShaderPass 相关的错误,由于缺乏经验,我不知道如何解决它们。有人可以帮我吗?

我得到的错误

这是我的代码:

// Canvas Setup
const canvas = document.querySelector("#canv") 
    const width = window.innerWidth;
    const height = window.innerHeight;
const renderer = new THREE.WebGLRenderer({canvas});
renderer.setSize( width, height );
renderer.setClearColor( 0x111, 1);
    const fov = 100;
    const aspect = width/height;
    const near = 0.1;
    const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;  
const scene = new THREE.Scene();

// Geometry Settings
const loader = new THREE.GLTFLoader().setPath("./");
loader.load("assets/model.glb", (gltf) =>{
    root1 = gltf.scene;
    scene.add(root1);
});

loader.load("assets/model2.glb", (gltf) =>{
    root2 = gltf.scene;
    scene.add(root2);
});

// Lighting
const light1 = new THREE.DirectionalLight(0x404040);
const light2 = new THREE.AmbientLight(0x404040);
light1.position.y = 2;
light1.position.z = 2;
light1.intensity = 2;
light1.shadowDarkness = .1
light2.position.y = -2;
light2.position.z = -2;
light2.intensity = 2;
light2.shadowDarkness = .1
scene.add(light1);
scene.add(light2);


// Controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
controls.enablePan = false;
controls.maxDistance = 2;
controls.minDistance = 1.3;
controls.maxPolarAngle = 2.5;
controls.minPolarAngle = .5;
controls.enableDamping = true;
controls.update();

// Effect Composer 
const composer = new THREE.EffectComposer(renderer);
composer.addPass(new THREE.RenderPass(scene, camera));
const bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
    bloomPass.threshold = 0;
    bloomPass.strength = 3;
    bloomPass.radius = 1;
composer.addPass(bloomPass);



// Render
function animate() {
    var delta = clock.getDelta();
    requestAnimationFrame( animate );
    
    root1.rotation.y += 0.002;
    root2.rotation.y += 0.0035;
    controls.update()
    // renderer.render( scene, camera );
    composer.render(delta);
}
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<!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>Document</title>
</head>
<body>
    
    <canvas id="canv"></canvas>

    <script src="build/three.min.js"></script>
    <script src="build/OrbitControls.js"></script>
    <script src="build/GLTFLoader.js"></script>
    <script src="build/EffectComposer.js"></script>
    <script src="build/RenderPass.js"></script>
    <script src="build/UnrealBloomPass.js"></script>
    <script src="exp.js"></script>

</body>
</html>

标签: javascriptthree.jswebgl

解决方案


问题是EffectComposer.js脚本无法访问它需要的正确元素(即THREE.ShaderPass)。

要解决此问题,您只需在 JavaScript/HTML 文件中导入 EffectComposer 脚本所需的文件,以便可以读取所需的缺失元素。以这种方式导入的某些文件可能需要它们自己的导入元素(即ShaderPass.js需要来自 的元素Pass.js),因此请确保以正确的顺序导入它们,以便可以最后读取需要附加元素的 js 文件以及需要导入其他元素的 js 文件可以先阅读脚本。

请参阅下面的更改代码(主要是 HTML 文件):

// Canvas Setup
const canvas = document.querySelector("#canv") 
    const width = window.innerWidth;
    const height = window.innerHeight;
const renderer = new THREE.WebGLRenderer({canvas});
renderer.setSize( width, height );
renderer.setClearColor( 0x0c023d, 1);
    const fov = 12;
    const aspect = width/height;
    const near = 0.1;
    const far = 20;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 10;  
const scene = new THREE.Scene();

// Geometry Settings
const loader = new THREE.GLTFLoader().setPath("./");
loader.load("assets/model.glb", (gltf) =>{
    root1 = gltf.scene;
    root1.name = 'world';
    scene.add(root1);
});

loader.load("assets/model2.glb", (gltf) =>{
    root2 = gltf.scene;
    root2.name = 'clouds';
    scene.add(root2);
});
loader.load("assets/house.glb", (gltf) =>{
    root3 = gltf.scene;
    root3.name = 'house';
    scene.add(root3);
});
loader.load("assets/city.glb", (gltf) =>{
    root4 = gltf.scene;
    root4.name = 'city';
    scene.add(root4);
});

// const geometry = new THREE.BoxGeometry();
// const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// const cube = new THREE.Mesh( geometry, material );
// cube.scale.y = 3;
// scene.add( cube );

// Lighting
const light1 = new THREE.DirectionalLight(0x404040);
const light2 = new THREE.AmbientLight(0x404040);
light1.position.y = 2;
light1.position.z = 2;
light1.intensity = 2;
light1.shadowDarkness = .1
light2.position.y = -2;
light2.position.z = -2;
light2.intensity = 2;
light2.shadowDarkness = .1
scene.add(light1);
scene.add(light2);


// Orbit Controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
controls.enablePan = false;
controls.maxDistance = 12;
controls.minDistance = 1.3;
controls.maxPolarAngle = 2.5;
controls.minPolarAngle = .5;
controls.enableDamping = true;
controls.update();

// Hover Controls
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
let INTERSECTED;

document.addEventListener( 'mousemove', onPointerMove );

function onPointerMove( event ) {
    pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}

function hoverObj() {
    raycaster.setFromCamera( pointer, camera );
    const intersects = raycaster.intersectObjects( scene.children );
    if ( intersects.length > 0 ) {
        if ( INTERSECTED != intersects[ 0 ].object ) {
            if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
            console.log("yo")
            var INTERSECTED = intersects[ 0 ].object;
            
        }else{
            
        }
    }
}
// Effect Composer 
const composer = new THREE.EffectComposer(renderer);
composer.addPass(new THREE.RenderPass(scene, camera));
const bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
    bloomPass.threshold = .5;
    bloomPass.strength = 3;
    bloomPass.radius = 1;
composer.addPass(bloomPass);

// Resize Window Function
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.updateProjectionMatrix();
};

// Animation
function animate() {
    // var delta = clock.getDelta();
    requestAnimationFrame( animate );
    scene.getObjectByName(root1.name).rotation.y += 0.002;
    scene.getObjectByName(root3.name).rotation.y += 0.002;
    scene.getObjectByName(root4.name).rotation.y += 0.002;
    scene.getObjectByName(root2.name).rotation.y += 0.0035;
    controls.update();
    hoverObj();
    objrender();
}
// Render
function objrender(){
    // renderer.render( scene, camera );
    composer.render();
}
animate();
<!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>Document</title>
</head>
<body>
    
    <canvas id="canv"></canvas>
    
    <script src="build/three.min.js"></script>
    <!-- required for ShaderPass -->
    <script src="build/Pass.js"></script>
    <!-- both scripts required for EffectComposer  -->
    <script src="build/ShaderPass.js"></script>
    <script src="build/CopyShader.js"></script>
    <!-- required for UnrealBloomPass -->
    <script src="build/LuminosityHighPassShader.js"></script>
    <!-- the main functions i want to use -->
    <script src="build/OrbitControls.js"></script>
    <script src="build/GLTFLoader.js"></script>
    <script src="build/EffectComposer.js"></script>
    <script src="build/RenderPass.js"></script>
    <script src="build/UnrealBloomPass.js"></script>
    <!-- main three.js script -->
    <script src="exp.js"></script>

</body>
</html>


推荐阅读