Generating thick, shadowed lines in three.js to represent layers in a 3D printing visualization

I've been exploring ways to add depth to lines in Three.js that can cast shadows and appear as solid objects, but so far I've only achieved thicker lines that lack the 3D look I'm aiming for.

This is for an online 3D printing platform where I need to visualize sliced geometry made up of lines, similar to how software like Cura handles it, as seen in this image:

https://i.sstatic.net/nz6S0.png

Converting these lines into mesh geometry might not be feasible due to the high number of lines in some models, making it too dense.

If anyone has suggestions on achieving the desired effect in three.js or another JavaScript library, I would be very grateful!

Answer №1

To accomplish this technique, the concept involves rendering a primitive that covers the thick line area. The fragment shader then determines if the fragment is inside or outside the thick line, calculates the 3D position and normal, and either renders it or discards it.

The main idea is to provide polyline geometry to OpenGL for rendering, resulting in thin lines, and utilizing shaders for the rest of the process.

  1. Vertex shader:

    This shader simply passes information into the geometry shader.

  2. Geometry shader:

    Receives two vertices (defining a line) as input and outputs two triangles (forming a quad) that cover the line's bounding box (enlarged by half its thickness). This is achieved by shifting the endpoints along a vector perpendicular to the line, equal to half the thickness. It is essential to perform this operation on a plane parallel to the camera screen plane, using basis vectors obtained from the camera matrix. Both vertices must also be passed in world and camera coordinates.

  3. Fragment shader:

    Here, the fragment shader checks if a point lies within the thick line using the following method:

    https://i.sstatic.net/Ytzgm.png

    The algorithm computes P', calculates the distance between P and P' - the perpendicular distance between the point and the line. This can be achieved by leveraging the dot product formula:

    t = dot(P-P0,P1-P0)
     P' = P0 + t*(P1-P0)
     d = |P'-P0|
    

    Subsequently, the 3D coordinates (fragment depth) and normals are computed, followed by rendering with directional light or discarding the fragment.

For further reference, you can explore a comprehensive example demonstrating this technique for 2D cubic curves:

  • Rendering Thick 2D Cubics in GLSL

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

Oops! There was an issue while trying to serialize the props returned from getServerSideProps in "..." - we apologize for the inconvenience

Attempting to add a condition within getServerSideProps: export async function getServerSideProps(context) { const jwt = parseCookies(context).jwt || null; if (jwt) { const user = parseJwt(jwt); const userId = user.id; console.log(userId); ...

Issue with Datepicker in Angular Bootstrap: format identifier not being utilized

Check out this Plunk for reference. This is how my controller is set up: app.controller("myController", [ "$scope", function($scope){ $scope.DateFormat = "DD/MM/YYYY"; $scope.From = '15/01/2015'; // DD/MM/YYYY ...

Guide to putting a new track at the start of a jPlayer playlist

I am currently working on a website that utilizes the jPlayer playlist feature. I am facing an issue, as I need to implement a function that adds a song to the beginning of the playlist, but the existing add function only appends songs to the end of the pl ...

When using .slideup(), the entire ul is removed instead of just the nested li

Encountering some issues with this particular element: I am looking to ensure that when a hidden list collapses, the code checks to see if there are any other 'active' lists already open and closes them before opening a new one. It can be messy ...

Three.js does not have the capability to customize shapes with textures or color gradients

I have a task to create a polygon and fill it with a customized color spectrum. In regards to the color spectrum: I came across this informative post after doing some research on Google, which demonstrated how to generate a color spectrum according to ...

Outputting messages to a component with React

I'm attempting to create a component similar to a console where messages are displayed one after the other instead of replacing the old message. My goal is to have a component where I can input strings, like in a chatbox, using different parts of my ...

What sets the DisplayContext, displaySurface, and displayBuffer apart from each other?

As individuals who typically focus on graphics and visual representation, we frequently come across terms like Displaybuffer, DisplaySurface, and DisplayContext. Can you clarify the distinctions between these terms for us? ...

Guide on modifying cube material dynamically in WebGL at runtime

Currently, I am utilizing three.js to create animations. My goal is to dynamically modify the material of a cube mesh. Below is an example: // Create cube geometry var material1 = [new THREE.MeshBasicMaterial({color:0xBEE2FF}),.....]; var geometry = new ...

Does Parsley.js offer a way to configure so that the parsley-success field is not added to an input if it should be completely ignored?

Currently, I am excluding one input and adding the success class (which is fine with me) $('form').parsley({ excluded: '[data-parsley-sum-total="all"]' }); However, there are several other inputs without any validations that I do not wa ...

How to Position Input Fields over an Image Using CSS

I am working on positioning input fields over an image to allow data entry directly onto the image itself. https://i.sstatic.net/jW4iM.png Currently, I have a series of input fields (shown above) and three images with different squares on them. My goal is ...

"Can you guide me on how to display a React component in a

I have a function that loops through some promises and updates the state like this: }).then((future_data) => { this.setState({future_data: future_data}); console.log(this.state.future_data, 'tsf'); }); This outputs an array o ...

What is the best method for submitting an ajax form post when it is dynamically loaded within a bootstrap modal window?

Need some help with a Bootstrap modal form that is not submitting via AJAX as intended. When the form is submitted, the entire page reloads instead of having the data posted in the background. How can I fix this while keeping the page state? Below is the c ...

Stop the MP4 video in HTML when the user clicks outside of the modal window

I'm having trouble figuring out how to stop the video from playing when I close the modal by clicking outside of it. I've managed to make it work when the user clicks the "x" inside the modal box. The video is in mp4 format and embedded using HTM ...

How can I simply show a specific value from an object in Vue?

I've created a Vue application that filters messages and displays them on a page. Currently, when a user selects a message from the list, the entire JSON data associated with that message is shown on the page. However, I want to only display a specifi ...

Modify the text and purpose of the button

I have a button that I would like to customize. Here is the HTML code for the button: <button class="uk-button uk-position-bottom" onclick="search.start()">Start search</button> The corresponding JavaScript code is as follows: var search = n ...

Is there a way to prevent SignalR from disconnecting when the settings window is moved?

I am currently developing a webpage that utilizes SignalR events to trigger ajax requests to our servers. These requests return a URL with a custom URI scheme that, when accessed, opens up a specific program on the client's device without leaving the ...

Introducing the brand new feature: Video Mute Button!

Currently, I am working on implementing a mute button for a video on my webpage. The background of my page consists of a looping video with no other content, but the sound becomes quite bothersome after a while. While I have managed to find a button to pau ...

Verify whether an object possesses all the attributes of a class in TypeScript

Within my typescript code, I have a class called abc: export class ABC{ public a : any; public b : any; public c? : any; public d? : any; } In one of my functions, I receive an input which is represented as data:any. My goal is to verify i ...

Can we send a dynamic form using AJAX?

I am seeking a method to submit a page filled with quantities to another page and then retrieve their values. Here is my setup: <input type="number" name="item1" /> <input type="number" name="item2" /> <input type="number" name="item3" /> ...

How can you create an array in JavaScript?

Learning JavaScript has led me to discover the various methods for declaring arrays. var myArray = new Array() var myArray = new Array(3) var myArray = ["apples", "bananas", "oranges"] var myArray = [3] What sets them apart and which ways are typically ...