【发布时间】:2020-11-23 22:42:18
【问题描述】:
我认为显示代码示例是最好的。因此,我创建了一个显示问题的小示例。 我想创建一个缓冲区几何,其中每个组都有自己的着色器。虽然我总是在材质数组中创建一个新实例,但我不能独立使用各个着色器的制服。我在阵列中一个着色器的统一中调整的内容总是对材质阵列中的所有其他着色器具有相同的效果。 在我问之前,我尝试通过研究来推进,但在这里我已经到了无法再进一步的地步。有谁知道为什么材质数组中的各个着色器相互依赖以及如何避免这种情况?
var camera, controls, scene, renderer, container;
var PI = Math.PI;
var clock = new THREE.Clock();
var plane;
var MAX_Planes = 100;
var velocity = [];
var geometry;
var test1, test2, test3;
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
//renderer.sortObjects = true;
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);
//---------------shaders---------------
var BasicVertexShader = `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
var BasicFragmentShader = `
void main() {
gl_FragColor = vec4(vec3(1.0, 1.0, 0.8), 1.0);
}`;
var VertexShader = `
varying vec3 sPos;
uniform vec3 pos;
uniform float stretch;
void main() {
float rotation = 0.0;
sPos = position;
vec3 scale;
scale.x = 1.0*stretch;
scale.y = 1.0*stretch;
scale.z = 1.0*stretch;
vec3 alignedPosition = vec3(position.x * scale.x, position.y * scale.y, 0.0);
vec3 rotatedPosition;
rotatedPosition.x = cos(rotation) * alignedPosition.x - sin(rotation) * alignedPosition.y;
rotatedPosition.y = sin(rotation) * alignedPosition.x + cos(rotation) * alignedPosition.y;
rotatedPosition.z = alignedPosition.z;
vec4 finalPosition;
finalPosition = modelViewMatrix * vec4( 0, 0, 0, 1.0 );
finalPosition.xyz += rotatedPosition;
finalPosition = projectionMatrix * finalPosition;
gl_Position = finalPosition;
// gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
var FragmentShader = `
varying vec3 sPos;
void main() {
vec3 nDistVec = normalize(sPos);
float dist = pow(sPos.x, 2.0) + pow(sPos.y, 2.0);
float magnitude = 1.0/dist * pow(4.0, 2.0);
// gl_FragColor = vec4(vec3(1.0, 1.0, 0.8), 1.0) * magnitude;
gl_FragColor = vec4(vec3(1.0, 1.0, 0.8), 1.0);
}`;
var uniform = {
stretch: {type: 'f', value: 1.0},
pos: { value: new THREE.Vector3(0,0,0) },
}
Shader = new THREE.ShaderMaterial( {
uniforms: uniform,
vertexShader: VertexShader,
fragmentShader: FragmentShader,
transparent: true,
depthTest: false,
depthWrite: false
});
//just for tests
var Shade = new THREE.ShaderMaterial( {
vertexShader: BasicVertexShader,
fragmentShader: BasicFragmentShader,
side:THREE.DoubleSide
});
//-------------------------------------------------
//create a plane: points, normals, uv
const vertices = [
{ pos: [-10, -10, 0], norm: [ 0, 0, 1], uv: [0, 1], },
{ pos: [ 10, -10, 0], norm: [ 0, 0, 1], uv: [1, 1], },
{ pos: [-10, 10, 0], norm: [ 0, 0, 1], uv: [0, 0], },
{ pos: [ 10, 10, 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 );
materials.push(Shader);
}
plane = new THREE.Mesh(geometry, materials);
scene.add(plane);
plane.material[0].uniforms.stretch.value = 2;
plane.material[1].uniforms.stretch.value = 3;
test1 = Object.keys(plane.material);
test2 = plane.material[0].uniforms.stretch.value; //why this returns 3 and not 2?
test3 = plane.material[1].uniforms.stretch.value;
//the goal is that each group has its own Shader without effecting the other ones
//----------------------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----------
function render() {
document.getElementById("demo1").innerHTML = test1;
document.getElementById("demo2").innerHTML = test2;
document.getElementById("demo3").innerHTML = test3;
for(var i = 0; i < MAX_Planes; i++){
for(var j = 0; j < 4; j++){
plane.geometry.attributes.position.array[i*12+3*j] = plane.geometry.attributes.position.array[i*12+3*j] + velocity[i].x;
plane.geometry.attributes.position.array[i*12+3*j+1] = plane.geometry.attributes.position.array[i*12+3*j+1] + velocity[i].y;
plane.geometry.attributes.position.array[i*12+3*j+2] = plane.geometry.attributes.position.array[i*12+3*j+2] + velocity[i].z;
}
}
plane.geometry.attributes.position.needsUpdate = true;
camera.updateMatrixWorld();
camera.updateProjectionMatrix();
renderer.render(scene, camera);
}//-------End render----------
【问题讨论】:
标签: three.js shader buffer-geometry