Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
665 views
in Technique[技术] by (71.8m points)

three.js - Texture atlas offset/repeat works for meshes but is ignored for point system particles

I am using a texture atlas to hold a sequence of images. When mapping to a mesh with MeshLambertMaterial, using Texture.offset and Texture.repeat works beautifully to cut the subtexture out of the entire image.

However, using the exact same texture instance for a PointCloudMaterial renders the particles with the entire atlas, not just the selected subimage.

I tried to follow the three.js source code, but the documentation is scarce.

Is there a workaround for this better than using canvases to chop up the image?

Edit: As requested, a work-in-progress is available at http://jnm2.com/minesweeper/.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 spriteSheet;
uniform vec2 repeat;

varying vec2 vOffset;

void main() {

    vec2 uv = vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y );

    vec4 tex = texture2D( spriteSheet, uv * repeat + vOffset );
    
    if ( tex.a < 0.5 ) discard;

    gl_FragColor = tex;

}

</script>

Then

   // geometry
    geometry = new THREE.BufferGeometry();
 
    // attributes
    var numVertices = 20;
    var positions = new Float32Array( numVertices * 3 ); // 3 coordinates per point
    var offsets = new Float32Array( numVertices * 2 ); // 2 coordinates per point

    geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
    geometry.setAttribute( 'offset', new THREE.BufferAttribute( offsets, 2 ) );

    // populate offsets
    var offset = new THREE.Vector2();

    for ( var i = 0, index = 0, l = numVertices; i < l; i ++, index += 3 ) {
 
        positions[ index ] = 100 * Math.random() - 50;
        positions[ index + 1 ] = 100 * Math.random() - 50;
        positions[ index + 2 ] = 100 * Math.random() - 50;

    }

   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;

    }

    // image
    image = document.createElement( 'img' );
    image.addEventListener( 'load', function ( event ) { texture.needsUpdate = true; } );

    // texture
    var texture = new THREE.Texture( image );

    // uniforms
    uniforms = {

        spriteSheet: { 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/dvenjys4/

three.js r.126


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...