如何为三个 js 实例对象设置颜色?
How do I set colors for three js instanced objects?
我有一个框架组件,它利用三个 js 实例有效地渲染大量球体。根据 https://github.com/mrdoob/three.js/blob/master/examples/webgl_instancing_scatter.html 等三个 js 库中的示例,我应该能够分别为每个实例化渲染设置颜色。我以为我已经按照这个例子做了,但是我的实例颜色没有生效。
AFRAME.registerComponent('spheres', {
schema: {
count: {type: 'number'},
radius: {type: 'number'},
scale: {type: 'number'},
colors: {type: 'array'},
positions: {type: 'array'}
},
init: function() {
const {count, radius, scale, colors, positions} = this.data;
const material = new THREE.MeshNormalMaterial();
const geometry = new THREE.SphereBufferGeometry( radius, 3, 2 );
const instancedGeometry = new THREE.InstancedBufferGeometry().copy(geometry);
var instanceColors = [];
for ( var i = 0; i < count; i ++ ) {
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
}
instancedGeometry.setAttribute("instanceColor", new THREE.InstancedBufferAttribute( new Float32Array( instanceColors ), 3 ))
instancedGeometry.computeVertexNormals();
material.vertexColors = true;
const matrix = new THREE.Matrix4();
const mesh = new THREE.InstancedMesh( instancedGeometry, material, count );
for ( var i = 0; i < count; i ++ ) {
this.setMatrix(positions[i], scale)( matrix );
mesh.setMatrixAt( i, matrix );
}
this.el.object3D.add( mesh );
},
我做错了什么?
您是否尝试使用与示例中相同的实际属性 'color'(即
blossomGeometry.setAttribute( 'color', new THREE.InstancedBufferAttribute( color, 3 ) );
因为我觉得属性的名字是'color'.
很重要
根据@prisoner849 示例,它可以与以下内容一起使用。我不得不使用 MeshPhongMaterial 而不是 MeshNormalMaterial。不太清楚为什么。也不确定为什么我需要对颜色使用 InstancedBufferAttribute 和 BufferAttribute。也许 @prisoner849 可以跟进细节。这个解决方案有点难看,希望三个能尽快提供一种更简洁的方法来调整实例化颜色,或者也许已经有更好的方法,我只是不知道
AFRAME.registerComponent('spheres', {
schema: {
count: {type: 'number'},
radius: {type: 'number'},
scale: {type: 'number'},
colors: {type: 'array'},
positions: {type: 'array'}
},
init: function() {
const {count, radius, scale, colors, positions} = this.data;
var geometry = new THREE.SphereBufferGeometry(radius);
var material = new THREE.MeshPhongMaterial({ flatShading: true });
var colorParsChunk = [
'attribute vec3 instanceColor;',
'varying vec3 vInstanceColor;',
'#include <common>'
].join( '\n' );
var instanceColorChunk = [
'#include <begin_vertex>',
'\tvInstanceColor = instanceColor;'
].join( '\n' );
var fragmentParsChunk = [
'varying vec3 vInstanceColor;',
'#include <common>'
].join( '\n' );
var colorChunk = [
'vec4 diffuseColor = vec4( diffuse * vInstanceColor, opacity );'
].join( '\n' );
material.onBeforeCompile = function ( shader ) {
shader.vertexShader = shader.vertexShader
.replace( '#include <common>', colorParsChunk )
.replace( '#include <begin_vertex>', instanceColorChunk );
shader.fragmentShader = shader.fragmentShader
.replace( '#include <common>', fragmentParsChunk )
.replace( 'vec4 diffuseColor = vec4( diffuse, opacity );', colorChunk );
};
var instanceColors = [];
for ( var i = 0; i < count; i ++ ) {
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
}
const matrix = new THREE.Matrix4();
const mesh = new THREE.InstancedMesh( geometry, material, count );
var instanceColorsBase = new Float32Array(instanceColors.length);
instanceColorsBase.set(instanceColors);
geometry.setAttribute( 'instanceColor', new THREE.InstancedBufferAttribute( new Float32Array( instanceColors ), 3 ) );
geometry.setAttribute( 'instanceColorBase', new THREE.BufferAttribute(new Float32Array( instanceColorsBase ), 3 ) );
for ( var i = 0; i < count; i ++ ) {
this.setMatrix(positions[i], scale)( matrix );
mesh.setMatrixAt( i, matrix );
}
this.el.object3D.add( mesh );
},
setMatrix: function( pos, scaler ) {
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 = pos[0];
position.y = pos[1];
position.z = pos[2];
rotation.x = 0;
rotation.y = 0;
rotation.z = 0;
quaternion.setFromEuler( rotation );
scale.x = scale.y = scale.z = scaler;
matrix.compose( position, quaternion, scale );
};
}
});
我有一个框架组件,它利用三个 js 实例有效地渲染大量球体。根据 https://github.com/mrdoob/three.js/blob/master/examples/webgl_instancing_scatter.html 等三个 js 库中的示例,我应该能够分别为每个实例化渲染设置颜色。我以为我已经按照这个例子做了,但是我的实例颜色没有生效。
AFRAME.registerComponent('spheres', {
schema: {
count: {type: 'number'},
radius: {type: 'number'},
scale: {type: 'number'},
colors: {type: 'array'},
positions: {type: 'array'}
},
init: function() {
const {count, radius, scale, colors, positions} = this.data;
const material = new THREE.MeshNormalMaterial();
const geometry = new THREE.SphereBufferGeometry( radius, 3, 2 );
const instancedGeometry = new THREE.InstancedBufferGeometry().copy(geometry);
var instanceColors = [];
for ( var i = 0; i < count; i ++ ) {
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
}
instancedGeometry.setAttribute("instanceColor", new THREE.InstancedBufferAttribute( new Float32Array( instanceColors ), 3 ))
instancedGeometry.computeVertexNormals();
material.vertexColors = true;
const matrix = new THREE.Matrix4();
const mesh = new THREE.InstancedMesh( instancedGeometry, material, count );
for ( var i = 0; i < count; i ++ ) {
this.setMatrix(positions[i], scale)( matrix );
mesh.setMatrixAt( i, matrix );
}
this.el.object3D.add( mesh );
},
我做错了什么?
您是否尝试使用与示例中相同的实际属性 'color'(即
blossomGeometry.setAttribute( 'color', new THREE.InstancedBufferAttribute( color, 3 ) );
因为我觉得属性的名字是'color'.
很重要根据@prisoner849 示例,它可以与以下内容一起使用。我不得不使用 MeshPhongMaterial 而不是 MeshNormalMaterial。不太清楚为什么。也不确定为什么我需要对颜色使用 InstancedBufferAttribute 和 BufferAttribute。也许 @prisoner849 可以跟进细节。这个解决方案有点难看,希望三个能尽快提供一种更简洁的方法来调整实例化颜色,或者也许已经有更好的方法,我只是不知道
AFRAME.registerComponent('spheres', {
schema: {
count: {type: 'number'},
radius: {type: 'number'},
scale: {type: 'number'},
colors: {type: 'array'},
positions: {type: 'array'}
},
init: function() {
const {count, radius, scale, colors, positions} = this.data;
var geometry = new THREE.SphereBufferGeometry(radius);
var material = new THREE.MeshPhongMaterial({ flatShading: true });
var colorParsChunk = [
'attribute vec3 instanceColor;',
'varying vec3 vInstanceColor;',
'#include <common>'
].join( '\n' );
var instanceColorChunk = [
'#include <begin_vertex>',
'\tvInstanceColor = instanceColor;'
].join( '\n' );
var fragmentParsChunk = [
'varying vec3 vInstanceColor;',
'#include <common>'
].join( '\n' );
var colorChunk = [
'vec4 diffuseColor = vec4( diffuse * vInstanceColor, opacity );'
].join( '\n' );
material.onBeforeCompile = function ( shader ) {
shader.vertexShader = shader.vertexShader
.replace( '#include <common>', colorParsChunk )
.replace( '#include <begin_vertex>', instanceColorChunk );
shader.fragmentShader = shader.fragmentShader
.replace( '#include <common>', fragmentParsChunk )
.replace( 'vec4 diffuseColor = vec4( diffuse, opacity );', colorChunk );
};
var instanceColors = [];
for ( var i = 0; i < count; i ++ ) {
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
instanceColors.push( Math.random() );
}
const matrix = new THREE.Matrix4();
const mesh = new THREE.InstancedMesh( geometry, material, count );
var instanceColorsBase = new Float32Array(instanceColors.length);
instanceColorsBase.set(instanceColors);
geometry.setAttribute( 'instanceColor', new THREE.InstancedBufferAttribute( new Float32Array( instanceColors ), 3 ) );
geometry.setAttribute( 'instanceColorBase', new THREE.BufferAttribute(new Float32Array( instanceColorsBase ), 3 ) );
for ( var i = 0; i < count; i ++ ) {
this.setMatrix(positions[i], scale)( matrix );
mesh.setMatrixAt( i, matrix );
}
this.el.object3D.add( mesh );
},
setMatrix: function( pos, scaler ) {
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 = pos[0];
position.y = pos[1];
position.z = pos[2];
rotation.x = 0;
rotation.y = 0;
rotation.z = 0;
quaternion.setFromEuler( rotation );
scale.x = scale.y = scale.z = scaler;
matrix.compose( position, quaternion, scale );
};
}
});