--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>three.js webgl - buffer geometry custom attributes - particles</title>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+ <style>
+ body {
+ color: #ffffff;
+ background-color: #000000;
+ margin: 0px;
+ overflow: hidden;
+ }
+ #info {
+ position: absolute;
+ top: 0px;
+ width: 100%;
+ padding: 5px;
+ font-family: Monospace;
+ font-size: 13px;
+ text-align: center;
+ font-weight: bold;
+ }
+ a {
+ color: #fff;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div id="container"></div>
+ <div id="info"><a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - buffergeometry custom attributes - particles</div>
+
+ <script src="../build/three.js"></script>
+
+ <script src="js/Detector.js"></script>
+ <script src="js/libs/stats.min.js"></script>
+
+ <script type="x-shader/x-vertex" id="vertexshader">
+
+ attribute float size;
+ attribute vec3 customColor;
+
+ varying vec3 vColor;
+
+ void main() {
+
+ vColor = customColor;
+
+ vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
+
+ gl_PointSize = size * ( 300.0 / -mvPosition.z );
+
+ gl_Position = projectionMatrix * mvPosition;
+
+ }
+
+ </script>
+
+ <script type="x-shader/x-fragment" id="fragmentshader">
+
+ uniform vec3 color;
+ uniform sampler2D texture;
+
+ varying vec3 vColor;
+
+ void main() {
+
+ gl_FragColor = vec4( color * vColor, 1.0 );
+
+ gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
+
+ }
+
+ </script>
+
+
+ <script>
+
+ if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+ var renderer, scene, camera, stats;
+
+ var particleSystem, uniforms, geometry;
+
+ var particles = 100000;
+
+ var WIDTH = window.innerWidth;
+ var HEIGHT = window.innerHeight;
+
+ init();
+ animate();
+
+ function init() {
+
+ camera = new THREE.PerspectiveCamera( 40, WIDTH / HEIGHT, 1, 10000 );
+ camera.position.z = 300;
+
+ scene = new THREE.Scene();
+
+ uniforms = {
+
+ color: { value: new THREE.Color( 0xffffff ) },
+ texture: { value: new THREE.TextureLoader().load( "textures/sprites/spark1.png" ) }
+
+ };
+
+ var shaderMaterial = new THREE.ShaderMaterial( {
+
+ uniforms: uniforms,
+ vertexShader: document.getElementById( 'vertexshader' ).textContent,
+ fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
+
+ blending: THREE.AdditiveBlending,
+ depthTest: false,
+ transparent: true
+
+ });
+
+
+ var radius = 200;
+
+ geometry = new THREE.BufferGeometry();
+
+ var positions = new Float32Array( particles * 3 );
+ var colors = new Float32Array( particles * 3 );
+ var sizes = new Float32Array( particles );
+
+ var color = new THREE.Color();
+
+ for ( var i = 0, i3 = 0; i < particles; i ++, i3 += 3 ) {
+
+ positions[ i3 + 0 ] = ( Math.random() * 2 - 1 ) * radius;
+ positions[ i3 + 1 ] = ( Math.random() * 2 - 1 ) * radius;
+ positions[ i3 + 2 ] = ( Math.random() * 2 - 1 ) * radius;
+
+ color.setHSL( i / particles, 1.0, 0.5 );
+
+ colors[ i3 + 0 ] = color.r;
+ colors[ i3 + 1 ] = color.g;
+ colors[ i3 + 2 ] = color.b;
+
+ sizes[ i ] = 20;
+
+ }
+
+ geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+ geometry.addAttribute( 'customColor', new THREE.BufferAttribute( colors, 3 ) );
+ geometry.addAttribute( 'size', new THREE.BufferAttribute( sizes, 1 ) );
+
+ particleSystem = new THREE.Points( geometry, shaderMaterial );
+
+ scene.add( particleSystem );
+
+ renderer = new THREE.WebGLRenderer();
+ renderer.setPixelRatio( window.devicePixelRatio );
+ renderer.setSize( WIDTH, HEIGHT );
+
+ var container = document.getElementById( 'container' );
+ container.appendChild( renderer.domElement );
+
+ stats = new Stats();
+ container.appendChild( stats.dom );
+
+ //
+
+ window.addEventListener( 'resize', onWindowResize, false );
+
+ }
+
+ function onWindowResize() {
+
+ camera.aspect = window.innerWidth / window.innerHeight;
+ camera.updateProjectionMatrix();
+
+ renderer.setSize( window.innerWidth, window.innerHeight );
+
+ }
+
+ function animate() {
+
+ requestAnimationFrame( animate );
+
+ render();
+ stats.update();
+
+ }
+
+ function render() {
+
+ var time = Date.now() * 0.005;
+
+ particleSystem.rotation.z = 0.01 * time;
+
+ var sizes = geometry.attributes.size.array;
+
+ for ( var i = 0; i < particles; i++ ) {
+
+ sizes[ i ] = 10 * ( 1 + Math.sin( 0.1 * i + time ) );
+
+ }
+
+ geometry.attributes.size.needsUpdate = true;
+
+ renderer.render( scene, camera );
+
+ }
+
+ </script>
+
+</body>
+</html>