就在昨天我开始尝试使用InstancedBufferGeometry方法,因为我希望渲染数千个具有良好性能的对象。 在我的情况下,我想要实例具有彼此不同高度的立方体几何。 我刚试过这段代码
AFRAME.registerComponent('instancing', {
schema: {
count: {type: 'int', default: 10000}
},
init: function () {
this.count = this.data.count;
this.model = null;
},
update: function () {
if (this.model !== null) { return; }
var data = this.data;
var el = this.el;
var count = this.count;
var geometry = new THREE.InstancedBufferGeometry();
geometry.copy(new THREE.BoxBufferGeometry(10, 5, 10));
var translateArray = new Float32Array(count*3);
var vectorArray = new Float32Array(count*3);
var colorArray = new Float32Array(count*3);
var vertices = new Float32Array(count * 24);
for(var i = 0; i < count; i++){
var y = Math.floor((Math.random() * 200) + 50);
vertices[i*3+0] = 10;
vertices[i*3+1] = y;
vertices[i*3+2] = 10;
vertices[i*24+3] = 10;
vertices[i*24+4] = y;
vertices[i*24+5] = -10;
vertices[i*24+6] = 10;
vertices[i*24+7] = -y;
vertices[i*24+8] = 10;
vertices[i*24+9] = 10;
vertices[i*24+10] = -y;
vertices[i*24+11] = -10;
vertices[i*24+12] = -10;
vertices[i*24+13] = y;
vertices[i*24+14] = -10;
vertices[i*24+15] = -10;
vertices[i*24+16] = y;
vertices[i*24+17] = 10;
vertices[i*24+18] = -10;
vertices[i*24+19] = -y;
vertices[i*24+20] = -10;
vertices[i*24+21] = -10;
vertices[i*24+22] = -y;
vertices[i*24+23] = 10;
}
for (var i = 0; i < count; i++) {
translateArray[i*3+0] = (Math.random() - 0.5) * 100.0;
translateArray[i*3+1] = (Math.random() - 0.5) * 100.0;
translateArray[i*3+2] = (Math.random() - 0.5) * 100.0;
}
for (var i = 0; i < count; i++) {
vectorArray[i*3+0] = (Math.random() - 0.5) * 100.0;
vectorArray[i*3+1] = (Math.random() + 1.5) * 100.0;
vectorArray[i*3+2] = (Math.random() - 0.5) * 100.0;
}
for (var i = 0; i < count; i++) {
colorArray[i*3+0] = Math.random();
colorArray[i*3+1] = Math.random();
colorArray[i*3+2] = Math.random();
}
geometry.addAttribute('position', new THREE.InstancedBufferAttribute(vertices, 24, 1));
geometry.addAttribute('translate', new THREE.InstancedBufferAttribute(translateArray, 3, 1));
geometry.addAttribute('vector', new THREE.InstancedBufferAttribute(vectorArray, 3, 1));
geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1));
var material = new THREE.ShaderMaterial({
uniforms: {
time: {value: 0}
},
vertexShader: [
'attribute vec3 translate;',
'attribute vec3 vector;',
'attribute vec3 color;',
'uniform float time;',
'varying vec3 vColor;',
'const float g = 9.8 * 1.5;',
'void main() {',
' vec3 offset;',
' offset.xz = vector.xz * time;',
' offset.y = vector.y * time - 0.5 * g * time * time;',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position + translate + offset, 1.0 );',
' vColor = color;',
'}'
].join('\n'),
fragmentShader: [
'varying vec3 vColor;',
'void main() {',
' gl_FragColor = vec4( vColor, 1.0 );',
'}'
].join('\n')
});
var mesh = new THREE.Mesh(geometry, material);
this.model = mesh;
el.setObject3D('mesh', mesh);
el.emit('model-loaded', {format:'mesh', model: mesh});
},
tick: function(time, delta) {
if (this.model === null) { return; }
var mesh = this.model;
mesh.material.uniforms.time.value = (mesh.material.uniforms.time.value + delta / 1000) % 30.0;
}
});
但我有这个错误
[.Offscreen-For-WebGL-0x17d96d74a000] GL错误:GL_INVALID_VALUE:glVertexAttribPointer:size GL_INVALID_VALUE (索引):1 [.Offscreen-For-WebGL-0x17d96d74a000] GL错误:GL_INVALID_OPERATION:glDrawElementsInstancedANGLE:附加到启用的attrib 1:无缓冲区
我是三级低级别职能的新兵。我从aframe开始,但不幸的是,我发现在我的情况下,正常使用这个框架并不足以获得良好的表现。
我的目标是在不同的位置拥有不同大小的多个立方体。有什么建议吗?提前谢谢
使用TheJim解决方案。
答案 0 :(得分:0)
首先,不应重新定义position
。 ShaderMaterial
注入了常见属性,包括position
,您的定义与此相冲突。如果您想自己定义所有内容,请查看RawShaderMaterial
。
其次,请记住,您要为一个立方体定义顶点,索引和法线,然后使用着色器/实例来操纵其余部分。只应将特定于实例的数据定义为InstancedBufferAttribute
s。
看一下这个例子:
var cubeGeo = new THREE.InstancedBufferGeometry().copy(new THREE.BoxBufferGeometry(10, 10, 10));
//cubeGeo.maxInstancedCount = 8;
cubeGeo.addAttribute("cubePos", new THREE.InstancedBufferAttribute(new Float32Array([
25, 25, 25,
25, 25, -25, -25, 25, 25, -25, 25, -25,
25, -25, 25,
25, -25, -25, -25, -25, 25, -25, -25, -25
]), 3, 1));
var vertexShader = [
"precision highp float;",
"",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
"",
"attribute vec3 position;",
"attribute vec3 cubePos;",
"",
"void main() {",
"",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( cubePos + position, 1.0 );",
"",
"}"
].join("\n");
var fragmentShader = [
"precision highp float;",
"",
"void main() {",
"",
" gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);",
"",
"}"
].join("\n");
var mat = new THREE.RawShaderMaterial({
uniforms: {},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true
});
var mesh = new THREE.Mesh(cubeGeo, mat);
scene.add(mesh);
和你一样,我创造了一个立方体(只有一个立方体)。然后我添加名为InstancedBufferAttribute
的{{1}},它将更改多维数据集的位置(cubePos
适用于此示例中的所有顶点)。这类似于您的cubePos
属性。
就拉伸立方体而言,看起来您可能已接近translate
属性。如果您只是给它一个非内置名称,例如position
,它可能会按预期工作。
就个人而言,由于看起来你在两个方向上均匀地拉伸它,我可能只是为每个实例传递一个值,并使用它在两个Y方向上缩放立方体。