在Three.js THREE.Points对象中逐个索引隐藏

问题描述

我遇到了一个包含许多点的对象的问题(使用THREE.Points创建)。一个示例为https://threejs.org/examples/?q=points#webgl_interactive_points。现在,如果要单击某个特定点,我将尝试隐藏它。使用“相交-method I'm able to enlarge these or change their color: using particles.geometry.attributes.size.array [INDEX] and setting。needsUpdate`。但是,我完全看不见。目的是通过“缓冲区几何”中的索引隐藏点。您可以在下面找到该示例的代码段。

var vertices = new THREE.BoxGeometry( 200,200,16,16 ).vertices;

var positions = new Float32Array( vertices.length * 3 );
var colors = new Float32Array( vertices.length * 3 );
var sizes = new Float32Array( vertices.length );

var vertex;
var color = new THREE.Color();

for ( var i = 0,l = vertices.length; i < l; i ++ ) {

    vertex = vertices[ i ];
    vertex.toArray( positions,i * 3 );

    color.setHSL( 0.01 + 0.1 * ( i / l ),1.0,0.5 );
    color.toArray( colors,i * 3 );

    sizes[ i ] = PARTICLE_SIZE * 0.5;

}

var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position',new THREE.BufferAttribute( positions,3 ) );
geometry.setAttribute( 'customColor',new THREE.BufferAttribute( colors,3 ) );
geometry.setAttribute( 'size',new THREE.BufferAttribute( sizes,1 ) );

//

var material = new THREE.ShaderMaterial( {

    uniforms: {
        color: { value: new THREE.Color( 0xffffff ) },pointTexture: { value: new THREE.TextureLoader().load( "textures/sprites/disc.png" ) }
    },vertexShader: document.getElementById( 'vertexshader' ).textContent,fragmentShader: document.getElementById( 'fragmentshader' ).textContent,alphaTest: 0.9

} );

//

particles = new THREE.Points( geometry,material );
scene.add( particles );

更改悬停时的“大小”的操作如下:

// function render() {

particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;

var geometry = particles.geometry;
var attributes = geometry.attributes;

raycaster.setFromCamera( mouse,camera );

intersects = raycaster.intersectObject( particles );

if ( intersects.length > 0 ) {

    if ( INTERSECTED != intersects[ 0 ].index ) {

        attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE;

        INTERSECTED = intersects[ 0 ].index;

        attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE * 1.25;
        attributes.size.needsUpdate = true;

    }

我已经看过着色器(以我的观点认为这太复杂了,无法完成此任务),并尝试创建透明材质。有什么被忽略吗?

非常感谢。

解决方法

作为一种选择,使用附加的缓冲区属性来提高可见性并在着色器中对其进行处理,可以达到以下目的:

body {
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from "https://threejs.org/build/three.module.js";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60,innerWidth / innerHeight,1,100);
camera.position.set(0,10);
let renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x444444);
renderer.setSize(innerWidth,innerHeight);

document.body.appendChild(renderer.domElement);

let g = new THREE.PlaneBufferGeometry(10,10,10);
g.index = null;
let pos = g.getAttribute("position");
let colors = [];
let color = new THREE.Color();
let sizes = [];
let visibility = [];
for(let i = 0; i < pos.count; i++){
  color.set( Math.random() * 0x888888 + 0x888888);
  colors.push(color.r,color.g,color.b);
  sizes.push( Math.random() * 0.5 + 0.5);
  visibility.push(1);
}
g.setAttribute("color",new THREE.Float32BufferAttribute(colors,3));
g.setAttribute("sizes",new THREE.Float32BufferAttribute(sizes,1));
g.setAttribute("visibility",new THREE.Float32BufferAttribute(visibility,1));

let m = new THREE.PointsMaterial({
  vertexColors: true,onBeforeCompile: function(shader){
    shader.vertexShader = `
      attribute float sizes;
      attribute float visibility;
      varying float vVisible;
    ${shader.vertexShader}`
    .replace(
      `gl_PointSize = size;`,`gl_PointSize = size * sizes;
        vVisible = visibility;
      `
    );
    shader.fragmentShader = `
      varying float vVisible;
    ${shader.fragmentShader}`
    .replace(
      `#include <clipping_planes_fragment>`,`
        if (vVisible < 0.5) discard;
      #include <clipping_planes_fragment>`
    )
  }
});

let p = new THREE.Points(g,m);
scene.add(p);

let oldIndex = 0;
setInterval(function(){
  let newIndex = THREE.Math.randInt(0,pos.count - 1);
  g.attributes.visibility.setX(oldIndex,1);
  g.attributes.visibility.setX(newIndex,0);
  oldIndex = newIndex;
  g.attributes.visibility.needsUpdate = true;
},500);

renderer.setAnimationLoop(animate);
function animate(){
  renderer.render(scene,camera);
}

</script>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...