You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
earthquake_3d_viewer_front/three/examples/webgpu_instance_sprites.html

172 lines
4.0 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgpu - instance sprites</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - instance sprites
</div>
<script type="importmap">
{
"imports": {
"three": "../build/three.webgpu.js",
"three/webgpu": "../build/three.webgpu.js",
"three/tsl": "../build/three.tsl.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { uniform, time, instanceIndex, instancedBufferAttribute } from 'three/tsl';
let camera, scene, renderer, stats, material;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
init();
function init() {
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 2, 2000 );
camera.position.z = 1000;
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0x000000, 0.001 );
// positions
const count = 10000;
const positions = [];
for ( let i = 0; i < count; i ++ ) {
positions.push( 2000 * Math.random() - 1000, 2000 * Math.random() - 1000, 2000 * Math.random() - 1000 );
}
const positionAttribute = new THREE.InstancedBufferAttribute( new Float32Array( positions ), 3 );
// texture
const map = new THREE.TextureLoader().load( 'textures/sprites/snowflake1.png' );
map.colorSpace = THREE.SRGBColorSpace;
// material
material = new THREE.SpriteNodeMaterial( { sizeAttenuation: true, map, alphaMap: map, alphaTest: 0.1 } );
material.color.setHSL( 1.0, 0.3, 0.7, THREE.SRGBColorSpace );
material.positionNode = instancedBufferAttribute( positionAttribute );
material.rotationNode = time.add( instanceIndex ).sin();
material.scaleNode = uniform( 15 );
// sprites
const particles = new THREE.Sprite( material );
particles.count = count;
scene.add( particles );
//
renderer = new THREE.WebGPURenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );
//
stats = new Stats();
document.body.appendChild( stats.dom );
//
const gui = new GUI();
gui.add( material, 'sizeAttenuation' ).onChange( function () {
material.needsUpdate = true;
material.scaleNode.value = material.sizeAttenuation ? 15 : 0.03;
} );
gui.open();
//
document.body.style.touchAction = 'none';
document.body.addEventListener( 'pointermove', onPointerMove );
//
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onPointerMove( event ) {
if ( event.isPrimary === false ) return;
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
//
function animate() {
render();
stats.update();
}
function render() {
const time = Date.now() * 0.00005;
camera.position.x += ( mouseX - camera.position.x ) * 0.05;
camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
camera.lookAt( scene.position );
const h = ( 360 * ( 1.0 + time ) % 360 ) / 360;
material.color.setHSL( h, 0.5, 0.5 );
renderer.render( scene, camera );
}
</script>
</body>
</html>