three.js /从着色器中读取mat4类型的THREE.InstancedBufferAttribute

时间:2016-10-18 06:01:39

标签: three.js webgl

我正在尝试使用THREE.InstancedBufferAttribute将matrix4发送到顶点着色器,但我无法弄清楚如何。

这样可行:

JS

// convert the geometry to an InstancedBufferGeometry
var geometry = new THREE.InstancedBufferGeometry().fromGeometry(geometry);

(...)

// transforms
var transformsCol0 = new THREE.InstancedBufferAttribute(new Float32Array(instanceCount * 4), 4, 1);
var transformsCol1 = new THREE.InstancedBufferAttribute(new Float32Array(instanceCount * 4), 4, 1);
var transformsCol2 = new THREE.InstancedBufferAttribute(new Float32Array(instanceCount * 4), 4, 1);
var transformsCol3 = new THREE.InstancedBufferAttribute(new Float32Array(instanceCount * 4), 4, 1);

// declare matrices only once outside the loop
var workingMatrix = new THREE.Matrix4();
var transformMatrix = new THREE.Matrix4();

for (var i = 0; i < instanceCount; i++) {
    var instance = instances[i];

    // transforms: translation
    transformMatrix.makeTranslation(instance.position.x, instance.position.y, instance.position.z);

    // transforms: rotation: X
    workingMatrix.makeRotationX(instance.rotation.x);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    // transforms: rotation: Y
    workingMatrix.makeRotationY(instance.rotation.y);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    // transforms: rotation: Z
    workingMatrix.makeRotationZ(instance.rotation.z);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    // transforms: scale
    workingMatrix.makeScale(instance.scale.x, instance.scale.y, instance.scale.z);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    transformsCol0.setXYZW(i, transformMatrix.elements[0], transformMatrix.elements[1], transformMatrix.elements[2], transformMatrix.elements[3]);
    transformsCol1.setXYZW(i, transformMatrix.elements[4], transformMatrix.elements[5], transformMatrix.elements[6], transformMatrix.elements[7]);
    transformsCol2.setXYZW(i, transformMatrix.elements[8], transformMatrix.elements[9], transformMatrix.elements[10], transformMatrix.elements[11]);
    transformsCol3.setXYZW(i, transformMatrix.elements[12], transformMatrix.elements[13], transformMatrix.elements[14], transformMatrix.elements[15]);
}

geometry.addAttribute('transformsCol0', transformsCol0);
geometry.addAttribute('transformsCol1', transformsCol1);
geometry.addAttribute('transformsCol2', transformsCol2);
geometry.addAttribute('transformsCol3', transformsCol3);

着色

precision highp float;

attribute vec4 color;

attribute vec4 transformsCol0;
attribute vec4 transformsCol1;
attribute vec4 transformsCol2;
attribute vec4 transformsCol3;

varying vec4 vColor;

void main() {
    vColor = color;

    mat4 transforms = mat4(
        transformsCol0,
        transformsCol1,
        transformsCol2,
        transformsCol3
    );


    gl_Position = projectionMatrix * modelViewMatrix * transforms * vec4( position, 1.0 );
}

然而,这不会:

JS

// convert the geometry to an InstancedBufferGeometry
var geometry = new THREE.InstancedBufferGeometry().fromGeometry(geometry);

(...)

// transforms
var transforms = new THREE.InstancedBufferAttribute(new Float32Array(instanceCount * 16), 16, 1);

// declare matrices only once outside the loop
var workingMatrix = new THREE.Matrix4();
var transformMatrix = new THREE.Matrix4();

for (var i = 0; i < instanceCount; i++) {
    var instance = instances[i];

    // transforms: translation
    transformMatrix.makeTranslation(instance.position.x, instance.position.y, instance.position.z);

    // transforms: rotation: X
    workingMatrix.makeRotationX(instance.rotation.x);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    // transforms: rotation: Y
    workingMatrix.makeRotationY(instance.rotation.y);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    // transforms: rotation: Z
    workingMatrix.makeRotationZ(instance.rotation.z);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    // transforms: scale
    workingMatrix.makeScale(instance.scale.x, instance.scale.y, instance.scale.z);
    transformMatrix.multiply(workingMatrix);
    workingMatrix.identity();

    transforms.set(transformMatrix.elements, i);
}

geometry.addAttribute('transforms', transforms);

着色

attribute vec4 color;
attribute mat4 transforms;

varying vec4 vColor;

void main() {
    vColor = color;

    gl_Position = projectionMatrix * modelViewMatrix * transforms * vec4( position, 1.0 );
}

当我尝试运行上面的代码时,我在浏览器控制台中出现此错误

[.Offscreen-For-WebGL-0x7ff054396800]GL ERROR :GL_INVALID_VALUE : glVertexAttribPointer: size GL_INVALID_VALUE

我在github中找不到任何相关问题,但我认为此示例的创建者由于this commented-out code而面临同样的问题

1 个答案:

答案 0 :(得分:1)

每个通用顶点属性的组件数必须为1,2,3或4.您尝试传递16个组件。

参考:https://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttribPointer.xml

three.js r.81