A guide to creating animated mesh drawings using three.js

I have created a ribbon-like mesh using buffer geometry with invisible faces, and I am applying a custom shader to it:

gl_FragColor = vec4(1.0, 1.0, 1.0, 0.0)
.

Currently, as a 3D object moves along the ribbon, I perform raycasting to determine the index of the faces it crosses and update the shader accordingly.

However, I am not happy with the animation as it appears too chunky. Adding more faces improves the visual effect but at the cost of performance degradation.

Is there a way for me to adjust the fragment's alpha value based on the position of the 3D object without modifying entire faces?

Additionally, I experimented with hiding parts of the ribbon based on pixel coordinates in x/z views, which improved performance and resulted in a satisfactory effect. However, this approach produced undesirable artifacts when the ribbon made sharp turns.

Answer №1

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Attempting to transfer various variables from several windows using AJAX

Is it possible to pass multiple variables from two different windows into the same PHP script? If not, what would be the best approach to take? Thank you. verifyemail.html <script type = "text/javascript" src = "js/js_functions.js"></script> ...

Implementing a messaging feature with inbox functionality in a Node.js web application

In my node.js application, I am looking to incorporate a send message and inbox feature. The website focuses on job postings within a forum, catering to freelancers, mentors, and clients. To facilitate communication between these three types of users, I ...

React Component State in JavaScript is a crucial aspect of building

What happens when the expression [...Array(totalStars)] is used within a React Component? Is the result an array with a length of 5, and what are the specific elements in this array? We appreciate your response. class StarRating extends Component { ...

Remove the most recent row that was dynamically inserted into an HTML table

Currently, I am in the process of developing an ASP.NET Web Api 2.2 application using .NET Framework 4.5, C#, and jQuery. Within one of my views, I have set up the following table: <table id ="batchTable" class="order-list"> <thead> ...

Ways to generate an array containing the headings from a list using typescript?

How can I extract the headers of objects in an array in TypeScript? let data = [{name: "A", skills: 50, result: 80}, {name: "B", skills: 40, result: 90}, {name: "C", skills: 60, result: 60}]; let headers = Ob ...

Using PHP's for loop to iterate through data and store them into arrays

Attempting to transmit data from JavaScript to a PHP file through an AJAX request, and then store each result in an array using PHP. queryData={"data":{"data_string":{"data":"medicine","default_field":"Content"}}} testArgument=0; $.ajax({ url:"test/q ...

JavaScript and the Firefox Scratchpad platform

Currently, I am utilizing the MDN guide for learning JavaScript and experimenting with examples using scratchpad. Here's a scenario: console.log('The value of b is ' + b); var b; Why does the console log display "The value of b is -1"? I ...

Is it possible to replicate a slow image loading experience in React.js?

Referenced the solution below How to simulate slow loading of image Slowing down internet connection with Chrome DevTools works, but the entire site loads slowly. I want to specifically focus on slowing down the image reloading. One of the suggestions w ...

Arranging method for organizing a set of items into order

I want to arrange the elements in a list using JavaScript/jQuery. The initial sorting works fine, but I also need it to revert back to the unsorted view when clicked again. This cycle should repeat continuously. Check out the demo here: Sorting Demo ...

Eavesdrop on outbound requests on a web page using JavaScript

As I develop a single-page application that integrates a third-party analytics tool (such as Heap, Segment, Mixpanel, etc.), I am looking to actively monitor the outgoing HTTPS requests from my app and take necessary actions, such as logging. I am curious ...

Conceal/reveal specific sections of a table cell using jQuery

Here is a table I have: A header Another header First (some-text-initially-hidden) click row Upon clicking, it changes to: A header Another header First (some-text-should-be visible now) click row However, the text "some-text-initially-hi ...

AdminLTE-3 Bootstrap-4 sidebar menu with dynamic AJAX functionality fails to toggle treeview open/hide after page is fully loaded

I am looking to update the sidebar menu dynamically in the adminlte 3 dashboard with bootstrap 4 using AJAX calls. However, I have run into an issue where the menu open/close functionality is not working when the data is loaded dynamically using AJAX. On t ...

During the deployment of a ReactJS app, webpack encounters difficulty resolving folders

While developing my ReactJS app, everything ran smoothly on localhost. However, I encountered some serious issues when I tried to deploy the app to a hosting service. In my project, I have a ./reducers folder which houses all of my reducers. Here is the s ...

Can one function be invoked from another function in Node.js?

As I delve into learning Node.js through the process of converting an existing Rails project, I find myself grappling with callbacks and the asynchronous nature of Node. It has been a challenging journey to wrap my head around these concepts. Initially, m ...

Unable to access an element using jquery

This is an example of an HTML file: <div id ="main"> </div> Here is the JavaScript code: //creating a new div element var divElem = $('<div class="divText"></div>'); //creating an input element inside the div var i ...

Angular input range slider that automatically rounds decimal values from the data bindings

I've implemented a range slider within an Angular form to capture and display recorded values. <input [formControlName]="object.id" [id]="object.id" type="range" [(ngModel)]="object.answer" [step]="objec ...

Using TypeOrm QueryBuilder to establish multiple relations with a single table

Thank you for taking the time to read and offer your assistance! I am facing a specific issue with my "Offer" entity where it has multiple relations to "User". The code snippet below illustrates these relationships: @ManyToOne(() => User, (user) => ...

Visualizing JSON data in React.js using Chart.js

Currently, as a beginner in ReactJS, I am working on an application that displays COVID-19 data from a JSON API in a visual format using Chart.js. However, despite trying various solutions, I am unable to visualize the data. Below is my source code: App ...

What is the method for retrieving a value with a designated key?

An array has been created from JSON source using the $.each method. The console displays the following: $vm0.sailNames; [Array(24), __ob__: Observer] (Interestingly, jQuery seems to have created an Observer) In the Vue.js development view, it appears li ...

The Issue of Browsers Freezing or Crashing Due to Ajax Autocomplete

My current project involves implementing Ajax Autocomplete for jQuery and passing additional parameters. While the documentation provides guidance on how to achieve this, I've encountered an issue where attempting to use a value from another field cau ...