英文:
Box Overflow Clipping Three JS
问题
使用three.js有没有办法裁剪或隐藏对象超出其父级的部分?例如,我有一个盒子和一个球体,就像这张图片上的样子:球体在盒子内。
我想裁剪或隐藏球体超出盒子外部的部分。简单来说,我需要类似于CSS中overflow:hidden的逻辑。
我在three.js方面非常新手,请不要因为我问了一些愚蠢的问题而批评我。无论如何,我的代码在这里:
// 简单的例子
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
let renderer, scene, camera, controls;
init();
animate();
function init() {
    // 渲染器
    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 = new THREE.Scene();
    // 相机
    camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(0, 0, 40);
    // 控制器
    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);
}
英文:
Using three js is there any way to clip or hide object out of its parent? For example i have a box and a sphere inside of this box like on image: sphere inside box
I want to clip or hide the part of sphere that is outside of the box. To put it simply, i need similar logic like css overflow:hidden works;
I am very new working with three.js, don't judge me if i'm asking something dumb. Anyways,my code is here:
// Simple example
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/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 );
}
答案1
得分: 0
以下是已翻译的内容:
- 
One solution is to using clipping as you suggest.
一种解决方法是使用剪裁,正如您所建议的那样。 - 
You have some example here: https://threejs.org/examples/?q=clip
您可以在这里找到一些示例:https://threejs.org/examples/?q=clip - 
First you have to enable local clipping on the renderer (see WebGLRenderer.localClippingEnabled).
首先,您需要在渲染器上启用局部剪裁(参见 WebGLRenderer.localClippingEnabled)。 - 
Then you can add some clipping planes to specify the area you want to clip. For this, you can use the Math class.
然后,您可以添加一些剪裁平面来指定要剪裁的区域。为此,您可以使用Math类。 - 
Enable 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)); - 
And finally, specify the plane in the material:
最后,在材质中指定平面:clippingPlanes: [clipPlane1], clipIntersection: true - 
Here is your entire code:
这是您的完整代码: 
// 简单示例
import * as THREE from 'three';
import { OrbitControls } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls';
let renderer, scene, camera, controls;
init();
animate();
function init() {
    // 渲染器
    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);
    console.log(renderer);
    
    // 场景
    scene = new THREE.Scene();
    
    // 相机
    camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(0, 0, 40);
    
    // 平面
    const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
    clipPlane1.translate(new THREE.Vector3(6, 0, 0));
    
    // 控制器
    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);
}
<details>
<summary>英文:</summary>
One solution is to using clipping as you suggest.
You have some example here: https://threejs.org/examples/?q=clip
First you have to enable local clipping on the renderer
(see [WebGLRenderer.localClippingEnabled][1]). Then you can add some clipping planes to specify the area you want to clip. For this, you can use the [Math class][2].
So in your example, you have to:
Enable 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));
And finally, specify the plane in the material:
clippingPlanes: [clipPlane1],
clipIntersection: true
---
Here is your entire code:
// Simple example
import * as THREE from 'three';
import { OrbitControls } from 'https://cdn.skypack.dev/three@0.136.0/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);
renderer.localClippingEnabled = true;
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);
// planes
const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
clipPlane1.translate(new THREE.Vector3(6, 0, 0));
// 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);
}
[1]: https://threejs.org/docs/index.html?q=renderer#api/en/renderers/WebGLRenderer.localClippingEnabled
[2]: https://threejs.org/docs/index.html?q=plane#api/en/math/Plane
</details>
				通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论