当前位置: 首页 > 知识库问答 >
问题:

将数据存储为纹理,以便在实例化几何体的顶点着色器中使用(三个JS/GLSL)

向和歌
2023-03-14

我用的是三。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设置为vec2(1.0,0.0),并更改偏移位置,则不会发生任何更改),而且我不确定如何确保实例可以引用纹理中的正确纹理。

此外,我是否必须规范化数据(0.0-1.0,或0-255,或-1-

谢谢

共有1个答案

南门承教
2023-03-14

你需要对每个实例的纹理计算某种索引。也就是说,您需要一个将由每个实例共享的属性。

如果你的三角形是

[a,b,c]

你的索引应该是

[0,0,0] 

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

attribute float aIndex;

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

vec4 myRes = texture2D( mySampler, myIndex);
 类似资料:
  • 在课程的第二章对Threejs几何体Geometry和BufferGeometry的顶点概念做过比较多的介绍,讲解过顶点位置坐标数据、顶点颜色数据、顶点法线方向向量数据,不过顶点的UV数据没有去讲解,主要是几何体顶点的纹理坐标数据和纹理贴图的映射有关系,所以放在了本章节去讲解。 纹理UV坐标 纹理坐标含义就是一面意思,一张纹理贴图图像的坐标,选择一张图片,比如以图片左下角为坐标原点,右上角为坐标(

  • 我用C SDL2 GLEW Opengl 4.1编程一个小的体素游戏,有点像Minecraft。 我正在尽可能优化体素渲染。 我把世界滑成一块块,而这块块又滑成一块块。 每个块包含16x16x16个块。 现在,如果编辑块(删除/放置块),我将重建完整块和相邻块,并将其与vao和vbo一起上载到图形卡。 现在,为了最小化顶点数据,我必须从cpu传输到gpu,我使用几何体着色器。 首先,这是个好主意吗

  • 我能够使用javascript和three.js库创建一个球体。然而,我有一个图像,我想覆盖在球体的顶部,每当我这样做,球体变成一个黑色的球体,没有图像投射在上面。下面是我如何实现它:var渲染器=new THREE. WebGL渲染器();renderer.set大小(window.inner宽度,window.inner高度);document.body.append(renderer.dom

  • 使用GLE管材和挤出库(http://www.linas.org/gle/)我能够使用OpenGL将2D计数挤出到3D对象中。该库在CPU上完成所有工作,并使用OpenGL即时模式。 我想在GPU上使用几何着色器进行挤压可能会更快,尤其是在渲染大量几何图形时。因为我还没有在OpenGL中使用几何着色器的任何经验,我想知道这是否可能,以及我必须注意什么。您认为将这些计算转移到GPU并提高性能是个好主

  • 我正在尝试制作一个几何体着色器(使用着色器生成器)来简化模型。首先,我试图做一个体素化,但结果不好,我找不到它的错。 在下面的代码中,想法是找到输入三角形的中心,然后使其成为我要创建的框的中心。 我知道这不是世界上最优雅的代码,但先走一步,我需要让它工作...

  • 我正在OpenGL中练习纹理,将定义为白色的简单纹理应用到四边形上。代码编译和运行良好,但四元体的颜色只是黑色,而不是我指定的白色。 我认为这是因为我的片段着色器没有进行正确的采样,就像它从纹理函数返回的数据都是零,因此四边形的纹理变为黑色。我之所以这么想,是因为当我运行程序时,我可以把白色变成清晰的颜色,并稍微移动四边形上的一个顶点,以便看到背景(因为它通常会填充整个曲面)。然后我可以清楚地看到