65.Three.js案例-使用 MeshNormalMaterial 和 MeshDepthMaterial 创建 3D 图形
实现效果
在该案例中,Three.js 被用来创建一个包含多个 3D 对象的场景。其中包括:
- 圆环结(TorusKnot)
- 立方体(Box)
- 球体(Sphere)
这些对象使用 MeshNormalMaterial 来渲染,并且整个场景背景为白色,所有对象位于一个居中的容器中。

知识点
WebGLRenderer (WebGL 渲染器)
构造器
THREE.WebGLRenderer(parameters)
| 参数 | 类型 | 描述 |
|---|---|---|
| parameters | Object | 包含渲染器选项的对象 |
常用参数:
antialias:布尔值,启用抗锯齿以获得更平滑的渲染结果。alpha:布尔值,是否支持透明背景(默认为黑色)。precision:字符串,着色器精度 (highp,mediump,lowp)。
方法
setSize(width, height, updateStyle)
设置渲染器的尺寸。
width:渲染器的宽度(像素)。height:渲染器的高度(像素)。updateStyle:是否更新 canvas 的样式尺寸(可选,默认为true)。
setClearColor(color, opacity)
设置渲染器的清除颜色。
color:十六进制颜色值或 CSS 字符串表示的颜色。opacity:透明度(0.0 到 1.0)。
PerspectiveCamera (透视相机)
构造器
THREE.PerspectiveCamera(fov, aspect, near, far)
| 参数 | 类型 | 描述 |
|---|---|---|
| fov | Number | 视野角度(单位是度),即垂直视角范围 |
| aspect | Number | 渲染区域的宽高比(通常用窗口宽度除以高度) |
| near | Number | 近裁剪面(相机视图可见范围的最近距离) |
| far | Number | 远裁剪面(相机视图可见范围的最远距离) |
方法
position.set(x, y, z)
设置相机的位置坐标。
lookAt(vector)
让相机朝向指定的三维坐标点。
Scene (场景)
构造器
THREE.Scene()
用于创建一个空的场景对象,之后可以将相机、灯光、几何体等添加到场景中。
属性
overrideMaterial : Material
如果被赋值,则场景中的所有物体都会使用这个材质进行渲染,常用于调试。
translateX(value)
沿 X 轴移动整个场景。
MeshNormalMaterial (法线材质)
构造器
THREE.MeshNormalMaterial(options)
| 参数 | 类型 | 描述 |
|---|---|---|
| options | Object | 可选参数对象 |
常见参数:
wireframe:布尔值,是否显示线框模式。flatShading:布尔值,是否使用平面着色。visible:布尔值,控制材质是否可见。
说明:此材质会根据物体表面的法线方向映射成 RGB 颜色,用于调试模型的表面方向。
TorusKnotGeometry (圆环结几何体)
构造器
THREE.TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q)
| 参数 | 类型 | 描述 |
|---|---|---|
| radius | Number | 圆环结的主半径 |
| tube | Number | 管道的半径 |
| tubularSegments | Number | 管道分段数(越高越光滑) |
| radialSegments | Number | 径向分段数(越高越光滑) |
| p | Number | 扭转因子(控制打结的方式) |
| q | Number | 扭曲因子(控制打结的方式) |
BoxGeometry (立方体几何体)
构造器
THREE.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
| 参数 | 类型 | 描述 |
|---|---|---|
| width | Number | 立方体宽度 |
| height | Number | 立方体高度 |
| depth | Number | 立方体深度 |
| widthSegments | Number | 宽度方向上的分段数 |
| heightSegments | Number | 高度方向上的分段数 |
| depthSegments | Number | 深度方向上的分段数 |
SphereGeometry (球体几何体)
构造器
THREE.SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
| 参数 | 类型 | 描述 |
|---|---|---|
| radius | Number | 球体半径 |
| widthSegments | Number | 经线数量(越高越光滑) |
| heightSegments | Number | 纬线数量(越高越光滑) |
| phiStart | Number | 起始经度角(弧度) |
| phiLength | Number | 经度跨度(弧度) |
| thetaStart | Number | 起始纬度角(弧度) |
| thetaLength | Number | 纬度跨度(弧度) |
Mesh (网格模型)
构造器
THREE.Mesh(geometry, material)
| 参数 | 类型 | 描述 |
|---|---|---|
| geometry | Geometry | 几何体对象 |
| material | Material | 材质对象 |
方法
translateX(value)
沿 X 轴方向移动模型。
代码
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="ThreeJS/three.js"></script>
<script src="ThreeJS/jquery.js"></script>
</head>
<body>
<center id="myContainer"></center>
<script type="text/javascript">
// 创建渲染器并开启抗锯齿
var myRenderer = new THREE.WebGLRenderer({antialias: true});
myRenderer.setSize(window.innerWidth, window.innerHeight);
myRenderer.setClearColor('white', 1.0);
$('#myContainer')[0].appendChild(myRenderer.domElement);
// 创建透视相机
var myCamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 30, 1000);
myCamera.position.set(-76.03, 30.40, -48.87);
myCamera.lookAt(new THREE.Vector3(0, 0, 0));
// 创建场景
var myScene = new THREE.Scene();
myScene.overrideMaterial = new THREE.MeshDepthMaterial();
myScene.translateX(30);
// 创建法向量材质
var myMaterial = new THREE.MeshNormalMaterial();
// 创建圆环结
var myTorusKnotGeometry = new THREE.TorusKnotGeometry(8, 3, 200, 60);
var myTorusKnotMesh = new THREE.Mesh(myTorusKnotGeometry, myMaterial);
myTorusKnotMesh.translateX(-62);
myScene.add(myTorusKnotMesh);
// 创建立方体
var myBoxGeometry = new THREE.BoxGeometry(20, 20, 20);
var myBoxMesh = new THREE.Mesh(myBoxGeometry, myMaterial);
myBoxMesh.translateX(-20);
myScene.add(myBoxMesh);
// 创建球体
var mySphereGeometry = new THREE.SphereGeometry(20, 60, 60);
var mySphereMesh = new THREE.Mesh(mySphereGeometry, myMaterial);
mySphereMesh.translateX(70);
myScene.add(mySphereMesh);
// 渲染场景
myRenderer.render(myScene, myCamera);
</script>
</body>
</html>