Three JS Box Overflow Clipping: An Innovative Solution

Is it possible to clip or hide parts of an object in three.js that extend beyond its parent container? For instance, imagine having a sphere inside a box like this: sphere inside box

I want to achieve a clipping effect where the part of the sphere outside of the box is hidden. Essentially, I am looking for similar functionality as CSS overflow:hidden.

I am relatively new to working with three.js, so please bear with me if my question seems naive. Here is the code I have:

// Simple example
import * as THREE from "https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1e6a766c7b7b5e2e302f2f23626d666527262d2168"><span class="__cf_email__" data-cfemail="bcdff0f3fff9fbece2eadccdfcd4ddd48bdda3fed">[email protected]</span></a>";
import {OrbitControls} from "https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ef9b879d8a8aafdfc1dedcd9c1df">[email protected]</a>/examples/jsm/controls/OrbitControls";

let renderer, scene, camera, controls;

init();
animate();

function init() {
    // renderer
  renderer = new THREE.WebGLRenderer({alpha:true, antialias:true});
  renderer.autoClear = false;
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );
  console.log(renderer)
    // scene
  scene = new THREE.Scene();

    // camera
  camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
  camera.position.set(0, 0, 40);

    // controls
  controls = new OrbitControls( camera, renderer.domElement );
    const materialA =  new THREE.MeshStandardMaterial({
        roughness: 0,
        metalness: 0,
        color: 0xffffff,
    })
  const materialB = new THREE.MeshPhysicalMaterial({
        roughness: 0,
        transmission: 1,
        thickness: 0.5
    });
  const sphere = new THREE.Mesh(new THREE.SphereGeometry(-5,30,30),materialA);
  sphere.position.set(5, 0, 0)
  
  const box = new THREE.Mesh(new THREE.BoxGeometry(12,12,12),materialB);
   scene.add(box);
  
  const light = new THREE.DirectionalLight('white', 1);
  light.position.set(10, 10, 0);
  const light2 = new THREE.DirectionalLight('white', 1);
  light2.position.set(-10, -10, -10);
  scene.add(sphere, box,light,light2);
}

function animate() {    
  requestAnimationFrame( animate );
  renderer.render( scene, camera );
}

Answer №1

One way to tackle this issue is by utilizing clipping, as you suggested.

For further guidance and examples, visit:

To begin, activate local clipping on the renderer through (look at WebGLRenderer.localClippingEnabled). Then, specify the regions to clip using clipping planes with the Math class.

In your specific case, follow these steps:

Activate local clipping:

renderer.localClippingEnabled = true;

Create a plane:

const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
clipPlane1.translate(new THREE.Vector3(6, 0, 0));

Lastly, define the plane in the material:

clippingPlanes: [clipPlane1],
clipIntersection: true

Your full code snippet is provided below:

// Implementation example
import * as THREE from 'three';
import { OrbitControls } from 'https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2b5f43594e4e6b1b051a181d051b">[email protected]</a>/examples/jsm/controls/OrbitControls';

let renderer, scene, camera, controls;

init();
animate();

function init() {
    // renderer setup
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.autoClear = false;
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.localClippingEnabled = true;
    document.body.appendChild(renderer.domElement);
    
    // creation of scene
    scene = new THREE.Scene();

    // setting up camera
    camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(0, 0, 40);

    // defining planes
    const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
    clipPlane1.translate(new THREE.Vector3(6, 0, 0));

    // implementing controls
    controls = new OrbitControls(camera, renderer.domElement);
    const materialA = new THREE.MeshStandardMaterial({
        roughness: 0,
        metalness: 0,
        color: 0xffffff,
        clippingPlanes: [clipPlane1],
        clipIntersection: true,
    });
    const materialB = new THREE.MeshPhysicalMaterial({
        roughness: 0,
        transmission: 1,
        thickness: 0.5,
    });
    const sphere = new THREE.Mesh(new THREE.SphereGeometry(-5, 30, 30), materialA);
    sphere.position.set(5, 0, 0);

    const box = new THREE.Mesh(new THREE.BoxGeometry(12, 12, 12), materialB);
    scene.add(box);

    const light = new THREE.DirectionalLight('white', 1);
    light.position.set(10, 10, 0);
    const light2 = new THREE.DirectionalLight('white', 1);
    light2.position.set(-10, -10, -10);
    scene.add(sphere, box, light, light2);
}

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}

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

How can SQL data be loaded following the selection from a dropdown menu?

I have a pressing query that I need assistance with. I am aiming to achieve a certain task, but due to lack of prior experience in this area, I am unsure about how to proceed. My current situation involves populating a dropdown menu with names retrieved f ...

Tips for Designing a Custom Footer Layout for KoGrid

