To display only a portion of your BufferGeometry
, you can specify the range using drawRange
in this way:
mesh.geometry.setDrawRange( startIndex, count );
For more details, check out this response.
UPDATE - Another method mentioned below in the comments involves adding an attribute to your geometry that denotes the fractional distance each vertex is positioned along the geometry. This technique necessitates a custom ShaderMaterial
, enabling smooth animation of mesh rendering.
Here's a sample vertex shader and fragment shader:
<script id="vertex_shader" type="x-shader/x-vertex">
attribute float distance;
varying float vDistance;
varying vec3 vNormal;
varying vec3 vViewPosition;
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vDistance = distance;
vNormal = normalize( normalMatrix * normal );
vViewPosition = - mvPosition.xyz;
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="fragment_shader" type="x-shader/x-fragment">
uniform float fraction;
varying float vDistance;
varying vec3 vNormal;
varying vec3 vViewPosition;
void main() {
if ( vDistance > fraction ) discard;
vec3 color = vec3( 0.25, 0.5, 1.0 );
// incorporate fake pointlight at camera location, plus ambient
vec3 normal = normalize( vNormal );
vec3 lightDir = normalize( vViewPosition );
float dotProduct = max( dot( normal, lightDir ), 0.0 ) + 0.2;
// ensure clipped ends appear solid
gl_FragColor = ( gl_FrontFacing ) ? vec4( color * dotProduct, 1.0 ) : vec4( color, 1.0 );
}
</script>
Here's how to introduce an attribute to your BufferGeometry
and create the material.
// new attribute
var numVertices = geometry.attributes.position.count;
var distance = new Float32Array( numVertices * 1 ); // 1 value per vertex
geometry.setAttribute( 'distance', new THREE.BufferAttribute( distance, 1 ) );
// populate attribute
for ( var i = 0, l = numVertices; i < l; i ++ ) {
// define new attribute
distance[ i ] = ( geometry.attributes.position.getY( i ) + 10 ) / 20;
// adjust geometry slightly
var x = geometry.attributes.position.getX( i )
var y = geometry.attributes.position.getY( i );
geometry.attributes.position.setX( i, x + 2 * Math.sin( y ) );
}
// uniforms
var uniforms = {
"fraction" : { value: 0 }
};
// material
var material = new THREE.ShaderMaterial( {
uniforms : uniforms,
vertexShader : document.getElementById( 'vertex_shader' ).textContent,
fragmentShader : document.getElementById( 'fragment_shader' ).textContent,
side: THREE.DoubleSide
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
Then, in your render loop, set the desired fraction for rendering:
mesh.material.uniforms.fraction.value = 0.5 * ( 1 + Math.cos( t ) );
Version three.js r.144