Texture atlas offset/repeat works for meshes but is ignored for point system particles

前端 未结 1 887
别那么骄傲
别那么骄傲 2020-12-17 07:17

I am using a texture atlas to hold a sequence of images. When mapping to a mesh with MeshLambertMaterial, using Texture.offset and Texture.re

相关标签:
1条回答
  • 2020-12-17 07:54

    THREE.PointCloudMaterial has been renamed THREE.PointsMaterial.

    THREE.PointCloud has been renamed THREE.Points.


    You want to use a sprite sheet with your point cloud.

    Instead of using PointsMaterial with your Points, you can create a custom ShaderMaterial instead.

    The custom ShaderMaterial can access your sprite sheet and use a different sub-image for each particle.

    To do so, use a shader like this one:

    <script type="x-shader/x-vertex" id="vertexshader">
    
    attribute vec2 offset;
    
    varying vec2 vOffset;
    
    void main() {
    
        vOffset = offset;
    
        gl_PointSize = 25.0;
    
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    
    }
    
    </script>
    
    <script type="x-shader/x-fragment" id="fragmentshader">
    
    uniform sampler2D texture;
    uniform vec2 repeat;
    
    varying vec2 vOffset;
    
    void main() {
    
        vec2 uv = vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y );
    
        vec4 tex = texture2D( texture, uv * repeat + vOffset );
    
        if ( tex.a < 0.5 ) discard;
    
        gl_FragColor = tex;
    
    }
    
    </script>
    

    Set your BufferGeometry like so:

    // vertices
    var geometry = new THREE.SphereGeometry( 100, 16, 12 );
    geometry.mergeVertices(); // to remove duplicate vertices at the poles
    var vertices = geometry.vertices;
    
    // geometry
    geometry = new THREE.BufferGeometry();
    
    // attributes
    numVertices = vertices.length;
    var positions = new Float32Array( numVertices * 3 ); // 3 coordinates per point
    var offsets = new Float32Array( numVertices * 2 ); // 2 coordinates per point
    
    geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
    geometry.addAttribute( 'offset', new THREE.BufferAttribute( offsets, 2 ) );
    
    // populate positions
    geometry.attributes.position.copyVector3sArray( vertices );
    
    // populate offsets
    var offset = new THREE.Vector2();
    
    for ( var i = 0, index = 0, l = numVertices; i < l; i ++, index += 2 ) {
    
        offset.set( THREE.Math.randInt( 1, 3 ), THREE.Math.randInt( 2, 3 ) ).multiplyScalar( 0.25 ); // sprite sheet: 4 rows x 4 cols
    
        offsets[ index ] = offset.x;
        offsets[ index + 1 ] = offset.y;
    
    }
    

    And your ShaderMaterial like so:

    // uniforms
    uniforms = {
    
        texture:    { value: texture },
        repeat:     { value: new THREE.Vector2( 0.25, 0.25 ) }
    
    };
    
    // material
    var material = new THREE.ShaderMaterial( {
    
        uniforms:       uniforms,
        vertexShader:   document.getElementById( 'vertexshader' ).textContent,
        fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
        transparent:    true
    
    } );
    
    // point cloud
    pointCloud = new THREE.Points( geometry, material );
    
    scene.add( pointCloud );
    

    fiddle: http://jsfiddle.net/myy7x4zd/10/

    three.js r.84

    0 讨论(0)
提交回复
热议问题