2017-08-14 274 views
1

我是THREEJS的新成员,过去我使用过AFRAME,CESIUM,XEOGL和BABYLONJS,但最后由于内存消耗和性能,我意识到制作CAD可视化器的最佳产品是THREEJS 。GLTF创建实例

BABYLONJS需要4分多钟才能载入一个大的GLTF文件(400MB),而THREEJS只需要30秒。 BABYLONJS的记忆力是THREEJS使用的4倍。

我知道仍然有一些问题能够从THREEJS中加载的GLTF文件创建实例(GPU),但我只需要在每个实例中更改位置和旋转角度,而不需要设置任何动画。

我试过用GLTF1.0和GLTF2.0,问题是一样的。 当我加载GLTF模型时,我得到一个场景。

从这个场景我试图从儿童数组获得缓冲区几何,但是当我试图créate一个实例它不起作用。

我的对象是静态的(根本没有动画)。

有什么办法可以创建一个Object3D的实例或从其缓冲区几何?

在BABYLONJS中,从加载的GLTF文件创建实例非常简单。

我确实需要使用实例来破坏RAM,并使用GPU来代替CPU资源。

我的场景需要加载很多次相同的对象来复合场景。

非常感谢您的支持。

我使用GLFT加载器看到的一些问题: 1.-您必须识别包含有效几何体的所有object3D。在这个例子中是第335行: var geo = data.scene.children [0] .children [0] .children [0] .children [0] .geometry 2.-合并示例不起作用。它在原始示例中不起作用。 3.-似乎实例化不提高性能都: - 10000对象,多材料 - >下4fps - 10000对象,singlematerial - >下4fps - 10000对象实例化 - >下4fps - 10000的对象,合并 - >不工作 4.-当选择了instanced时,几何图形不能正确渲染。