Is it possible to create a footer template for a koGrid that displays the sum of a column? gridOptions : { displaySelectionCheckbox: false, data: items, // selectedItems: self.selectedItems, multiSelect: false, ena ...

Attempting to deploy my initial Google Cloud Function, encountering an error message indicating that Express is not detected

Currently in the process of deploying my first Google Cloud function, the code for which can be found here: https://github.com/rldaulton/GCF-Stripe/blob/master/Charge%20Customer/index.js The code starts with the following line: var app = require('e ...

Vue js throws a maximum call stack error when updating a Chart component

I have successfully created a line chart using the Chart.js 3.5 library. The chart is responsive, all animations are working fine too. I am currently facing an issue where I am attempting to update the data from a parent component and trigger a chart updat ...

Unable to retrieve an image from various sources

My setup includes an Express server with a designated folder for images. app.use(express.static("files")); When attempting to access an image from the "files" folder at localhost:3000/test, everything functions properly. However, when trying to ...

Interactive table on click

Seeking assistance with an issue involving a combobox (select) and a dynamic table generated from PHP. The table displays names along with their Firstname, Lastname, and ID (hidden). Upon clicking on a row in the table, I should retrieve the ID of that spe ...

JavaScript - Returning an object using a promise

I'm facing an issue where I am struggling to retrieve an object with a specific structure, but I am unable to successfully return the object. When I inspect the code, I notice that if I log the data inside the promise, it shows the data. However, whe ...

JavaScript placeholder-type expression

Hey there, I am a C++ developer who is venturing into the world of JavaScript. While exploring JavaScript syntax, I stumbled upon something that resembles templates in C++. For example, while going through RxJs tutorials, I came across this line of code: ...

How do I extract a parameter when passing it to a promise in NodeJS?

Let me simplify this query. I need to fetch a parameter used in a promise. Here's the gist of the code: function foo(param) { return fromPromise(blabla, blabla2, param) .then((res) => { return res }).catch((error) => { console.log( ...

What is the best way to navigate back to the top of the page once a link has been clicked?

One issue I'm facing is that whenever I click on a link in NextJS, it directs me to the middle of the page: <Link href={`/products/${id}`} key={id}> <a> {/* other components */} </a> </Link> I believe the problem l ...

Preventing the pull-down-to-refresh feature on Chrome mobile can be achieved by adjusting the

Looking for a way to prevent the pull-down-to-refresh feature on mobile Chrome, especially iOS Chrome? My web application utilizes vertical panning events with device-width and device-height viewport settings, but each time I pan down, mobile Chrome refres ...

Separating stylesheets, head, and other elements in a curl response

After successfully using curl to retrieve an external site, I noticed that the results were interfering with my own content. The CSS from the external site was affecting my webpage's layout and z-index values were conflicting. I am seeking a solution ...

Can we effectively manage the input for a component that is created dynamically in real-time?

Please note: I am a newcomer to ReactJS, JavaScript, and the world of front-end development in general. Hello everyone, I have made the decision to create a versatile component that can handle all the forms within my project based on a predefined templat ...

Issue with Vue JS component on blade template page

Having trouble loading a Vue component into a Laravel blade file? Despite making changes, the content of my vue file isn't showing up in the blade file - even though there are no errors in the console. Any suggestions on how to resolve this issue woul ...

Top techniques for creating a popup window with React

I'm working on my React application and I'm looking to implement a popup window that displays a table with some data. However, I want this popup to appear in a separate browser window rather than as a modal attached to the application's DOM. ...

Error: Unforeseen token encountered while attempting to import React in Javascript

Upon executing the command 'npm run start', I encountered this error: import React from 'react'; ^^^^^ SyntaxError: Unexpected identifier at Module._compile (internal/modules/cjs/loader.js:721:23) at Object.Module._exten ...

implementing a timestamp in a specific timezone with Vue.js

Utilizing a timestamp attribute, I have successfully implemented the display of the current time and date on my webpage. Is there a way to showcase this information in a specific time zone? I am looking to present it in the ZULU timezone, which remains st ...

Steps to Utilize Google Apps Script from a Website

I've been on a mission to find the solution to my problem. I have a basic web page with HTML/CSS/JS. What I want is for users to visit the page and immediately have it call up a Google script I created, which will pull information from a spreadsheet a ...

Open the JSON file and showcase its contents using Angular

I am attempting to read a JSON file and populate a table with the values. I've experimented with this.http.get('./data/file.json') .map(response => response.json()) .subscribe(result => this.results =result, function(error) ...

What is preventing the image from showing up as a texture in this web GL?

There seems to be an issue with displaying the image and I'm unable to identify the cause. The image can be found at: https://i.sstatic.net/O7Z3U.jpg. Do I need to specify a particular property for the texture or define it differently? Or could it s ...