gpt4 book ai didi

three.js - GLTF 创建实例

转载 作者:行者123 更新时间:2023-12-02 08:23:31 25 4
gpt4 key购买 nike

我是 THREEJS 的新人。过去,我使用过 AFRAME、CESIUM、XEOGL 和 BABYLONJS。但最终,由于内存消耗和性能,我意识到制作 CAD 可视化工具的最佳产品是 THREEJS。

BABYLONJS 需要 4 分钟以上才能加载一个大 GLTF 文件 (400MB),而 THREEJS 只需 30 秒。 BABYLONJS 占用的内存是 THREEJS 的 4 倍。

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

我尝试过GLTF1.0和GLTF2.0,问题是一样的。当我加载 GLTF 模型时,我得到一个场景。从这个场景中,我试图从子数组中获取缓冲区几何形状。但是,当我尝试创建实例时,它不起作用。我的对象是静态的(根本没有动画)。

有什么方法可以创建 Object3D 的实例或从其缓冲区几何图形创建实例吗?

在 BABYLONJS 中,从加载的 GLTF 文件创建实例非常简单。我确实需要使用实例来节省 RAM 并使用 GPU 而不是 CPU 资源。我的场景需要加载相同对象的许多副本来复合场景。

我在使用 GLFT 加载程序时看到的一些问题:

    1. 您必须识别包含有效几何图形的所有 object3D。在这个例子中是第 335 行:

    var geo = data.scene.children[0].children[0].children[0].children[0].geometry

  • 合并示例不起作用。它在原始示例中也不起作用。
  • IT 部门似乎认为实例化根本无法提高性能:
  • 10000 个物体,多种 Material --> 4FPS

  • 10000 个对象,单一 Material --> 4FPS

  • 10000 个对象,实例 --> 4FPS

  • 10000 个对象,已合并 --> 不起作用

  • 选择实例化后,几何图形无法正确渲染。

这里有我使用 Duck 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>

最佳答案

看来你的问题主要是,如何在 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 );

关于three.js - GLTF 创建实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45669968/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com