ThreeJS学习7_裁剪平面(clipping)


1. 裁剪平面简介

裁剪平面指的是存在一个平面, 能够对场景中的物质进行截断, 这个平面就是裁剪平面, 裁剪平面分为全局的裁剪和局部裁剪

  • 全局裁剪指的有一个平面裁剪了整个场景的物体, 这需要在renderer中设置
  • 局部裁剪指的有一个平面裁剪裁剪指定物体, 这需要在指定物体的material中设置
    • 里面涉及到被裁剪的物体的是否需要渲染阴影
    • 里面还涉及到被多个平面裁剪时, 保留并集还是交集, 下面一一讲解

2. 全局裁剪和局部裁剪

  1. 全局裁剪只需要设置一样

    renderer.clippingPlanes = planes

    renderer 是 WebGLRenderer实例,

    clippingPlanes 是用户自定义的剪裁平面,在世界空间中被指定为THREE.Plane对象。 这些平面全局使用。空间中与该平面点积为负的点将被切掉。 默认值是[]

    planes类型为[], 元素是任意的平面, 啥子叫做点积为负, 也就是点到平面的向量和平面法向量夹角大于90度, 简单来说, 平面法向量的反方向都被截断, , 该平面的法向量为(-1, 0, 0), 法向量的方向为x轴的负方向, 距离原点的距离为0.2, 因此, 在x>0.2的区域全部被截断不显示

    结合案例来看,

  1. 局部裁剪, 除了设置 renderer , 还要设置指定物质的material, 当平面裁剪时, 就只有物质被裁剪, 看案例

    此时的设置是

    // 这个也是全局的, localClippingEnable = false也有效
    // 全局截断平面
    renderer.clippingPlanes = Empty;
    // 这个是全局的, 不开的话material中的clipping无效
    // 这个设置为true后才能局部截断
    renderer.localClippingEnabled = true;
    // 设置clipping
    // 在material中设置clippingPlanes: 局部截断平面, clipShadows为截断阴影是否展示
    clippingPlanes: [localPlane], clipShadows: true
  2. 截断阴影展示

​ 通过比对可以看出设置截断阴影( clipShadows )为true时, 就像截断后的物质不存在, 已经没有阴影了, 设置为clipShadows为false时, 截断后的物质仍然能产生阴影

3. 被多个裁剪平面裁剪后

设置material中的clipIntersection = true, 会只裁剪更改剪裁平面的行为,以便仅剪切其交叉点,而不是它们的并集。

clipIntersection默认为false, 裁剪平面的并集

简单来说, 有多个裁剪平面, 每个裁剪平面裁剪的区域分布为c1, c2, ... ,cn, 默认设置, 裁剪 c1区域+c2区域+...+cn区域, 当clipIntersection=true时, 裁剪的只有这些区域共同的部分, c1 ∩ c2 ∩ ... cn

// 更改剪裁平面的行为,以便仅剪切其交叉点,而不是它们的并集。默认值为 false。
// 设置为true后剪切交集而不是并集
clipIntersection: true

三个截断平面法向量分布为(1, 0, 0), (0, -1, 0), (0, 0, -1), c1 为x负半轴区域, c2为 y正半轴, c3为z正半轴, 可以看到, 当clipIntersection为false时, c1, c2, c3区域都被截断了, 当为true时, 截断了他们共同的部分

效果如下

  1. clipIntersection = true;

  1. clipIntersection = false;

4. 被多个裁剪平面截断后代码

<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"> </div> <script type="module">
import * as THREE from '../build/three.module.js';
import {OrbitControls} from "./jsm/controls/OrbitControls.js";
import {GUI} from "./jsm/libs/dat.gui.module.js"; let container, camera, scene, renderer, mesh; let params = {
clipIntersection: true,
planeConstant: 0,
showHelpers: false
}; let clipPlanes = [
new THREE.Plane(new THREE.Vector3(1, 0, 0), 0),
new THREE.Plane(new THREE.Vector3(0, -1, 0), 0),
new THREE.Plane(new THREE.Vector3(0, 0, -1), 0)
]; init();
animation(); function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0x8FBCD4);
scene.add(new THREE.AmbientLight(0x8FBCD4, 0.4)); container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 200);
camera.position.set(-1.5, 2.5, 3.0);
scene.add(camera); let pointLight = new THREE.PointLight(0xffffff, 1);
// 灯跟着相机走, 效果不错
camera.add(pointLight); scene.add(new THREE.AxesHelper(5)); renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.localClippingEnabled = true;
container.appendChild(renderer.domElement); let group = new THREE.Group(); for (let i = 0; i <= 30; i += 2) {
let geometry = new THREE.SphereBufferGeometry(i / 30, 48, 24);
let material = new THREE.MeshLambertMaterial({
color: new THREE.Color().setHSL(Math.random(), 0.5, 0.5),
side: THREE.DoubleSide,
clippingPlanes: clipPlanes,
// 更改剪裁平面的行为,以便仅剪切其交叉点,而不是它们的并集。默认值为 false。
// 设置为true后剪切交集而不是并集
clipIntersection: params.clipIntersection
}); group.add(new THREE.Mesh(geometry, material));
} scene.add(group); let helpers = new THREE.Group();
helpers.add(new THREE.PlaneHelper(clipPlanes[0], 2, 0xff0000));
helpers.add(new THREE.PlaneHelper(clipPlanes[1], 2, 0x00ff00));
helpers.add(new THREE.PlaneHelper(clipPlanes[2], 2, 0x0000ff));
helpers.visible = false;
scene.add(helpers); let gui = new GUI(); gui.add(params, 'clipIntersection').name('clip intersection').onChange(value=>{ /*for(let item in group.children){
item.material.clipIntersection = value;
}*/ let children = group.children; for (let i = 0; i < children.length; i++) {
children[i].material.clipIntersection = value;
} }); gui.add(params, 'planeConstant', -1, 1).step(0.01).name('plane constant').onChange(value=>{ for (let i = 0; i < clipPlanes.length; i++) {
clipPlanes[i].constant = value;
}
}); gui.add(params, 'showHelpers').name('show helpers').onChange(value=>{
helpers.visible = value;
}); let controls = new OrbitControls(camera, renderer.domElement);
controls.enabledZoom = false; window.addEventListener('resize', onWindowResize, false);
} function animation(){
render(); requestAnimationFrame(animation);
} function render() { renderer.render(scene, camera);
} function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight);
} </script>
</body>
</html>

