Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 208 additions & 0 deletions examples/webgpu_sprites_debug.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
<html lang="en">
<head>
<title>three.js webgpu - 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="example.css">
</head>
<body>

<div id="info">
<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>

<div class="title-wrapper">
<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Sprites</span>
</div>

<small>
Example of using a custom SpriteMaterial with nodes.
</small>
</div>

<script type="importmap">
{
"imports": {
"three": "../src/three.webgpu.js",
"three/webgpu": "../src/three.webgpu.js",
"three/tsl": "../src/three.tsl.js",
"three/addons/": "./jsm/"
}
}
</script>

<script type="module">

import * as THREE from 'three/webgpu';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { texture, uv, userData, fog, rangeFogFactor, color, context } from 'three/tsl';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import context.
import { Inspector } from 'three/addons/inspector/Inspector.js';

let camera, scene, renderer;

let map;

let group;

let imageWidth = 1, imageHeight = 1;

init();

function init() {

const width = window.innerWidth;
const height = window.innerHeight;

camera = new THREE.PerspectiveCamera( 60, width / height, 1, 2100 );
camera.position.z = 1500;

scene = new THREE.Scene();
scene.fogNode = fog( color( 0x0000ff ), rangeFogFactor( 1500, 2100 ) );

// create sprites

const amount = 10000;
const radius = 500;

const textureLoader = new THREE.TextureLoader();

map = textureLoader.load( 'textures/sprite1.png', ( map ) => {

imageWidth = map.image.width;
imageHeight = map.image.height;

} );

group = new THREE.Group();

const textureNode = texture( map );

const material = new THREE.SpriteNodeMaterial();
material.colorNode = textureNode.mul( uv() ).mul( 2 ).saturate();
material.opacityNode = textureNode.a;
material.rotationNode = userData( 'rotation', 'float' ); // get value of: sprite.userData.rotation

for ( let a = 0; a < amount; a ++ ) {

const x = Math.random() - 0.5;
const y = Math.random() - 0.5;
const z = Math.random() - 0.5;

const sprite = new THREE.Sprite( material );

sprite.position.set( x, y, z );
sprite.position.normalize();
sprite.position.multiplyScalar( radius );

//sprite.scale.set( imageWidth * 100, imageHeight * 100, 1.0 );
const rand = Math.random() * 100;
sprite.scale.set( rand, rand, 1.0 );

// individual rotation per sprite
sprite.userData.rotation = 0;

group.add( sprite );

}

scene.add( group );

setTimeout( () => {

const list = [];

for ( let a = 0; a < 100; a ++ ) {

const x = Math.random() - 0.5;
const y = Math.random() - 0.5;
const z = Math.random() - 0.5;

const sprite = new THREE.Sprite( material );

sprite.position.set( x, y, z );
sprite.position.normalize();
sprite.position.multiplyScalar( radius );

const rand = Math.random() * 100;
sprite.scale.set( rand, rand, 1.0 );

// individual rotation per sprite
sprite.userData.rotation = 0;

group.add( sprite );

//

list.push( sprite );

}

setTimeout( () => {

for ( let i = 0; i < list.length; i ++ ) {

const sprite = list[ i ];
sprite.material.dispose();

group.remove( sprite );

}

}, 1000 );

}, 1000 );

//

renderer = new THREE.WebGPURenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( render );
renderer.inspector = new Inspector();
/*renderer.contextNode = context( {
modelWorldMatrix: instancedModelWorldMatrix
} );*/
document.body.appendChild( renderer.domElement );

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

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable controls.

window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );

}

function render() {

const time = Date.now() / 1000;

for ( let i = 0, l = group.children.length; i < l; i ++ ) {

const sprite = group.children[ i ];
const scale = Math.sin( time + sprite.position.x * 0.01 ) * 0.3 + 1.0;

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable scale.

//sprite.userData.rotation += 0.1 * ( i / l );
//sprite.scale.set( scale * imageWidth, scale * imageHeight, 1.0 );

}

group.rotation.x = time * 0.5;
group.rotation.y = time * 0.75;
group.rotation.z = time * 1.0;

renderer.render( scene, camera );

}

</script>
</body>
</html>
Loading
Loading