三.js中消失的线对象

Disappearing line object in Three.js

本文关键字:对象 消失 js      更新时间:2023-09-26



我有一个奇怪的问题,可能是三.js的错误,但也可能是我的曲线手。

我有一个场景,其中包含一些网格(在下面的示例中,我使用了几个透明的立方体和小球体(和一个基于缓冲区几何体的线对象(可以是线段或线段 - 没关系(。当我旋转相机线时,对象有时会从视图中消失,就像它被另一个对象覆盖一样。如果我看不到线的起点(如果将相机旋转到起点在屏幕外的程度,即使没有额外的网格(,而 90% 的线对象应该在视图中,它似乎也会消失。

问题是:为什么这条线会消失,我应该如何防止它的行为?

这是它在截屏视频中的样子:

http://screencast.com/t/HLC99OMmDdK

这是问题的一个例子:

http://jsfiddle.net/exiara/sa4bxhc3/您应该能够看到相机旋转时线条如何消失。

jsfiddle的代码示例:

        var camera, controls, scene, renderer, dummy, projector,
            stats, fps = 30, fpsTimeout = 1000 / fps,
            linesGeometry,globalLine;
        init();
        animate();
        function init() {
            renderer = new THREE.WebGLRenderer({antialias: true});
            renderer.setClearColor(0xFFFFeF, 1);
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );
            scene = new THREE.Scene();
            scene.fog = new THREE.Fog( 0xFFFFeF, 100, 2500 );
            camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 50000 );
            camera.position.set(-450, 300, 650);
            camera.target = new THREE.Vector3(0,0,0);
            controls = new THREE.OrbitControls( camera );
            controls.addEventListener('change', render );
            // ------------ MAIN PART START ------------ //
            var lines = 1000;
            linesGeometry = new THREE.BufferGeometry();
            var positions = new Float32Array( lines * 6 );
            for ( var i = 0, j, ll = lines; i < ll; i++ ) {
                j=i*6;
                positions[j]   = Math.random()*100;
                positions[j+1] = Math.random()*100;
                positions[j+2] = Math.random()*100;
                positions[j+3] = Math.random()*100;
                positions[j+4] = Math.random()*100;
                positions[j+5] = Math.random()*100;
            }
            linesGeometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
            globalLine = new THREE.Line( linesGeometry, new THREE.LineBasicMaterial({
                color: 0x000000,
                transparent: true,
                opacity: 0.8
            } ));
            scene.add( globalLine );
            // ------------ MAIN PART END ------------ //
            // add cubes
            var step = 400;
            var gridSize = 4;
            var offset = step*gridSize/2;
            var cubeGeometry = new THREE.BoxGeometry(step, step, step);
            var cubeMaterial = new THREE.MeshBasicMaterial({ color:0xFF0000, ambient: 0xCCCCCC, transparent: true, opacity: 0 });
            var testCube, edge;
            for (var x = -offset; x <= offset; x+=step) {
                for (var y = -offset; y <= offset; y+=step) {
                    for (var z = -offset; z <= offset; z+=step) {
                        testCube = new THREE.Mesh(cubeGeometry,cubeMaterial);
                        testCube.position.set(x, y, z);
                        edge = new THREE.EdgesHelper( testCube, 0x000000 );
                        scene.add(testCube);
                        scene.add(edge);
                    }
                }
            }
            // spheres
            var sphereGeometry = new THREE.SphereGeometry( 10,32,16),
                sphere;
            var spheres = [
                [0xff0000, 0,    0,    0   ], // red
                [0x0000ff, 200,  0,    0   ], // blue
                [0x00FF00, -200, 0,    0   ], // green
                [0xFF00ff, 0,    200,  0   ], // magenta
                [0x00ffff, 0,    -200, 0   ], // aqua
                [0xFFff00, 0,    0,    200 ], // lime
                [0x000000, 0,    0,    -200]  // black
            ];
            for (var i = 0, sl = spheres.length; i <sl; i++) {
                sphere = new THREE.Mesh(sphereGeometry, new THREE.MeshBasicMaterial({color: spheres[i][0]}));
                sphere.position.set(spheres[i][1], spheres[i][2], spheres[i][3]);
                scene.add(sphere);
            }
            /* Stats */
            stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.top = '0px';
            document.body.appendChild( stats.domElement );
            /* window observers */
            window.addEventListener( 'resize', onWindowResize, false );
            window.addEventListener( 'load', render, false );
        }
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize( window.innerWidth, window.innerHeight );
        }
        function degInRad(deg) {
            return deg * Math.PI / 180;
        }
        function animate()
        {
            setTimeout(function() {
                requestAnimationFrame(animate);
            }, fpsTimeout );
            render();
        }
        function render() {
            camera.lookAt(camera.target);
            renderer.render( scene, camera );
            stats.update();
        }

问题是你正在绘制多个级别的不透明度,webgl需要对它们进行排序。因此,简短的回答是将depthTest: false添加到立方体材料中。

var cubeMaterial = new THREE.MeshBasicMaterial({ color:0xFF0000, ambient: 0xCCCCCC, transparent: true, opacity: 0, depthTest: false });

但我想提一下,你正在做的事情是低效的。您不应该以这种方式绘制网格。请改用线条。