在这里,你已经用我的代码鸭GLTF例如:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
<title>three.js webgl - interactive instances (gpu)</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 { 
font-family: Monospace; 
background-color: #f0f0f0; 
margin: 0px; 
overflow: hidden; 
} 
.info { 
position: absolute; 
background-color: black; 
opacity: 0.8; 
color: white; 
text-align: center; 
top: 0px; 
width: 100%; 
} 
.info a { 
color: #00ffff; 
} 
#notSupported { 
width: 50%; 
margin: auto; 
border: 2px red solid; 
margin-top: 20px; 
padding: 10px; 
} 
</style> 
</head> 
<body> 
<div class="info"> 
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - gpu picking of geometry instances 
<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div> 
<br/><br/> 
<div>This demo compares different methods of constructing and rendering many instances of a single geometry.</div> 
<br/> 
<div> 
<div style="display:inline-block;"> 
<span>number of<br/>geometry instances</span> 
<br/> 
<select id="instanceCount"> 
<option>100</option> 
<option>500</option> 
<option selected>1000</option> 
<option>2000</option> 
<option>3000</option> 
<option>5000</option> 
<option>10000</option> 
<option>20000</option> 
<option>30000</option> 
<option>50000</option> 
<option>100000</option> 
</select> 
</div> 
&nbsp;&nbsp;&nbsp; 
<div style="display:inline-block;"> 
<span>method of<br/>construction/rendering</span> 
<br/> 
<select id="method"> 
<option>instanced</option> 
<option>merged</option> 
<option selected>singleMaterial</option> 
<option>multiMaterial</option> 
</select> 
</div> 
&nbsp;&nbsp;&nbsp; 
<div style="display:inline-block;"> 
<span>render continuously<br/>(to get fps reading)</span> 
<br/> 
<input id="animate" type="checkbox" /> 
</div> 
&nbsp;&nbsp;&nbsp; 
<div style="display:inline-block;"> 
<span>use override material<br/>(only effects singleMaterial method)</span> 
<br/> 
<input id="override" type="checkbox" checked/> 
</div> 
&nbsp;&nbsp;&nbsp; 
<div style="display:inline-block;"> 
<span>construct anew<br/>(to get additional timings)</span> 
<br/> 
<button id="construct" type="button">do it</button> 
</div> 
</div> 
<br/> 
<div> 
<span>Materials: #<span id="materialCount"></span></span> 
&nbsp;&nbsp;&nbsp; 
<span>Objects: #<span id="objectCount"></span></span> 
&nbsp;&nbsp;&nbsp; 
<span>Drawcalls: #<span id="drawcalls"></span></span> 
&nbsp;&nbsp;&nbsp; 
<span>Construction time: <span id="initTime"></span>&nbsp;ms</span> 
&nbsp;&nbsp;&nbsp; 
</div> 
</div> 
<div id="container"></div> 
<script src="../build/three.js"></script> 
<script src="js/controls/TrackballControls.js"></script> 
<script src="js/libs/stats.min.js"></script> 
<script src="js/loaders/GLTF2Loader.js"></script> 
<script id="vertMerged" type="x-shader/x-vertex"> 
#define SHADER_NAME vertMerged 
precision highp float; 
uniform mat4 modelViewMatrix; 
uniform mat4 projectionMatrix; 
attribute vec3 position; 
#ifdef PICKING 
attribute vec3 pickingColor; 
#else 
attribute vec3 color; 
varying vec3 vPosition; 
#endif 
varying vec3 vColor; 
void main() { 
vec3 positionEye = (modelViewMatrix * vec4(position, 1.0)).xyz; 
#ifdef PICKING 
vColor = pickingColor; 
#else 
vColor = color; 
vPosition = positionEye; 
#endif 
gl_Position = projectionMatrix * vec4(positionEye, 1.0); 
} 
</script> 
<script id="fragMerged" type="x-shader/x-fragment"> 
#define SHADER_NAME fragMerged 
#extension GL_OES_standard_derivatives : enable 
precision highp float; 
varying vec3 vColor; 
#ifndef PICKING 
varying vec3 vPosition; 
#endif 
void main() { 
#ifdef PICKING 
gl_FragColor = vec4(vColor, 1.0); 
#else 
vec3 fdx = dFdx(vPosition); 
vec3 fdy = dFdy(vPosition); 
vec3 normal = normalize(cross(fdx, fdy)); 
float diffuse = dot(normal, vec3(0.0, 0.0, 1.0)); 
gl_FragColor = vec4(diffuse * vColor, 1.0); 
#endif 
} 
</script> 
<script id="vertInstanced" type="x-shader/x-vertex"> 
#define SHADER_NAME vertInstanced 
precision highp float; 
uniform mat4 modelViewMatrix; 
uniform mat4 projectionMatrix; 
attribute vec3 position; 
attribute vec3 mcol0; 
attribute vec3 mcol1; 
attribute vec3 mcol2; 
attribute vec3 mcol3; 
#ifdef PICKING 
attribute vec3 pickingColor; 
#else 
attribute vec3 color; 
varying vec3 vPosition; 
#endif 
varying vec3 vColor; 
void main() { 
mat4 matrix = mat4(
vec4(mcol0, 0), 
vec4(mcol1, 0), 
vec4(mcol2, 0), 
vec4(mcol3, 1) 
); 
vec3 positionEye = (modelViewMatrix * matrix * vec4(position, 1.0)).xyz; 
#ifdef PICKING 
vColor = pickingColor; 
#else 
vColor = color; 
vPosition = positionEye; 
#endif 
gl_Position = projectionMatrix * vec4(positionEye, 1.0); 
} 
</script> 
<script id="fragInstanced" type="x-shader/x-fragment"> 
#define SHADER_NAME fragInstanced 
#extension GL_OES_standard_derivatives : enable 
precision highp float; 
varying vec3 vColor; 
#ifndef PICKING 
varying vec3 vPosition; 
#endif 
void main() { 
#ifdef PICKING 
gl_FragColor = vec4(vColor, 1.0); 
#else 
vec3 fdx = dFdx(vPosition); 
vec3 fdy = dFdy(vPosition); 
vec3 normal = normalize(cross(fdx, fdy)); 
float diffuse = dot(normal, vec3(0.0, 0.0, 1.0)); 
gl_FragColor = vec4(diffuse * vColor, 1.0); 
#endif 
} 
</script> 
<script id="vertMaterial" type="x-shader/x-vertex"> 
#define SHADER_NAME vertMaterial 
precision highp float; 
uniform mat4 modelViewMatrix; 
uniform mat4 projectionMatrix; 
attribute vec3 position; 
#ifndef PICKING 
varying vec3 vPosition; 
#endif 
void main() { 
vec3 positionEye = (modelViewMatrix * vec4(position, 1.0)).xyz; 
#ifndef PICKING 
vPosition = positionEye; 
#endif 
gl_Position = projectionMatrix * vec4(positionEye, 1.0); 
} 
</script> 
<script id="fragMaterial" type="x-shader/x-fragment"> 
#define SHADER_NAME fragMaterial 
#extension GL_OES_standard_derivatives : enable 
precision highp float; 
#ifdef PICKING 
uniform vec3 pickingColor; 
#else 
uniform vec3 color; 
varying vec3 vPosition; 
#endif 
void main() { 
#ifdef PICKING 
gl_FragColor = vec4(pickingColor, 1.0); 
#else 
vec3 fdx = dFdx(vPosition); 
vec3 fdy = dFdy(vPosition); 
vec3 normal = normalize(cross(fdx, fdy)); 
float diffuse = dot(normal, vec3(0.0, 0.0, 1.0)); 
gl_FragColor = vec4(diffuse * color, 1.0); 
#endif 
} 
</script> 
<script> 
var container, stats; 
var camera, controls, scene, renderer; 
var pickingData, pickingRenderTarget, pickingScene; 
var useOverrideMaterial = true; 
var singleMaterial, singlePickingMaterial; 
var highlightBox; 
var materialList = []; 
var geometryList = []; 
var objectCount = 0; 
var geometrySize; 
var mouse = new THREE.Vector2(); 
var scale = 1.03; 
var loader = new THREE.GLTF2Loader(); 
var pixelBuffer = new Uint8Array(4); 
var instanceCount, method, doAnimate; 
gui(); 
init(); 
initMesh(); 
if (doAnimate) animate(); 
function gui() { 
var instanceCountElm = document.getElementById('instanceCount'); 
instanceCount = parseInt(instanceCountElm.value); 
instanceCountElm.addEventListener("change", function() { 
instanceCount = parseInt(instanceCountElm.value); 
initMesh(); 
}); 
var methodElm = document.getElementById('method'); 
method = methodElm.value; 
methodElm.addEventListener("change", function() { 
method = methodElm.value; 
initMesh(); 
}); 
var animateElm = document.getElementById('animate'); 
doAnimate = animateElm.checked; 
animateElm.addEventListener("click", function() { 
doAnimate = animateElm.checked; 
animate(); 
}); 
var overrideElm = document.getElementById('override'); 
useOverrideMaterial = overrideElm.checked; 
overrideElm.addEventListener("click", function() { 
useOverrideMaterial = overrideElm.checked; 
initMesh(); 
}); 
var constructElm = document.getElementById('construct'); 
constructElm.addEventListener("click", function() { 
initMesh(); 
}); 
} 
function clean() { 
THREE.Cache.clear(); 
materialList.forEach(function(m) { 
m.dispose(); 
}); 
geometryList.forEach(function(g) { 
g.dispose(); 
}); 
scene = new THREE.Scene(); 
scene.background = new THREE.Color(0xffffff); 
scene.add(camera); 
scene.add(highlightBox); 
pickingScene = new THREE.Scene(); 
pickingData = {}; 
materialList = []; 
geometryList = []; 
objectCount = 0; 
singleMaterial = undefined; 
singlePickingMaterial = undefined; 
} 
var randomizeMatrix = function() { 
var position = new THREE.Vector3(); 
var rotation = new THREE.Euler(); 
var quaternion = new THREE.Quaternion(); 
var scale = new THREE.Vector3(); 
return function(matrix) { 
position.x = Math.random() * 40 - 20; 
position.y = Math.random() * 40 - 20; 
position.z = Math.random() * 40 - 20; 
rotation.x = Math.random() * 2 * Math.PI; 
rotation.y = Math.random() * 2 * Math.PI; 
rotation.z = Math.random() * 2 * Math.PI; 
quaternion.setFromEuler(rotation, false); 
scale.x = scale.y = scale.z = 0.001; 
matrix.compose(position, quaternion, scale); 
}; 
}(); 
function initMesh() { 
clean(); 
loader.load('models/gltf/Duck/glTF-Binary/Duck.glb', function (data) { 
console.log(data); 
var geo = data.scene.children[0].children[0].children[0].children[0].geometry 
console.log("geo:"); 
console.log(geo); 
geo.computeBoundingBox(); 
geometrySize = geo.boundingBox.getSize(); 
geometryList.push(geo); 
var start = window.performance.now(); 
switch (method){ 
case "merged": 
makeMerged(geo); 
break; 
case "instanced": 
makeInstanced(geo); 
break; 
case "singleMaterial": 
makeSingleMaterial(geo); 
break; 
case "multiMaterial": 
makeMultiMaterial(geo); 
break; 
} 
render(); 
var end = window.performance.now(); 
document.getElementById('materialCount').innerText = materialList.length; 
document.getElementById('objectCount').innerText = objectCount; 
document.getElementById('drawcalls').innerText = renderer.info.render.calls; 
document.getElementById('initTime').innerText = (end - start).toFixed(2); 
}); 
} 
function makeMultiMaterial(geo) { 
var vert = document.getElementById('vertMaterial').textContent; 
var frag = document.getElementById('fragMaterial').textContent; 
var material = new THREE.RawShaderMaterial({ 
vertexShader: vert, 
fragmentShader: frag, 
uniforms: { 
color: { 
value: new THREE.Color() 
} 
} 
}); 
var pickingMaterial = new THREE.RawShaderMaterial({ 
vertexShader: "#define PICKING\n" + vert, 
fragmentShader: "#define PICKING\n" + frag, 
uniforms: { 
pickingColor: { 
value: new THREE.Color() 
} 
} 
}); 
var matrix = new THREE.Matrix4(); 
for (var i = 0; i < instanceCount; i ++) { 
var object = new THREE.Mesh(geo, material); 
objectCount ++; 
randomizeMatrix(matrix); 
object.applyMatrix(matrix); 
var pickingObject = object.clone(); 
objectCount ++; 
object.material = material.clone(); 
object.material.uniforms.color.value.setHex(Math.random() * 0xffffff); 
materialList.push(object.material); 
pickingObject.material = pickingMaterial.clone(); 
pickingObject.material.uniforms.pickingColor.value.setHex(i + 1); 
materialList.push(pickingObject.material); 
pickingData[ i + 1 ] = object; 
scene.add(object); 
pickingScene.add(pickingObject); 
} 
material.dispose(); 
pickingMaterial.dispose(); 
} 
function makeSingleMaterial(geo) { 
var vert = document.getElementById('vertMaterial').textContent; 
var frag = document.getElementById('fragMaterial').textContent; 
var material = new THREE.RawShaderMaterial({ 
vertexShader: vert, 
fragmentShader: frag, 
uniforms: { 
color: { 
value: new THREE.Color() 
} 
} 
}); 
materialList.push(material); 
var pickingMaterial = new THREE.RawShaderMaterial({ 
vertexShader: "#define PICKING\n" + vert, 
fragmentShader: "#define PICKING\n" + frag, 
uniforms: { 
pickingColor: { 
value: new THREE.Color() 
} 
} 
}); 
materialList.push(pickingMaterial); 
if (useOverrideMaterial) { 
singleMaterial = material; 
singlePickingMaterial = pickingMaterial; 
} 
var matrix = new THREE.Matrix4(); 
function onBeforeRender(renderer, scene, camera, geometry, material, group){ 
var updateList = []; 
var u = material.uniforms; 
var d = this.userData; 
if(u.pickingColor){ 
u.pickingColor.value.setHex(d.pickingColor); 
updateList.push("pickingColor"); 
} 
if(u.color){ 
u.color.value.setHex(d.color); 
updateList.push("color"); 
} 
if(updateList.length){ 
var materialProperties = renderer.properties.get(material); 
if(materialProperties.program){ 
var gl = renderer.getContext(); 
var p = materialProperties.program; 
gl.useProgram(p.program); 
var pu = p.getUniforms(); 
updateList.forEach(function(name){ 
pu.setValue(gl, name, u[ name ].value); 
}); 
} 
} 
} 
for (var i = 0; i < instanceCount; i ++) { 
var object = new THREE.Mesh(geo, material); 
objectCount ++; 
randomizeMatrix(matrix); 
object.applyMatrix(matrix); 
var pickingObject; 
if (! useOverrideMaterial) { 
pickingObject = object.clone(); 
objectCount ++; 
} 
object.material = material; 
object.userData[ "color" ] = Math.random() * 0xffffff; 
if (useOverrideMaterial) { 
object.userData[ "pickingColor" ] = i + 1; 
object.onBeforeRender = onBeforeRender; 
}else { 
pickingObject.material = pickingMaterial; 
pickingObject.userData[ "pickingColor" ] = i + 1; 
pickingObject.onBeforeRender = onBeforeRender; 
} 
pickingData[ i + 1 ] = object; 
scene.add(object); 
if (! useOverrideMaterial) pickingScene.add(pickingObject); 
} 
} 
function makeMerged(geo) { 
var vert = document.getElementById('vertMerged').textContent; 
var frag = document.getElementById('fragMerged').textContent; 
var material = new THREE.RawShaderMaterial({ 
vertexShader: vert, 
fragmentShader: frag 
}); 
materialList.push(material); 
var pickingMaterial = new THREE.RawShaderMaterial({ 
vertexShader: "#define PICKING\n" + vert, 
fragmentShader: "#define PICKING\n" + frag 
}); 
materialList.push(pickingMaterial); 
var bgeo = geo.clone(); 
geometryList.push(bgeo); 
var mgeo = new THREE.BufferGeometry(); 
geometryList.push(mgeo); 
var pos = bgeo.attributes.position; 
var posLen = bgeo.attributes.position.count * 3; 
var vertices = new THREE.BufferAttribute(
new Float32Array(instanceCount * posLen), 3 
); 

var matrix = new THREE.Matrix4(); 
for (var i = 0, ul = instanceCount; i < ul; i ++) { 
randomizeMatrix(matrix); 
var object = new THREE.Object3D(); 
objectCount ++; 
object.applyMatrix(matrix); 
pickingData[ i + 1 ] = object; 
vertices.set(pos.array, i * posLen); 
//matrix.applyToVector3Array(vertices.array, i * posLen, posLen) 
} 
mgeo.addAttribute('position', vertices); 
var colCount = posLen/3; 
var colors = new THREE.BufferAttribute(
new Float32Array(instanceCount * colCount * 3), 3 
); 



var randCol = function() { 
return Math.random(); 
}; 
for (var i = 0, ul = instanceCount; i < ul; i ++) { 
var r = randCol(), g = randCol(), b = randCol(); 
for (var j = i * colCount, jl = (i + 1) * colCount; j < jl; j ++) { 
colors.setXYZ(j, r, g, b); 
} 
} 
mgeo.addAttribute('color', colors); 
var col = new THREE.Color(); 
var pickingColors = new THREE.BufferAttribute(
new Float32Array(instanceCount * colCount * 3), 3 
); 
for (var i = 0, ul = instanceCount; i < ul; i ++) { 
col.setHex(i + 1); 
for (var j = i * colCount, jl = (i + 1) * colCount; j < jl; j ++) { 
pickingColors.setXYZ(j, col.r, col.g, col.b); 
} 
} 
mgeo.addAttribute('pickingColor', pickingColors); 
var mesh = new THREE.Mesh(mgeo, material); 
scene.add(mesh); 
var pickingMesh = new THREE.Mesh(mgeo, pickingMaterial); 
pickingScene.add(pickingMesh); 
} 
function makeInstanced(geo) { 
var vert = document.getElementById('vertInstanced').textContent; 
var frag = document.getElementById('fragInstanced').textContent; 
var material = new THREE.RawShaderMaterial({ 
vertexShader: vert, 
fragmentShader: frag, 
}); 
materialList.push(material); 
var pickingMaterial = new THREE.RawShaderMaterial({ 
vertexShader: "#define PICKING\n" + vert, 
fragmentShader: "#define PICKING\n" + frag 
}); 
materialList.push(pickingMaterial); 
var bgeo = geo.clone(); 
geometryList.push(bgeo); 
var igeo = new THREE.InstancedBufferGeometry(); 
geometryList.push(igeo); 
var vertices = bgeo.attributes.position.clone(); 
igeo.addAttribute('position', vertices); 
var mcol0 = new THREE.InstancedBufferAttribute(
new Float32Array(instanceCount * 3), 3, 1 
); 
var mcol1 = new THREE.InstancedBufferAttribute(
new Float32Array(instanceCount * 3), 3, 1 
); 
var mcol2 = new THREE.InstancedBufferAttribute(
new Float32Array(instanceCount * 3), 3, 1 
); 
var mcol3 = new THREE.InstancedBufferAttribute(
new Float32Array(instanceCount * 3), 3, 1 
); 
var matrix = new THREE.Matrix4(); 
var me = matrix.elements; 
for (var i = 0, ul = mcol0.count; i < ul; i ++) { 
randomizeMatrix(matrix); 
var object = new THREE.Object3D(); 
objectCount ++; 
object.applyMatrix(matrix); 
pickingData[ i + 1 ] = object; 
mcol0.setXYZ(i, me[ 0 ], me[ 1 ], me[ 2 ]); 
mcol1.setXYZ(i, me[ 4 ], me[ 5 ], me[ 6 ]); 
mcol2.setXYZ(i, me[ 8 ], me[ 9 ], me[ 10 ]); 
mcol3.setXYZ(i, me[ 12 ], me[ 13 ], me[ 14 ]); 
} 
igeo.addAttribute('mcol0', mcol0); 
igeo.addAttribute('mcol1', mcol1); 
igeo.addAttribute('mcol2', mcol2); 
igeo.addAttribute('mcol3', mcol3); 
var randCol = function() { 
return Math.random(); 
}; 
var colors = new THREE.InstancedBufferAttribute(
new Float32Array(instanceCount * 3), 3, 1 
); 
for (var i = 0, ul = colors.count; i < ul; i ++) { 
colors.setXYZ(i, randCol(), randCol(), randCol()); 
} 
igeo.addAttribute('color', colors); 
var col = new THREE.Color(); 
var pickingColors = new THREE.InstancedBufferAttribute(
new Float32Array(instanceCount * 3), 3, 1 
); 
for (var i = 0, ul = pickingColors.count; i < ul; i ++) { 
col.setHex(i + 1); 
pickingColors.setXYZ(i, col.r, col.g, col.b); 
} 
igeo.addAttribute('pickingColor', pickingColors); 
var mesh = new THREE.Mesh(igeo, material); 
scene.add(mesh); 
var pickingMesh = new THREE.Mesh(igeo, pickingMaterial); 
pickingScene.add(pickingMesh); 
} 
function init() { 
camera = new THREE.PerspectiveCamera(
70, window.innerWidth/window.innerHeight, 1, 100 
); 
camera.position.z = 40; 
pickingRenderTarget = new THREE.WebGLRenderTarget(
window.innerWidth, window.innerHeight 
); 
pickingRenderTarget.texture.generateMipmaps = false; 
pickingRenderTarget.texture.minFilter = THREE.NearestFilter; 
highlightBox = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1), 
new THREE.MeshLambertMaterial({ 
emissive: 0xffff00, 
transparent: true, 
opacity: 0.5, 
side: THREE.FrontSide 
}) 
); 
container = document.getElementById("container"); 
renderer = new THREE.WebGLRenderer({ 
antialias: true, 
alpha: true 
}); 
if (renderer.extensions.get('ANGLE_instanced_arrays') === false) { 
document.getElementById("notSupported").style.display = ""; 
return; 
} 
renderer.setPixelRatio(window.devicePixelRatio); 
renderer.setSize(window.innerWidth, window.innerHeight); 
container.appendChild(renderer.domElement); 
if (renderer.extensions.get('ANGLE_instanced_arrays') === false) { 
throw 'ANGLE_instanced_arrays not supported'; 
} 
controls = new THREE.TrackballControls(
camera, renderer.domElement 
); 
controls.staticMoving = true; 
stats = new Stats(); 
container.appendChild(stats.dom); 
renderer.domElement.addEventListener('mousemove', onMouseMove); 
window.addEventListener('resize', onWindowResize, false); 
} 
// 
function onMouseMove(e) { 
mouse.x = e.clientX; 
mouse.y = e.clientY; 
controls.update(); 
requestAnimationFrame(render); 
} 
function onWindowResize(event) { 
camera.aspect = window.innerWidth/window.innerHeight; 
camera.updateProjectionMatrix(); 
renderer.setSize(window.innerWidth, window.innerHeight); 
pickingRenderTarget.setSize(window.innerWidth, window.innerHeight); 
} 
function animate() { 
if (doAnimate) { 
requestAnimationFrame(animate); 
} 
controls.update(); 
stats.update(); 
document.getElementById('materialCount').innerText = materialList.length; 
document.getElementById('objectCount').innerText = objectCount; 
document.getElementById('drawcalls').innerText = renderer.info.render.calls; 
render(); 
} 
function pick() { 
highlightBox.visible = false; 
if (singlePickingMaterial) { 
scene.overrideMaterial = singlePickingMaterial; 
renderer.render(scene, camera, pickingRenderTarget); 
scene.overrideMaterial = null; 
}else { 
renderer.render(pickingScene, camera, pickingRenderTarget); 
} 
renderer.readRenderTargetPixels(
pickingRenderTarget, 
mouse.x, 
pickingRenderTarget.height - mouse.y, 
1, 
1, 
pixelBuffer 
); 
var id = 
(pixelBuffer[ 0 ] << 16) | 
(pixelBuffer[ 1 ] << 8) | 
(pixelBuffer[ 2 ]); 
var object = pickingData[ id ]; 
if (object) { 
if (object.position && object.rotation && object.scale) { 
highlightBox.position.copy(object.position); 
highlightBox.rotation.copy(object.rotation); 
highlightBox.scale.copy(object.scale) 
.multiply(geometrySize) 
.multiplyScalar(scale); 
highlightBox.visible = true; 
} 
} else { 
highlightBox.visible = false; 
} 
} 
function render() { 
pick(); 
renderer.render(scene, camera); 
} 
</script> 
</body> 
</html> 

