|
|
@@ -27,16 +27,13 @@
|
|
|
<script type="module">
|
|
|
|
|
|
import * as THREE from 'three';
|
|
|
- import { color, storage, Fn, instanceIndex, sin, time, float, uniform, attribute, mix, vec3 } from 'three/tsl';
|
|
|
+ import { color, storage, Fn, instancedBufferAttribute, instanceIndex, sin, time, float, uniform, shapeCircle, mix, vec3 } from 'three/tsl';
|
|
|
|
|
|
import Stats from 'three/addons/libs/stats.module.js';
|
|
|
|
|
|
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
|
|
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
|
|
|
|
- import InstancedPoints from 'three/addons/objects/InstancedPoints.js';
|
|
|
- import InstancedPointsGeometry from 'three/addons/geometries/InstancedPointsGeometry.js';
|
|
|
-
|
|
|
import * as GeometryUtils from 'three/addons/utils/GeometryUtils.js';
|
|
|
|
|
|
let renderer, scene, camera, camera2, controls, backgroundNode;
|
|
|
@@ -54,13 +51,7 @@
|
|
|
|
|
|
init();
|
|
|
|
|
|
- function init() {
|
|
|
-
|
|
|
- renderer = new THREE.WebGPURenderer( { antialias: true } );
|
|
|
- renderer.setPixelRatio( window.devicePixelRatio );
|
|
|
- renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
- renderer.setAnimationLoop( animate );
|
|
|
- document.body.appendChild( renderer.domElement );
|
|
|
+ async function init() {
|
|
|
|
|
|
scene = new THREE.Scene();
|
|
|
|
|
|
@@ -70,19 +61,14 @@
|
|
|
camera2 = new THREE.PerspectiveCamera( 40, 1, 1, 1000 );
|
|
|
camera2.position.copy( camera.position );
|
|
|
|
|
|
- controls = new OrbitControls( camera, renderer.domElement );
|
|
|
- controls.enableDamping = true;
|
|
|
- controls.minDistance = 10;
|
|
|
- controls.maxDistance = 500;
|
|
|
-
|
|
|
backgroundNode = color( 0x222222 );
|
|
|
|
|
|
effectController = {
|
|
|
|
|
|
pulseSpeed: uniform( 6 ),
|
|
|
minWidth: uniform( 6 ),
|
|
|
- maxWidth: uniform( 12 ),
|
|
|
- alphaToCoverage: true,
|
|
|
+ maxWidth: uniform( 20 ),
|
|
|
+ alphaToCoverage: true
|
|
|
|
|
|
};
|
|
|
|
|
|
@@ -115,12 +101,10 @@
|
|
|
|
|
|
// Instanced Points
|
|
|
|
|
|
- const geometry = new InstancedPointsGeometry();
|
|
|
- geometry.setPositions( positions );
|
|
|
- geometry.setColors( colors );
|
|
|
+ const positionAttribute = new THREE.InstancedBufferAttribute( new Float32Array( positions ), 3 );
|
|
|
+ const colorsAttribute = new THREE.InstancedBufferAttribute( new Float32Array( colors ), 3 );
|
|
|
|
|
|
const instanceSizeBufferAttribute = new THREE.StorageInstancedBufferAttribute( sizes, 1 );
|
|
|
- geometry.setAttribute( 'instanceSize', instanceSizeBufferAttribute );
|
|
|
const instanceSizeStorage = storage( instanceSizeBufferAttribute, 'float', instanceSizeBufferAttribute.count );
|
|
|
|
|
|
computeSize = Fn( () => {
|
|
|
@@ -135,29 +119,48 @@
|
|
|
|
|
|
} )().compute( divisions );
|
|
|
|
|
|
- geometry.instanceCount = positions.length / 3; // this should not be necessary
|
|
|
+ // Material / Sprites
|
|
|
+
|
|
|
+ const attributeRange = instancedBufferAttribute( instanceSizeBufferAttribute );
|
|
|
+ const pointColors = mix( vec3( 0.0 ), instancedBufferAttribute( colorsAttribute ), attributeRange.div( float( effectController.maxWidth ) ) );
|
|
|
|
|
|
- material = new THREE.InstancedPointsNodeMaterial( {
|
|
|
+ material = new THREE.PointsNodeMaterial( {
|
|
|
|
|
|
- color: 0xffffff,
|
|
|
- pointWidth: 10, // in pixel units
|
|
|
+ colorNode: pointColors,
|
|
|
+ opacityNode: shapeCircle(),
|
|
|
+ positionNode: instancedBufferAttribute( positionAttribute ),
|
|
|
+ // rotationNode: time,
|
|
|
+ sizeNode: instancedBufferAttribute( instanceSizeBufferAttribute ),
|
|
|
+ // size: 40, // in pixels units
|
|
|
vertexColors: true,
|
|
|
- alphaToCoverage: true,
|
|
|
+ sizeAttenuation: false,
|
|
|
+ alphaToCoverage: true
|
|
|
|
|
|
} );
|
|
|
|
|
|
- const attributeRange = attribute( 'instanceSize' ).sub( 1 );
|
|
|
+ const instancedPoints = new THREE.Sprite( material );
|
|
|
+ instancedPoints.count = divisions;
|
|
|
+ scene.add( instancedPoints );
|
|
|
|
|
|
- material.pointWidthNode = attribute( 'instanceSize' );
|
|
|
- material.pointColorNode = mix( vec3( 0.0 ), attribute( 'instanceColor' ), attributeRange.div( float( effectController.maxWidth.sub( 1 ) ) ) );
|
|
|
+ // Renderer / Controls
|
|
|
|
|
|
- const instancedPoints = new InstancedPoints( geometry, material );
|
|
|
- instancedPoints.scale.set( 1, 1, 1 );
|
|
|
- scene.add( instancedPoints );
|
|
|
+ renderer = new THREE.WebGPURenderer( { antialias: true } );
|
|
|
+ renderer.setPixelRatio( window.devicePixelRatio );
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
+ renderer.setAnimationLoop( animate );
|
|
|
+ //renderer.logarithmicDepthBuffer = true;
|
|
|
+ document.body.appendChild( renderer.domElement );
|
|
|
+
|
|
|
+ controls = new OrbitControls( camera, renderer.domElement );
|
|
|
+ controls.enableDamping = true;
|
|
|
+ controls.minDistance = 10;
|
|
|
+ controls.maxDistance = 500;
|
|
|
|
|
|
window.addEventListener( 'resize', onWindowResize );
|
|
|
onWindowResize();
|
|
|
|
|
|
+ // GUI
|
|
|
+
|
|
|
stats = new Stats();
|
|
|
document.body.appendChild( stats.dom );
|
|
|
|
|
|
@@ -169,8 +172,8 @@
|
|
|
|
|
|
} );
|
|
|
|
|
|
- gui.add( effectController.minWidth, 'value', 1, 20, 1 ).name( 'minWidth' );
|
|
|
- gui.add( effectController.maxWidth, 'value', 2, 20, 1 ).name( 'maxWidth' );
|
|
|
+ gui.add( effectController.minWidth, 'value', 1, 30, 1 ).name( 'minWidth' );
|
|
|
+ gui.add( effectController.maxWidth, 'value', 2, 30, 1 ).name( 'maxWidth' );
|
|
|
gui.add( effectController.pulseSpeed, 'value', 1, 20, 0.1 ).name( 'pulseSpeed' );
|
|
|
|
|
|
}
|
|
|
@@ -195,6 +198,7 @@
|
|
|
stats.update();
|
|
|
|
|
|
// compute
|
|
|
+
|
|
|
renderer.compute( computeSize );
|
|
|
|
|
|
// main scene
|