将数据存储为纹理以在实例化几何体的顶点着色器中使用(三个JS/GLSL) [英] Storing data as a texture for use in Vertex Shader for Instanced Geometry (THREE JS / GLSL)

查看:18
本文介绍了将数据存储为纹理以在实例化几何体的顶点着色器中使用(三个JS/GLSL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是THREE.InstancedBufferGeometry,我希望访问已编码到纹理中的顶点着色器中的数据。

我要做的是为每个实例创建一个具有一个像素的数据纹理,它将存储每个实例的位置数据(然后在稍后的阶段,我可以使用带有流场的模拟来更新纹理以设置位置的动画)。

我正在努力从顶点着色器中的纹理访问数据。

const INSTANCES_COUNT = 5000;

// FOR EVERY INSTANCE, GIVE IT A RANDOM X, Y, Z  OFFSET, AND SAVE IT IN DATA TEXTURE
const data = new Uint8Array(4 * INSTANCES_COUNT);
for (let i = 0; i < INSTANCES_COUNT; i++) {
    const stride = i * 4;
    data[stride] = (Math.random() - 0.5);
    data[stride + 1] = (Math.random() - 0.5);
    data[stride + 2] = (Math.random() - 0.5);
    data[stride + 3] = 0.0;
}

const offsetTexture = new THREE.DataTexture( data, INSTANCES, 1, THREE.RGBAFormat, THREE.FloatType );
offsetTexture.minFilter = THREE.NearestFilter;
offsetTexture.magFilter = THREE.NearestFilter;
offsetTexture.generateMipmaps = false;
offsetTexture.needsUpdate = true;

// CREATE MY INSTANCED GEOMETRY
const geometry = new THREE.InstancedBufferGeometry();
geometry.maxInstancedCount = INSTANCES_COUNT;
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute([5, -5, 0, -5, 5, 0, 0, 0, 5], 3 )); // SIMPLE TRIANGLE


const vertexShader = `
    precision highp float;

    uniform vec3 color;
    uniform sampler2D offsetTexture;

    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;

    attribute vec3 position;

    varying vec3 vPosition;
    varying vec3 vColor;


    void main(){
        vPosition = position;

        vec4 orientation = vec4(.0, .0, .0, .0);
        vec3 vcV = cross( orientation.xyz, vPosition );
        vPosition = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + vPosition );

        vec2 uv = position.xy;
        vec4 data = texture2D( offsetTexture, uv );
        vec3 particlePosition = data.xyz * 1000.0;

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

const fragmentShader = `
    precision highp float;
    varying vec3 vColor;

    void main() {
        gl_FragColor = vec4(vColor, 1.0);
    }
`;

const uniforms = {
    size: { value: 1.0 },
    color: {
        type: 'c',
        value: new THREE.Color(0x3db230),
    },
    offsetTexture: {
        type: 't',
        value: offsetTexture,
    },
};

// CREATE MY MATERIAL
const material = new THREE.RawShaderMaterial({
    uniforms,
    vertexShader,
    fragmentShader,
    side: THREE.DoubleSide,
    transparent: false,
});

scene.add(new THREE.Mesh(geometry, material));

目前,似乎无法在顶点着色器中访问图像中的数据(例如,如果我只是将VUV设置为ve2(1.0,0.0),然后更改偏移位置,则不会发生任何变化),而且我也不确定如何确保实例可以引用纹理中的正确纹理元素。

因此,我的两个问题是: 1)如何正确设置数据图像纹理,并在顶点着色器中访问该数据 2)如何正确引用为每个特定实例存储数据的纹理元素(例如,实例1000应使用ve2(1000,1)等

另外,我是否必须对数据(0.0-1.0、0-255或-1-10+1)进行标准化

谢谢

推荐答案

您需要为每个实例的纹理计算某种索引。 这意味着您需要一个将由每个实例共享的属性。

如果您的三角形

[a,b,c]

您的索引应该是

[0,0,0] 

假设您有1024个实例和1024x1像素纹理。

attribute float aIndex;

vec2 myIndex = ((aIndex + 0.5)/1024.,1.);

vec4 myRes = texture2D( mySampler, myIndex);

这篇关于将数据存储为纹理以在实例化几何体的顶点着色器中使用(三个JS/GLSL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