回答

3

好像你的问题主要是,如何做实例化的three.js所?一旦你加载了一个模型,它用什么格式来创建它并不重要。

既然如此,您可能只想查看three.js instancing examples或使用three-instanced-mesh之类的助手之一。

第二个链接显示如何进行,一旦你抓住了从模型的几何形状:

// Assumes your model only contains one mesh. 
var geometry; 
model.traverse(function (node) => { 
    if (node.isMesh) { 
    geometry = node.geometry; 
    } 
}); 

//material that the geometry will use 
var material = new THREE.MeshPhongMaterial(); 

//the instance group 
var cluster = new THREE.InstancedMesh( 
    geometry, 
    material, 
    10000, //instance count 
    false, //is it dynamic 
    false //does it have color 
    true, //uniform scale 
); 

var _v3 = new THREE.Vector3(); 
var _q = new THREE.Quaternion(); 

for (var i ; i < 10000 ; i ++) { 

    cluster.setQuaternionAt(i , _q); 
    cluster.setPositionAt(i , v3.set(Math.random() , Math.random(), Math.random())); 
    cluster.setScaleAt(i , v3.set(1,1,1)); 

} 

scene.add(cluster); 
+0

yeey谢谢你的插件! – pailhead

1

是的,我已经基于GPU的实例例如: https://threejs.org/examples/?q=insta#webgl_interactive_instances_gpu

