【问题标题】:Per instance UV texture mapping in Three.js InstancedBufferGeometryThree.js InstancedBufferGeometry 中的每个实例 UV 纹理映射
【发布时间】:2018-07-14 10:40:56
【问题描述】:

我有一个由单个平面组成的 InstancedBufferGeometry:

const plane = new THREE.PlaneBufferGeometry(100, 100, 1, 1);
const geometry = new THREE.InstancedBufferGeometry();
geometry.maxInstancedCount = 100;
geometry.attributes.position = plane.attributes.position;

geometry.index = plane.index;
geometry.attributes.uv = plane.attributes.uv;

geometry.addAttribute( 'offset', new THREE.InstancedBufferAttribute( new Float32Array( offsets ), 3 ) ); // an offset position

我正在为每个平面应用一个纹理,它按预期工作,但是我希望为每个实例应用一个不同的纹理区域,我不确定正确的方法。

目前,我尝试根据单个平面的 uv 结构构建每个实例的 uv:

let uvs = [];

for (let i = 0; i < 100; i++) {
    const tl = [0, 1];
    const tr = [1, 1];
    const bl = [0, 0];
    const br = [1, 0];
    uvs = uvs.concat(tl, tr, bl, br);
}

...

geometry.addAttribute( 'uv', new THREE.InstancedBufferAttribute( new Float32Array( uvs ), 2) );

当我这样做时,我没有任何错误,但每个实例都只是一种颜色(所有实例都是相同的颜色)。我尝试更改实例大小以及每个属性的网格(我不完全理解,努力在文档中找到一个好的解释)。

我觉得我很接近了,但我错过了一些东西,所以在正确的方向上的一点会很棒!

(供参考,这是我的着色器):

const vertexShader = `
    precision mediump float;

    uniform vec3 color;
    uniform sampler2D tPositions;

    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;

    attribute vec2 uv;
    attribute vec2 dataUv;
    attribute vec3 position;
    attribute vec3 offset;
    attribute vec3 particlePosition;
    attribute vec4 orientationStart;
    attribute vec4 orientationEnd;

    varying vec3 vPosition;
    varying vec3 vColor;
    varying vec2 vUv;

    void main(){
        vPosition = position;
        vec4 orientation = normalize( orientationStart );
        vec3 vcV = cross( orientation.xyz, vPosition );
        vPosition = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + vPosition );

        vec4 data = texture2D( tPositions, vec2(dataUv.x, 0.0));
        vec3 particlePosition = (data.xyz - 0.5) * 1000.0;
        vUv = uv;

        vColor = data.xyz;

        gl_Position = projectionMatrix * modelViewMatrix * vec4(  position + particlePosition + offset, 1.0 );
    }
`;

const fragmentShader = `
    precision mediump float;

    uniform sampler2D map;

    varying vec3 vPosition;
    varying vec3 vColor;
    varying vec2 vUv;

    void main() {
        vec3 color = texture2D(map, vUv).xyz;

        gl_FragColor = vec4(color, 1.0);
    }
`;

【问题讨论】:

  • 您可以尝试为每个实例添加一个纹理变换矩阵。

标签: three.js glsl webgl uv-mapping geometry-instancing


【解决方案1】:

由于我的所有实例都需要采用相同大小的矩形区域,但要进行偏移(如精灵表),我为每个实例添加了 UV 偏移和 UV 比例属性,并使用它来定义地图的哪个区域使用:

const uvOffsets = [];
for (let i = 0; i < INSTANCES; i++) {
    const u = i % textureWidthHeight;
    const v = ~~ (i / textureWidthHeight);
    uvOffsets.push(u, v);
}

...

geometry.attributes.uv = plane.attributes.uv;
geometry.addAttribute( 'uvOffsets', new THREE.InstancedBufferAttribute( new Float32Array( uvOffsets ), 2 ) );

uniforms: {
    ...
    uUvScale: { value: 1 / textureWidthHeight }
}

在片段着色器中:

void main() {
    vec4 color = texture2D(map, (vUv * uUvScale) + (vUvOffsets * uUvScale));
    gl_FragColor = vec4(1.0, 1.0, 1.0, color.a);
}

\o/

【讨论】:

    猜你喜欢
    • 2014-12-06
    • 2021-02-05
    • 2013-11-22
    • 2017-12-21
    • 1970-01-01
    • 2018-10-24
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多