粒子跟随纹理

Particles follow texture

我有一个用 three.js 中的粒子创建的球体,效果很好。现在我想将这些粒子放在我拥有的模拟 3D 星球的世界地图的纹理之上,我在互联网上进行了搜索,但是当我放置纹理而不是在外面它最终进入每个粒子内部,我该怎么做?任何的想法 ?谢谢大家

这是我的代码

$( document ).ready(function() {

var globe = document.getElementById('globe')    
var Maxwidth = window.innerWidth
var Maxheight = window.innerHeight


var scene = new THREE.Scene();

var renderer = new THREE.WebGLRenderer({antilias:true});

renderer.setPixelRatio( window.devicePixelRatio );

renderer.setSize(Maxwidth,Maxheight)

globe.appendChild(renderer.domElement)


var camera = new THREE.PerspectiveCamera(60, Maxwidth / Maxheight,1,1000);

camera.position.z = 50;

var controls = new THREE.OrbitControls( camera, renderer.domElement );

controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled

controls.dampingFactor = 0.25;

controls.panningMode = THREE.HorizontalPanning; // default is 
THREE.ScreenSpacePanning


controls.maxPolarAngle = Math.PI / 2;

var geometry = new THREE.SphereGeometry( 200, 42, 42 );

geometry.widthSegments = 42;

var colors = [];

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

    // random color
    colors[i] = new THREE.Color();


    //colors[i].setHSV( Math.random(), 1.0, 1.0 );

}
geometry.colors = colors;

// texture
var texture = new THREE.Texture( generateTexture( ) );
texture.needsUpdate = true; // important

// particle system material
var material = new THREE.ParticleBasicMaterial( {
    size: 5,
    map: texture,
    blending: THREE.AdditiveBlending, // required
    depthTest: false, // required
    transparent: true,
    opacity: 0.7,
    vertexColors: true // optional
} );

material.map = THREE.ImageUtils.loadTexture('../img/point_picker.png')

material.anisotropy = 0;
material.magFilter = THREE.NearestFilter;
material.minFilter = THREE.NearestFilter;

var union = new THREE.ParticleSystem( geometry, material );

function generateTexture( ) {

var size = 128;

var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;

var context = canvas.getContext( '2d' );

var centerX = size / 2;
var centerY = size / 2;
var radius = size / 2;

context.beginPath();
context.arc( centerX, centerY, radius, 0, 2 * Math.PI, false );
context.fillStyle = "#FFFFFF";
context.fill();

return canvas;

}

scene.add(union)

renderer.setClearColor(0x2675AD)

renderer.render(scene,camera)

controls.update();

function render(delta){


 requestAnimationFrame(render);
 renderer.render(scene,camera)

 union.rotation.y  += 0.0009


 }

 render()



 });

我需要这样的东西

所以,这就是我在评论中谈到的选项:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(1.25, 7, 7);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setClearColor(0x080808);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var geom = new THREE.SphereBufferGeometry(5, 120, 60);
var colors = [];
var color = new THREE.Color();
var q = 0xffffff * 0.25;
for (let i = 0; i < geom.attributes.position.count; i++) {
  color.set(Math.random() * q + q * 3);
  color.toArray(colors, i * 3);
}
geom.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));

var loader = new THREE.TextureLoader();
loader.setCrossOrigin('');
var texture = loader.load('https://learningthreejs.com/data/2013-09-16-how-to-make-the-earth-in-webgl/demo/bower_components/threex.planets/images/earthspec1k.jpg');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1, 1);
var disk = loader.load('https://threejs.org/examples/textures/sprites/circle.png');

var points = new THREE.Points(geom, new THREE.ShaderMaterial({
  vertexColors: THREE.VertexColors,
  uniforms: {
    visibility: {
      value: texture
    },
    shift: {
      value: 0
    },
    shape: {
      value: disk
    },
    size: {
      value: 0.125
    },
    scale: {
      value: window.innerHeight / 2
    }
  },
  vertexShader: `
                
      uniform float scale;
      uniform float size;
      
      varying vec2 vUv;
      varying vec3 vColor;
      
      void main() {
      
        vUv = uv;
        vColor = color;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_PointSize = size * ( scale / length( mvPosition.xyz ) );
        gl_Position = projectionMatrix * mvPosition;

      }
  `,
  fragmentShader: `
      uniform sampler2D visibility;
      uniform float shift;
      uniform sampler2D shape;
      
      varying vec2 vUv;
      varying vec3 vColor;
      

      void main() {
        
        vec2 uv = vUv;
        uv.x += shift;
        vec4 v = texture2D(visibility, uv);
        if (length(v.rgb) > 1.0) discard;

        gl_FragColor = vec4( vColor, 1.0 );
        vec4 shapeData = texture2D( shape, gl_PointCoord );
        if (shapeData.a < 0.5) discard;
        gl_FragColor = gl_FragColor * shapeData;
        
      }
  `,
  transparent: true
}));
scene.add(points);

var blackGlobe = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({
  color: 0x000000
}));
blackGlobe.scale.setScalar(0.99);
points.add(blackGlobe);

var clock = new THREE.Clock();
var time = 0;

render();

function render() {
  requestAnimationFrame(render);
  time += clock.getDelta();
  points.material.uniforms.shift.value = time * 0.1;
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.91.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.91.0/examples/js/controls/OrbitControls.js"></script>