0

I am using THREE.PointCloud for better performance, I have to animate 100K objects. But the problem is I couldn't find a way to set different texture for particles. How to use uniforms with different texture in this code.

Can I pass shaderMaterial as array which has equal number as particles with different textures ?

Or in fragment shader how can I pass different texture ?

     var uniforms = {
                    amplitude: {
                        type: "f",
                        value: 1.0
                    },
                    color: {
                        type: "c",
                        value: new THREE.Color("#fff")
                    },
                    texture: {
                        type: "t",
                        value: new THREE.TextureLoader().load("./images/shape1.png") 
// I have to set different shapes randomly
                    }
                };

            var vertexShader = [
                        "uniform float amplitude;",
                        "attribute float size;",
                        "attribute vec3 customColor;",
                        "varying vec3 vColor;",
                        "void main() {",
                            "vColor = customColor;",
                            "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
                            "gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );",
                            " gl_Position = projectionMatrix * mvPosition;",
                        "}"
                        ].join("\n"),

                    fragmentShader = [
                        "uniform vec3 color;",
                        "uniform sampler2D texture;",
                        "varying vec3 vColor;",
                        "void main() {",
                            "gl_FragColor = vec4( color * vColor, 1.0 );",
                            "gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );",
                        "}"
                    ].join("\n");


    var shaderMaterial = new THREE.ShaderMaterial({
                    uniforms: uniforms,
                    //attributes: attributes,
                    vertexShader: vertexShader,
                    fragmentShader: fragmentShader,
                    blending: THREE.AdditiveBlending,
                    depthTest: true,
                    transparent: false
                });


                // particles.colors = colors;

                var particles = new THREE.BufferGeometry();
                particles.addAttribute('position', new THREE.BufferAttribute(positions, 3));
                particles.addAttribute('customColor', new THREE.BufferAttribute(colors, 3));
                particles.addAttribute('size', new THREE.BufferAttribute(sizes, 1));



                particleSystem = new THREE.PointCloud(particles, shaderMaterial); // can i pass shaderMaterial as array which has equal number as particles with different textures 
Sarath
  • 9,030
  • 11
  • 51
  • 84
  • You're limited by the number of textures that you can address in a shader. I'm not entirely sure if I understand what you are trying to achieve but I believe you might be interested in something called a "texture atlas"z – pailhead Oct 12 '16 at 06:34
  • If you try to assign an equal number or shsder mat risks you are going to end up wih 100k drawcalls which is. It optimized at all. You could write a shader slightly differently and query for max texture units. Based on this number you could batch a few of these points and have each index into a different texture. The solution is probably somewhere in between, read one atlas per call, break it up into a few drawcalls. – pailhead Oct 12 '16 at 06:39

1 Answers1

-1

I think here's a solution to your problem. I tried it and it worked. Three.js - Using multiple textures in a single PointCloud

You can see a live demo here by jigglebilly: http://jsfiddle.net/jigglebilly/drmvz5co/.

Also, the new version of Three.js doesn't support attributes in ShaderMaterial. We'll have to use geometry.addAttribute instead. Here's the code to define texIndex:

var vIndex = new Float32Array( vertices.length );
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
    vIndex[i] = Math.random()*getTextures().length;
}
geometry.addAttribute( 'texIndex', new THREE.BufferAttribute( vIndex, 1 ) );
Yan Wu
  • 79
  • 1
  • 5