当加载GLTF文件,你真的得到了一个/多个object3d的场景。 这些object3D对象没有几何形状,而是缓冲区几何。

我试图调整这个例子来加载一个GLTF模型,而不是JSON模型。

我已经成功地通过制作缓冲区几何体的克隆来创建实例,但边界框没有正确生成,我不知道为什么。

请尝试更改此示例并尝试使用GLTF模型,您会看到。

顺便说一句,我不知道为什么,但如果我尝试使用构造函数THREE.InstancedMesh它说这不是一个有效的构造函数。我正在使用r87。

我在示例中看到的另一个问题是合并不起作用。它说,matrix.applyToVector3Array已被删除,我不知道替代。

此致敬礼和非常感谢您的支持。

+0

最好不要创建可扩展您的问题的答案,而是编辑添加详细信息的原始问题。特别是,你似乎试图实现这一点,并得到特定于你的代码的错误,但是你没有在你的问题中包含任何代码。只有包含描述您所尝试的代码的内容才能提供帮助。 –

0

经过一段时间的调查后,我发现为什么使用instancedbuffergeometries不能处理在我的GLTF文件中找到的缓冲区几何。

问题是GLTF格式使用索引缓冲几何,解决方法非常简单,只需将它们转换为toNonIndexed()方法即可。

问题修复。

最好的问候