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

1. 裁剪平面简介
裁剪平面指的是存在一个平面, 能够对场景中的物质进行截断, 这个平面就是裁剪平面, 裁剪平面分为全局的裁剪和局部裁剪
- 全局裁剪指的有一个平面裁剪了整个场景的物体, 这需要在renderer中设置
- 局部裁剪指的有一个平面裁剪裁剪指定物体, 这需要在指定物体的material中设置
- 里面涉及到被裁剪的物体的是否需要渲染阴影
- 里面还涉及到被多个平面裁剪时, 保留并集还是交集, 下面一一讲解
2. 全局裁剪和局部裁剪
全局裁剪只需要设置一样
renderer.clippingPlanes = planes
renderer 是 WebGLRenderer实例,
clippingPlanes 是用户自定义的剪裁平面,在世界空间中被指定为THREE.Plane对象。 这些平面全局使用。空间中与该平面点积为负的点将被切掉。 默认值是[]
planes类型为[], 元素是任意的平面, 啥子叫做点积为负, 也就是点到平面的向量和平面法向量夹角大于90度, 简单来说, 平面法向量的反方向都被截断, , 该平面的法向量为(-1, 0, 0), 法向量的方向为x轴的负方向, 距离原点的距离为0.2, 因此, 在x>0.2的区域全部被截断不显示
结合案例来看,

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

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


通过比对可以看出设置截断阴影( 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时, 截断了他们共同的部分
效果如下
- clipIntersection = true;

- 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)的更多相关文章
- OSG学习:裁剪变换(2)
接着上一篇博客说. 还有一种裁剪的方法:osg::Scissor类. 这个类封装了OpenGL中的glScissor()函数. 该类主要用于设置一个视口裁剪平面举行.设置裁剪平面举行的函数如下: vo ...
- OSG学习:裁剪变换(1)
在OSG中,默认了6个裁剪平面以去除没有必要显示的物体.也可以自己定义其他的裁剪平面来确定裁剪. osg::ClipPlane类继承自osg::StateAttribute类,封装了OpenGL中的g ...
- opengl 裁剪平面
原帖地址:http://blog.sina.com.cn/s/blog_5ff6097b0100xqvr.html void glClipPlane(GLenum plane, const GLdou ...
- ThreeJS学习6_几何体相关(BufferGeometry)
ThreeJS学习6_几何体相关(BufferGeometry) 使用 BufferGeometry 可以有效减少向 GPU 传输几何体相关数据所需的开销 可以自定义顶点位置, 面片索引, 法向量, ...
- WebGL和ThreeJs学习5--ThreeJS基本功能控件
Threejs 2017年6月6日 15:06 Stats: new Stats();性能监视器,性能测试的方法,引入 Stats.js http://www.hewebgl.com ...
- threejs 学习之
主要内容: 使用 threejs 创建 20x20 的网格,鼠标移动时,方块跟随移动,点击时在网格任意位置放置方块,按 shift 时,删除当前位置方块. 流程如下: 创建网格 创建一个与网格同样尺寸 ...
- 梯度裁剪(Clipping Gradient):torch.nn.utils.clip_grad_norm
torch.nn.utils.clip_grad_norm_(parameters, max_norm, norm_type=2) 1.(引用:[深度学习]RNN中梯度消失的解决方案(LSTM) ) ...
- 9. svg学习笔记-裁剪和蒙版
裁剪 在svg中进行剪切,对整个svg元素而言,可以使用<svg>元素的viewbox属性,对于单个元素则可以使用<clipPath>元素.在单个图形元素上使用裁剪,可以在&l ...
- WebGL和ThreeJs学习6--射线法确定3D空间中所选物体
一.在 threejs 中如何确定下图3D空间中鼠标点击位置的 object 对象? 二.射线法确定步骤及代码 //Three.js提供一个射线类Raycaster来拾取场景里面的物体.更方便的使用鼠 ...
随机推荐
- python实例文本进度条
简单的文本进度条代码 解析 引入time库 打印一行作为开始 最后也打印一个结束的标签 定义变量等于10,文本进度条大概的宽度是10 使用for循环来模拟进度,for i in range()能够不断 ...
- 一文带你熟悉JAVA IO这个看似很高冷的菇凉
Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 N ...
- selenium过豆瓣滑动验证码
首先是加速度代码 def get_tracks(distance): """ 拿到移动轨迹,模仿人的滑动行为,先匀加速后匀减速 匀变速运动基本公式: ①v = v0+at ...
- 网络端口及nmap扫描
端口: 计算机与外界交流的出口,在渗透测试当中常用的端口号: 21号端口FTP:文件传输协议 23号端口Telent :远程登录接口 53号端口 DNS: 域名端口 80号端口HTTP:超文本传输协议 ...
- 087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点
087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点 本文知识点:封装的概念和特点 说明:因为时间紧张,本人写博客过程中只是对 ...
- python数据结构之图深度优先和广度优先实例详解
本文实例讲述了python数据结构之图深度优先和广度优先用法.分享给大家供大家参考.具体如下: 首先有一个概念:回溯 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到 ...
- python数据结构之二叉树的建立实例
先建立二叉树节点,有一个data数据域,left,right 两个指针域 # coding:utf-8 class TreeNode(object): def __init__(self,left=N ...
- git add 添加错文件如何撤销
git add 添加 多余文件 这样的错误是由于, 有的时候 可能 git add . (空格+ 点) 表示当前目录所有文件,不小心就会提交其他文件 git add 如果添加了错误的文件的话 以下是撤 ...
- 拉格朗日乘子法与KKT条件
拉格朗日乘子法 \[min \quad f = 2x_1^2+3x_2^2+7x_3^2 \\s.t. \quad 2x_1+x_2 = 1 \\ \quad \quad \quad 2x_2+3x_ ...
- 如何轻松使用 C 语言实现一个栈?
什么是数据结构? 数据结构是什么?要了解数据结构,我们要先明白数据和结构,数据就是一些int char 这样的变量,这些就是数据,如果你是一个篮球爱好者,那么你的球鞋就是你的数据,结构就是怎么把这些数 ...