自定义bufferGeometry与纹理



我不久前对粒子系统进行了测试。因为我现在又在努力了。我想使用纹理,但我只得到黑色粒子。我认为问题在于紫外线坐标,但我不知道在这种情况下如何使用它。我已经在代码中描述了我怀疑存在问题的地方。在这种情况下,我如何访问着色器中的纹理坐标

var camera, controls, scene, renderer, container;
var PI = Math.PI;
var clock = new THREE.Clock(); 
var plane;
var MAX_Planes = 2000;
var velocity = [];
var geometry;

function init() {
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true} );
renderer.setPixelRatio( window.devicePixelRatio ); 
renderer.shadowMap.enabled = true; 
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

container = document.getElementById('container');
renderer.setSize(container.clientWidth, container.clientHeight);
container.appendChild( renderer.domElement );
var aspect = container.clientWidth / container.clientHeight; 
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );

camera = new THREE.PerspectiveCamera( 45, container.clientWidth / container.clientHeight, 1, 100000 );
camera.position.set(0, 0, 4000);
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = true;
controls.enabled = true;
controls.target.set(0, 0, 0);

//---------------shader---------------  
var VertexShader = `
varying vec3 vUv;
uniform vec3 pos;

void main() {
vUv = uv;
vec4 finalPosition;
finalPosition = modelViewMatrix * vec4( pos, 1.0 );
finalPosition.xyz += vec3(position.x, position.y, 0.0);
finalPosition = projectionMatrix * finalPosition;
gl_Position = finalPosition;
}`;
var FragmentShader = `
varying vec3 vUv;
uniform sampler2D tDiffuse;
void main() {
gl_FragColor = vec4(texture2D(tDiffuse, vUv).rgb, 1.);
//gl_FragColor = vec4(1.0, 1.0, 0.8, 1.0); //just for testing
}`;
var loader = new THREE.TextureLoader();
var texture = loader.load( 'textures/test.jpg' ); //the texture is loaded correctly. I tested that with a box

var uniform = { 
tDiffuse: {value: texture}, 
pos: { value: new THREE.Vector3(0,0,0) },
} 
var material = new THREE.ShaderMaterial( {                  
uniforms: uniform,                  
vertexShader: VertexShader,
fragmentShader: FragmentShader, 
transparent: true,
depthTest: false,   
depthWrite: false
}); 

//-------------------------------------------------
//create a plane: points, normals, uv
const vertices = [
{ pos: [-20, -20,  0], norm: [ 0,  0,  1], uv: [0, 1], },
{ pos: [ 20, -20,  0], norm: [ 0,  0,  1], uv: [1, 1], },
{ pos: [-20,  20,  0], norm: [ 0,  0,  1], uv: [0, 0], },
{ pos: [ 20,  20,  0], norm: [ 0,  0,  1], uv: [1, 0], },
];
const numVertices = vertices.length;
const positionNumComponents = 3;
const normalNumComponents = 3;
const uvNumComponents = 2;
//arrays for buffergeometry
const positions = new Float32Array(numVertices * positionNumComponents * MAX_Planes);
const normals = new Float32Array(numVertices * normalNumComponents * MAX_Planes);
const uvs = new Float32Array(numVertices * uvNumComponents * MAX_Planes);

//fill arrays with vertices
var posPointer = 0;
var nrmPointer = 0;
var uvPointer = 0;

for(var i = 0; i <= MAX_Planes; i++) {
var posNdx = 0;
var nrmNdx = 0;
var uvNdx = 0;
for (const vertex of vertices) {
positions.set(vertex.pos, posNdx + posPointer);
normals.set(vertex.norm, nrmNdx + nrmPointer);
uvs.set(vertex.uv, uvNdx + uvPointer);
posNdx += positionNumComponents;
nrmNdx += normalNumComponents;
uvNdx += uvNumComponents;
}
posPointer = i * posNdx;
nrmPointer = i * nrmNdx;
uvPointer = i * uvNdx;
}
//create buffergeometry and assign the attribut arrays
geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, positionNumComponents));
geometry.setAttribute('normal', new THREE.BufferAttribute(normals, normalNumComponents));
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, uvNumComponents));
var ndx = 0;
var indices = [];
//instead 6 vertices for the both triangles of a plane i used 4, so reindication is neccessary
for(var i = 0; i < MAX_Planes; i++){
indices.push(ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3);
ndx += 4;
}
geometry.setIndex(indices);

var materials = [];
geometry.clearGroups(); 
for(var i = 0; i < MAX_Planes; i++){
geometry.addGroup( 6*i, 6*(i+1), i );
materials.push(material.clone());   
}
plane = new THREE.Mesh(geometry, materials);
scene.add(plane); 

//----------------------velocity---------------------------

for(var i = 0; i < MAX_Planes; i++){
velocity[i] = new THREE.Vector3(
Math.random()*2-1,
Math.random()*2-1,
Math.random()*2-1);
}   

}//-------End init----------

function animate() {
requestAnimationFrame( animate );  
render();

}//-------End animate----------
var loop = 0;
function render() {
loop = loop + 0.5;
for(var i = 0; i < MAX_Planes; i++){

var pos = new THREE.Vector3(0, 0, 0);

pos.x += velocity[i].x*loop;
pos.y += velocity[i].y*loop;
pos.z += velocity[i].z*loop;

plane.material[i].uniforms.pos.value = pos;
}
plane.geometry.attributes.position.needsUpdate = true;
plane.geometry.attributes.uv.needsUpdate = true;
camera.updateMatrixWorld();
camera.updateProjectionMatrix(); 
renderer.render(scene, camera); 

}//-------End render----------

我最初的设想是错误的。我怀疑现在的问题在于重组。下面这行我看到了纹理

plane = new THREE.Mesh(geometry, material);

但这对我来说没有用;缓冲器阵列内的一个平面";应该有自己的材料,为此我需要分组,但显然我做错了什么,因为我看不到";材料";阵列

ah,问题是在克隆材质时没有克隆纹理。只有当我纯粹使用没有纹理的着色器代码时,克隆材质才有效。如果我想拥有纹理,我必须在for循环中每次实例化材质