未验证 提交 14dcd30c 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #18033 from donmccurdy/examples-buffergeometry-instancedmesh

Examples: Update or remove some InstancedBufferGeometry examples
......@@ -278,10 +278,8 @@ var files = {
"webgl_buffergeometry_drawrange",
"webgl_buffergeometry_indexed",
"webgl_buffergeometry_instancing",
"webgl_buffergeometry_instancing2",
"webgl_buffergeometry_instancing_billboards",
"webgl_buffergeometry_instancing_dynamic",
"webgl_buffergeometry_instancing_interleaved_dynamic",
"webgl_buffergeometry_instancing_interleaved",
"webgl_buffergeometry_instancing_lambert",
"webgl_buffergeometry_lines",
"webgl_buffergeometry_lines_indexed",
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - instancing test (meshes)</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">
<style>
a {
color: #08f;
}
#notSupported {
width: 50%;
margin: auto;
background-color: #f00;
margin-top: 20px;
padding: 10px;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - instancing test (meshes)
<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div>
</div>
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
attribute vec3 instancePosition;
attribute vec4 instanceQuaternion;
attribute vec3 instanceScale;
varying vec3 vColor;
vec3 applyTRS( vec3 position, vec3 translation, vec4 quaternion, vec3 scale ) {
position *= scale;
position += 2.0 * cross( quaternion.xyz, cross( quaternion.xyz, position ) + quaternion.w * position );
return position + translation;
}
void main(){
vColor = color;
vec3 transformed = applyTRS( position.xyz, instancePosition, instanceQuaternion, instanceScale );
gl_Position = projectionMatrix * modelViewMatrix * vec4( transformed, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
varying vec3 vColor;
void main() {
gl_FragColor = vec4( vColor, 1.0 );
}
</script>
<script type="module">
import * as THREE from '../build/three.module.js';
import Stats from './jsm/libs/stats.module.js';
import { TrackballControls } from './jsm/controls/TrackballControls.js';
var container, stats;
var camera, scene, renderer;
var controls;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 100 );
camera.position.z = 4;
scene = new THREE.Scene();
//
var geometry = new THREE.IcosahedronBufferGeometry( 0.1, 1 );
var colors = [];
for ( var i = 0, l = geometry.attributes.position.count; i < l; i ++ ) {
colors.push( Math.random(), Math.random(), Math.random() );
}
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, vertexColors: THREE.VertexColors } );
//
var instances = 100;
var instancePositions = [];
var instanceQuaternions = [];
var instanceScales = [];
// we create for each mesh a counterpart in our instanced geometry data
for ( var i = 0; i < instances; i ++ ) {
// the red meshes are drawn with separate draw calls
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var position = mesh.position;
var quaternion = mesh.quaternion;
var scale = mesh.scale;
position.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
quaternion.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
quaternion.normalize();
scale.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
// instanced attribute data
instancePositions.push( position.x, position.y, position.z );
instanceQuaternions.push( quaternion.x, quaternion.y, quaternion.z, quaternion.w );
instanceScales.push( scale.x, scale.y, scale.z );
}
var instancedGeometry = new THREE.InstancedBufferGeometry();
instancedGeometry.attributes.position = geometry.attributes.position;
instancedGeometry.attributes.color = geometry.attributes.color;
instancedGeometry.setAttribute( 'instancePosition', new THREE.InstancedBufferAttribute( new Float32Array( instancePositions ), 3 ) );
instancedGeometry.setAttribute( 'instanceQuaternion', new THREE.InstancedBufferAttribute( new Float32Array( instanceQuaternions ), 4 ) );
instancedGeometry.setAttribute( 'instanceScale', new THREE.InstancedBufferAttribute( new Float32Array( instanceScales ), 3 ) );
//
var shaderMaterial = new THREE.ShaderMaterial( {
uniforms: {},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
vertexColors: true
} );
// counterparts are drawn all at once with a single draw call (via instanced rendering)
var instancedMesh = new THREE.Mesh( instancedGeometry, shaderMaterial );
instancedMesh.position.x = 0.1;
scene.add( instancedMesh );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
controls = new TrackballControls( camera, renderer.domElement );
if ( renderer.extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
document.getElementById( 'notSupported' ).style.display = '';
return;
}
//
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() {
controls.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - indexed instancing (single box), dynamic updates</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">
<style>
a {
color: #08f;
}
#notSupported {
width: 50%;
margin: auto;
background-color: #f00;
margin-top: 20px;
padding: 10px;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - indexed instancing (single box), dynamic updates
<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div>
</div>
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec3 offset;
attribute vec2 uv;
attribute vec4 orientation;
varying vec2 vUv;
// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
vec3 applyQuaternionToVector( vec4 q, vec3 v ){
return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );
}
void main() {
vec3 vPosition = applyQuaternionToVector( orientation, position );
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( offset + vPosition, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
uniform sampler2D map;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D( map, vUv );
}
</script>
<script type="module">
import * as THREE from '../build/three.module.js';
import Stats from './jsm/libs/stats.module.js';
var container, stats;
var camera, scene, renderer, mesh;
var offsetAttribute, orientationAttribute;
var lastTime = 0;
var moveQ = new THREE.Quaternion( 0.5, 0.5, 0.5, 0.0 ).normalize();
var tmpQ = new THREE.Quaternion();
var currentQ = new THREE.Quaternion();
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x101010 );
// geometry
var instances = 5000;
var bufferGeometry = new THREE.BoxBufferGeometry( 2, 2, 2 );
// copying data from a simple box geometry, but you can specify a custom geometry if you want
var geometry = new THREE.InstancedBufferGeometry();
geometry.index = bufferGeometry.index;
geometry.attributes.position = bufferGeometry.attributes.position;
geometry.attributes.uv = bufferGeometry.attributes.uv;
// per instance data
var offsets = [];
var orientations = [];
var vector = new THREE.Vector4();
var x, y, z, w;
for ( var i = 0; i < instances; i ++ ) {
// offsets
x = Math.random() * 100 - 50;
y = Math.random() * 100 - 50;
z = Math.random() * 100 - 50;
vector.set( x, y, z, 0 ).normalize();
vector.multiplyScalar( 5 ); // move out at least 5 units from center in current direction
offsets.push( x + vector.x, y + vector.y, z + vector.z );
// orientations
x = Math.random() * 2 - 1;
y = Math.random() * 2 - 1;
z = Math.random() * 2 - 1;
w = Math.random() * 2 - 1;
vector.set( x, y, z, w ).normalize();
orientations.push( vector.x, vector.y, vector.z, vector.w );
}
offsetAttribute = new THREE.InstancedBufferAttribute( new Float32Array( offsets ), 3 );
orientationAttribute = new THREE.InstancedBufferAttribute( new Float32Array( orientations ), 4 ).setUsage( THREE.DynamicDrawUsage );
geometry.setAttribute( 'offset', offsetAttribute );
geometry.setAttribute( 'orientation', orientationAttribute );
// material
var material = new THREE.RawShaderMaterial( {
uniforms: {
map: { value: new THREE.TextureLoader().load( 'textures/crate.gif' ) }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
if ( renderer.extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
document.getElementById( 'notSupported' ).style.display = '';
return;
}
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 = performance.now();
mesh.rotation.y = time * 0.00005;
var delta = ( time - lastTime ) / 5000;
tmpQ.set( moveQ.x * delta, moveQ.y * delta, moveQ.z * delta, 1 ).normalize();
for ( var i = 0, il = orientationAttribute.count; i < il; i ++ ) {
currentQ.fromArray( orientationAttribute.array, ( i * 4 ) );
currentQ.multiply( tmpQ );
orientationAttribute.setXYZW( i, currentQ.x, currentQ.y, currentQ.z, currentQ.w );
}
orientationAttribute.needsUpdate = true;
lastTime = time;
renderer.render( scene, camera );
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - indexed instancing (single box), interleaved buffers, dynamic updates</title>
<title>three.js webgl - indexed instancing (single box), interleaved buffers</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">
......@@ -22,68 +22,29 @@
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - indexed instancing (single box)<br/>interleaved buffers, dynamic updates
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - indexed instancing (single box), interleaved buffers
<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div>
</div>
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec3 offset;
attribute vec2 uv;
attribute vec4 orientation;
varying vec2 vUv;
// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
vec3 applyQuaternionToVector( vec4 q, vec3 v ){
return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );
}
void main() {
vec3 vPosition = applyQuaternionToVector( orientation, position );
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( offset + vPosition, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
uniform sampler2D map;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D(map, vUv);
}
</script>
<script type="module">
import * as THREE from '../build/three.module.js';
import Stats from './jsm/libs/stats.module.js';
var container, stats;
var camera, scene, renderer, mesh;
var offsetAttribute, orientationAttribute;
var instances = 5000;
var lastTime = 0;
var camera, scene, renderer;
var orientations, instanceBuffer;
var moveQ = new THREE.Quaternion( 0.5, 0.5, 0.5, 0.0 ).normalize();
var tmpQ = new THREE.Quaternion();
var tmpM = new THREE.Matrix4();
var currentM = new THREE.Matrix4();
init();
animate();
function init() {
......@@ -94,12 +55,8 @@
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x101010 );
renderer = new THREE.WebGLRenderer();
// geometry
var instances = 5000;
var geometry = new THREE.InstancedBufferGeometry();
// per mesh data x,y,z,w,u,v,s,t for 4-element alignment
......@@ -161,69 +118,63 @@
geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
// per instance data
instanceBuffer = new THREE.InstancedInterleavedBuffer( new Float32Array( instances * 8 ), 8, 1 ).setUsage( THREE.DynamicDrawUsage );
var offsets = new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 );
// material
var vector = new THREE.Vector4();
for ( var i = 0, ul = offsets.count; i < ul; i ++ ) {
var material = new THREE.MeshBasicMaterial();
material.map = new THREE.TextureLoader().load( 'textures/crate.gif' );
material.side = THREE.DoubleSide;
var x = Math.random() * 100 - 50;
var y = Math.random() * 100 - 50;
var z = Math.random() * 100 - 50;
vector.set( x, y, z, 0 ).normalize();
// move out at least 5 units from center in current direction
offsets.setXYZ( i, x + vector.x * 5, y + vector.y * 5, z + vector.z * 5 );
// per instance data
}
var matrix = new THREE.Matrix4();
var offset = new THREE.Vector3();
var orientation = new THREE.Quaternion();
var scale = new THREE.Vector3( 1, 1, 1 );
var x, y, z, w;
geometry.setAttribute( 'offset', offsets ); // per mesh translation
mesh = new THREE.InstancedMesh( geometry, material, instances );
orientations = new THREE.InterleavedBufferAttribute( instanceBuffer, 4, 4 );
for ( var i = 0; i < instances; i ++ ) {
for ( var i = 0, ul = orientations.count; i < ul; i ++ ) {
// offsets
vector.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
vector.normalize();
x = Math.random() * 100 - 50;
y = Math.random() * 100 - 50;
z = Math.random() * 100 - 50;
orientations.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
offset.set( x, y, z ).normalize();
offset.multiplyScalar( 5 ); // move out at least 5 units from center in current direction
offset.set( x + offset.x, y + offset.y, z + offset.z );
}
// orientations
geometry.setAttribute( 'orientation', orientations ); // per mesh orientation
x = Math.random() * 2 - 1;
y = Math.random() * 2 - 1;
z = Math.random() * 2 - 1;
w = Math.random() * 2 - 1;
// material
var texture = new THREE.TextureLoader().load( 'textures/crate.gif' );
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
orientation.set( x, y, z, w ).normalize();
var material = new THREE.RawShaderMaterial( {
matrix.compose( offset, orientation, scale );
uniforms: {
map: { value: texture }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
side: THREE.DoubleSide,
transparent: false
mesh.setMatrixAt( i, matrix );
} );
}
var mesh = new THREE.Mesh( geometry, material );
mesh.frustumCulled = false;
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
if ( renderer.extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
document.getElementById( "notSupported" ).style.display = "";
document.getElementById( 'notSupported' ).style.display = '';
return;
}
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
......@@ -251,41 +202,31 @@
}
var lastTime = 0;
var moveQ = ( new THREE.Quaternion( .5, .5, .5, 0.0 ) ).normalize();
var tmpQ = new THREE.Quaternion();
var currentQ = new THREE.Quaternion();
function render() {
var time = performance.now();
var object = scene.children[ 0 ];
object.rotation.y = time * 0.00005;
renderer.render( scene, camera );
mesh.rotation.y = time * 0.00005;
var delta = ( time - lastTime ) / 5000;
tmpQ.set( moveQ.x * delta, moveQ.y * delta, moveQ.z * delta, 1 ).normalize();
tmpM.makeRotationFromQuaternion( tmpQ );
for ( var i = 0, ul = orientations.count; i < ul; i ++ ) {
for ( var i = 0, il = instances; i < il; i ++ ) {
var index = i * instanceBuffer.stride + orientations.offset;
currentQ.set( instanceBuffer.array[ index ], instanceBuffer.array[ index + 1 ], instanceBuffer.array[ index + 2 ], instanceBuffer.array[ index + 3 ] );
currentQ.multiply( tmpQ );
orientations.setXYZW( i, currentQ.x, currentQ.y, currentQ.z, currentQ.w );
mesh.getMatrixAt( i, currentM );
currentM.multiply( tmpM );
mesh.setMatrixAt( i, currentM );
}
instanceBuffer.needsUpdate = true;
mesh.instanceMatrix.needsUpdate = true;
lastTime = time;
}
renderer.render( scene, camera );
init();
animate();
}
</script>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册