javascript three.js

javascript - Cómo animar el dibujo de una malla en three.js



(1)

Tengo una malla tipo cinta hecha de una geometría de amortiguación, cuyas caras son invisibles. Estoy usando un sombreador personalizado para esto - gl_FragColor = vec4(1.0,1.0,1.0,0.0) .

Cuando se desplaza un objeto 3D a lo largo de la cinta, filmo el índice de las caras sobre las que se encuentra y actualizo el sombreado que las forma.

No estoy satisfecho con el efecto ya que resulta en una animación bastante gruesa. Si agrego más caras, recibo un golpe de rendimiento serio.

¿Hubiera alguna forma de actualizar el alfa del fragmento en función de la posición 3DObject sin tener que recurrir a caras enteras?

En una nota al margen: también he intentado recortar la cinta de la vista, en función de las posiciones de píxeles x / z. El efecto es perfecto, el rendimiento es bueno, pero obtengo efectos no deseados cuando la cinta gira bruscamente.


Puede representar solo una parte de su BufferGeometry configurando drawRange manera:

mesh.geometry.setDrawRange( startIndex, count );

Para obtener más información y un ejemplo en vivo, vea esta respuesta .

EDITAR - Como se menciona en los comentarios a continuación, otro enfoque es agregar un atributo a su geometría que represente la distancia fraccional que cada vértice está posicionado a lo largo de la geometría. Este enfoque requerirá un ShaderMaterial personalizado, pero podrá animar suavemente el dibujo de su malla.

Aquí hay un sombreador de vértices y un sombreador de fragmentos de ejemplo

<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 ); // hack in a 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; // trick to make the clipped ends appear solid gl_FragColor = ( gl_FrontFacing ) ? vec4( color * dotProduct, 1.0 ) : vec4( color, 1.0 ); } </script>

Aquí se explica cómo agregar un atributo a su BufferGeometry y crear una instancia del material.

// new attribute var numVertices = geometry.attributes.position.count; var distance = new Float32Array( numVertices * 1 ); // 1 value per vertex geometry.addAttribute( ''distance'', new THREE.BufferAttribute( distance, 1 ) ); // populate attribute for ( var i = 0, l = numVertices; i < l; i ++ ) { // set new attribute distance[ i ] = ( geometry.attributes.position.getY( i ) + 10 ) / 20; // wiggle geometry a bit while we''re at it 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 );

Luego, en su ciclo de renderizado, configure la fracción deseada para procesar:

mesh.material.uniforms.fraction.value = 0.5 * ( 1 + Math.cos( t ) );

violín: http://jsfiddle.net/m99aj10b/

three.js r.76