问题描述
限时送ChatGPT账号..我似乎无法再让 InstancedBufferGeometry 出现在场景中.我尝试了以下技术:
I can't seem to get an InstancedBufferGeometry to appear in a scene anymore. I've tried the following technique:
let bg = BoxBufferGeometry(3,3,3),
ig : InstancedBufferGeometry = new InstancedBufferGeometry(),
mesh : Mesh;
ig.index = bg.index;
ig.attributes.position = bg.attributes.position;
ig.attributes.uv = bg.attributes.uv;
//ig.copy( bg ); <- also tried this
ig.instanceCount = Infinity; <- otherwise this populates as undefined
var offsets = [];
var orientations = [];
var vector = new Vector4();
var x, y, z, w;
for ( var i = 0; i < 1000; 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 );
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 );
}
var offsetAttribute = new InstancedBufferAttribute( new Float32Array( offsets ), 3 );
var orientationAttribute = new InstancedBufferAttribute( new Float32Array( orientations ), 4 ).setUsage( DynamicDrawUsage );
ig.setAttribute( 'offset', offsetAttribute );
ig.setAttribute( 'orientation', orientationAttribute );
let m = new MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } );
mesh = new Mesh( ig, m );
scene.add(mesh);
我没有收到任何错误,并且当我检查时网格确实出现在场景中.我已经尝试了 IBG 中的所有属性组合.
I don't get any errors and the mesh does appear in the scene when I inspect. I've tried all combinations of attributes in the IBG.
这种方法不再有效了吗?(它在 r97 中有效......我知道,很久以前.)
Will this approach no longer work? (It worked in r97... I know, ages ago. )
推荐答案
let m = new MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } );
let m = new MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } );
当使用 InstancedBufferGeometry
时,您不能使用像 MeshPhongMaterial
这样的内置材质创建网格.相反,您必须创建一个利用实例化属性的自定义着色器.示例:
When using InstancedBufferGeometry
, you can't create a mesh with built-in materials like MeshPhongMaterial
. Instead you have to create a custom shader that utilizes the instanced attributes. Example:
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 100;
scene = new THREE.Scene();
var geometry = new THREE.BoxBufferGeometry();
var ig = new THREE.InstancedBufferGeometry();
ig.index = geometry.index;
ig.attributes.position = geometry.attributes.position;
var offsets = [];
var orientations = [];
var vector = new THREE.Vector4();
var x, y, z, w;
for (var i = 0; i < 1000; i++) {
// offsets
x = Math.random() * 100 - 50;
y = Math.random() * 100 - 50;
z = Math.random() * 100 - 50;
vector.set(x, y, z, 0).normalize();
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);
}
var offsetAttribute = new THREE.InstancedBufferAttribute(new Float32Array(offsets), 3);
var orientationAttribute = new THREE.InstancedBufferAttribute(new Float32Array(orientations), 4);
ig.setAttribute('offset', offsetAttribute);
ig.setAttribute('orientation', orientationAttribute);
var material = new THREE.RawShaderMaterial({
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent,
side: THREE.DoubleSide
});
mesh = new THREE.Mesh(ig, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr/npm/three@0.124/build/three.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec3 offset;
attribute vec4 orientation;
void main(){
vec3 pos = offset + position;
vec3 vcV = cross( orientation.xyz, pos );
pos = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + pos );
gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
</script>
考虑使用 InstancedMesh 以获得更直接的用法实例化渲染.
Consider to use InstancedMesh for a more straightforward usage of instanced rendering.
这篇关于无法让 Three.js InstancedBufferGeometry 出现在场景中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论