# ThreeJS学习7_裁剪平面(clipping)的更多相关文章

  1. OSG学习:裁剪变换(2)

    接着上一篇博客说. 还有一种裁剪的方法:osg::Scissor类. 这个类封装了OpenGL中的glScissor()函数. 该类主要用于设置一个视口裁剪平面举行.设置裁剪平面举行的函数如下: vo ...

  2. OSG学习:裁剪变换(1)

    在OSG中,默认了6个裁剪平面以去除没有必要显示的物体.也可以自己定义其他的裁剪平面来确定裁剪. osg::ClipPlane类继承自osg::StateAttribute类,封装了OpenGL中的g ...

  3. opengl 裁剪平面

    原帖地址:http://blog.sina.com.cn/s/blog_5ff6097b0100xqvr.html void glClipPlane(GLenum plane, const GLdou ...

  4. ThreeJS学习6_几何体相关(BufferGeometry)

    ThreeJS学习6_几何体相关(BufferGeometry) 使用 BufferGeometry 可以有效减少向 GPU 传输几何体相关数据所需的开销 可以自定义顶点位置, 面片索引, 法向量, ...

  5. WebGL和ThreeJs学习5--ThreeJS基本功能控件

      Threejs 2017年6月6日 15:06 Stats: new Stats();性能监视器,性能测试的方法,引入 Stats.js        http://www.hewebgl.com ...

  6. threejs 学习之

    主要内容: 使用 threejs 创建 20x20 的网格,鼠标移动时,方块跟随移动,点击时在网格任意位置放置方块,按 shift 时,删除当前位置方块. 流程如下: 创建网格 创建一个与网格同样尺寸 ...

  7. 梯度裁剪(Clipping Gradient):torch.nn.utils.clip_grad_norm

    torch.nn.utils.clip_grad_norm_(parameters, max_norm, norm_type=2) 1.(引用:[深度学习]RNN中梯度消失的解决方案(LSTM) ) ...

  8. 9. svg学习笔记-裁剪和蒙版

    裁剪 在svg中进行剪切,对整个svg元素而言,可以使用<svg>元素的viewbox属性,对于单个元素则可以使用<clipPath>元素.在单个图形元素上使用裁剪,可以在&l ...

  9. WebGL和ThreeJs学习6--射线法确定3D空间中所选物体

    一.在 threejs 中如何确定下图3D空间中鼠标点击位置的 object 对象? 二.射线法确定步骤及代码 //Three.js提供一个射线类Raycaster来拾取场景里面的物体.更方便的使用鼠 ...

随机推荐

  1. explain为mysql关键字,不能作为表字段创建

    在用jpa自动建表时,字段名命名为了explain,发现报实体类与数据库表字段不一致的错,查询才发现explain是mysql的关键字,无法作为表字段建立,特此记录

  2. 手把手教你springboot中导出数据到excel中

    手把手教你springboot中导出数据到excel中 问题来源: 前一段时间公司的项目有个导出数据的需求,要求能够实现全部导出也可以多选批量导出(虽然不是我负责的,我自己研究了研究),我们的项目是x ...

  3. 极简 Node.js 入门 - 4.4 可写流

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  4. Oracle 11gR2-Win 64bit

    版本:Oracle 11gR2下载地址:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.ht ...

  5. mybatis基础使用

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .20 ...

  6. 面试官:开发过Maven插件吗?我:开发过啊。。。

    写在前面 转眼间,今天已经是假期的第4天了.今天要给大家分享点啥呢?想了半天,想起了之前去某宝面试的情景.记得面试前自己基于Maven开发过一些简单实用的插件,而且在自己的本地环境中一直在使用,极大的 ...

  7. C++中头文件简介(stdio.h & chrono)

    参考: 1. https://baike.baidu.com/item/stdio.h 2. https://www.cnblogs.com/jwk000/p/3560086.html 1. stdi ...

  8. Python之路——变量

    什么是变量 #变量即变化的量,核心是"变"与"量"二字,变即变化,量即衡量状态. 为什么要有变量 #程序执行的本质就是一系列状态的变化,变是程序执行的直接体现, ...

  9. Linux软件漏洞-1

    RHSA-2018:3107-中危: wpa_supplicant 安全和BUG修复更新 漏洞编号:CVE-2018-14526 漏洞公告:wpa_supplicant中未经身份验证的EAPOL-Ke ...

  10. volatile、ThreadLocal的使用场景和原理

    并发编程中的三个概念 原子性 一个或多个操作.要么全部执行完成并且执行过程不会被打断,要么不执行.最常见的例子:i++/i--操作.不是原子性操作,如果不做好同步性就容易造成线程安全问题. 可见性 多 ...