个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
内容 | 参考链接 |
---|---|
WebGL专栏 | WebGL 入门 |
Three.js(一) | 创建场景、渲染三维对象、添加灯光、添加阴影、添加雾化 |
Three.js(二) | scene场景、几何体位置旋转缩放、正射投影相机、透视投影相机 |
Three.js(三) | 聚光灯、环境光、点光源、平行光、半球光 |
文章目录
- 前言
- 一、基础网格材质
- 二、深度网格材质
- 三、法向网格材质
- 四、面材质
- 五、朗伯网格材质
- 六、Phong 网格材质
- 七、着色器网格材质
- 八、直线和虚线
- 九、联合材质
- 总结
前言
大家好,这里是前端杂货铺。
上篇文章我们学习了 聚光灯、环境光、点光源、平行光、半球光。接下来,我们继续我们 three.js 的学习!
在学习的过程中,如若需要深入了解或扩展某些知识,可以自行查阅 => three.js官方文档。
老规矩,我们先把本篇文章需要使用的 ./controls/index.js
补充完毕
const basicType = {
// 颜色。默认为一个白色(0xffffff)的 Color 对象。
color: {
method: 'addColor',
getValue: item => item.color.getStyle(),
setValue: (item, value) => item.color.setStyle(value),
},
//
skyColor: {
method: 'addColor',
getValue: item => item.skyColor.getStyle(),
setValue: (item, value) => item.skyColor.setStyle(value),
},
// 光照强度。默认值为 1
intensity: {
method: 'add',
extends: [0, 2],
getValue: item => item.intensity,
setValue: (item, value) => item.intensity = +value,
},
// 光源照射的最大距离。默认值为 0(无限远)
distance: {
method: 'add',
extends: [0, 1],
getValue: item => item.distance,
setValue: (item, value) => item.distance = +value,
},
// 光线照射范围的角度。默认值为 Math.PI/3
angle: {
method: 'add',
extends: [0, Math.PI / 2],
getValue: item => item.angle,
setValue: (item, value) => item.angle = +value,
},
// 决定了光线强度递减的速度。
exponent: {
method: 'add',
extends: [0, 20],
getValue: item => item.exponent,
setValue: (item, value) => item.exponent = +value,
},
// 亮度
opacity: {
extends: [0, 1],
getValue: item => item.opacity,
setValue: (item, value) => item.opacity = +value
},
// 透明度
transparent: {
getValue: item => item.transparent,
setValue: (item, value) => item.transparent = value
},
// 线框
wireframe: {
getValue: item => item.wireframe,
setValue: (item, value) => item.wireframe = value
},
// 显隐
visible: {
getValue: item => item.visible,
setValue: (item, value) => item.visible = value
},
cameraNear: {
extends: [0, 50],
getValue: (item, camera) => camera.near,
setValue: (item, value, camera) => camera.near = value
},
cameraFar: {
extends: [50, 200],
getValue: (item, camera) => camera.far,
setValue: (item, value, camera) => camera.far = value
},
side: {
extends: [['font', 'back', 'double']],
getValue: (item, camera) => 'font',
setValue: (item, value) => {
switch(value) {
case 'font':
item.side = THREE.FrontSide;
break;
case 'back':
item.side = THREE.BackSide;
break;
case 'double':
item.side = THREE.DoubleSide;
break;
}
}
},
// 材料的环境颜色
ambient: {
method: 'addColor',
getValue: (item) => item.ambient.getHex(),
setValue: (item, value) => item.ambient = new THREE.Color(value),
},
// 物体材料本身发出的颜色
emissive: {
method: 'addColor',
getValue: (item) => item.emissive.getHex(),
setValue: (item, value) => item.emissive = new THREE.Color(value),
},
// 设置高亮部分的颜色
specular: {
method: 'addColor',
getValue: (item) => item.specular.getHex(),
setValue: (item, value) => item.specular = new THREE.Color(value),
},
// 设置高亮部分的亮度
shininess: {
extends: [0, 100],
getValue: (item) => item.shininess,
setValue: (item, value) => item.shininess = value,
},
red: {
extends: [0, 1],
getValue: (item) => item.uniforms.r.value,
setValue: (item, value) => item.uniforms.r.value = value,
},
alpha: {
extends: [0, 1],
getValue: (item) => item.uniforms.a.value,
setValue: (item, value) => item.uniforms.a.value = value,
},
dashSize: {
extends: [0, 5],
getValue: (item) => item.dashSize,
setValue: (item, value) => item.dashSize = +value,
},
gapSize: {
extends: [0, 5],
getValue: (item) => item.gapSize,
setValue: (item, value) => item.gapSize = +value,
}
}
const itemType = {
SpotLight: ['color', 'intensity', 'distance', 'angle', 'exponent'], // 聚光灯
AmbientLight: ['color'], // 环境光
PointLight: ['color', 'intensity', 'distance'], // 点光源
DirectionalLight: ['color', 'intensity'], // 平行光
HemisphereLight: ['groundColor', 'intensity'], // 半球光
MeshBasicMaterial: ['color', 'opacity', 'transparent', 'wireframe', 'visible'], // 基础网格材质
MeshDepthMaterial: ['wireframe', 'cameraNear', 'cameraFar'], // 深度网格材质
MeshNormalMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side'],
MeshLambertMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side', 'ambient', 'emissive', 'color'], // 朗伯材质
MeshPhongMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side', 'ambient', 'emissive', 'color', 'specular', 'shininess'], // Phong材质
ShaderMaterial: ['red', 'alpha'], // 着色器材质
LineBasicMaterial: ['color'], // 直线
LineDashedMaterial: ['dashSize', 'gapSize'], // 虚线
}
function initControls(item, camera) {
console.log('item', item)
const typeList = itemType[item.type];
const controls = {};
if (!typeList || !typeList.length) {
return;
}
const gui = new dat.GUI();
for (let i = 0; i < typeList.length; i++) {
const child = basicType[typeList[i]];
if (child) {
controls[typeList[i]] = child.getValue(item, camera);
const childExtends = child.extends || [];
gui[child.method || 'add'](controls, typeList[i], ...childExtends).onChange((value) => {
child.setValue(item, value, camera);
})
}
}
}
一、基础网格材质
基础网格材质,是一个以简单着色(平面或线框)方式来绘制几何体的材质。这种材质不受光照的影响。
new MeshBasicMaterial(parameters: Object);
使用场景:适用于不需要光照计算或复杂渲染效果的简单物体。例如,静态的、不需要光照变化的物体。
特点:不受光照影响,颜色始终保持一致。
参数名称 | 描述 |
---|---|
color | 材质颜色 |
wireframe | 是否渲染成线框 |
wireframeLinewidth | 设置线框宽度 |
wireframeLinecap | 线段间的端点如何显示 |
wireframeLinejoin | 线段的连接点如何显示 |
shading | 定义如何着色 |
vertexColors | 为每个顶点定义不同的颜色 |
fog | 是否会受全局雾化效果设置的影响 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: false
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
基础网格材质
二、深度网格材质
深度网格材质是一种 按深度绘制几何体的材质。深度基于相机远近平面。白色最近,黑色最远。
new MeshDepthMaterial(parameters: Object);
使用场景:用于显示物体的深度信息,通常用于深度测试或特殊视觉效果。
特点:只渲染物体的深度信息,不显示颜色或纹理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.MeshDepthMaterial();
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial, camera);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
深度网格材质
三、法向网格材质
法向网格材质是一种 把法向量映射到 RGB 颜色的材质。
new THREE.MeshNormalMaterial(parameters: Object);
使用场景:适用于低多边形数模型或动态生成的几何形状。通过使用法线贴图,它可以在没有复杂几何形状的情况下创建逼真的凹凸效果。
特点:基于法向量的颜色映射,MeshNormalMaterial渲染的每一个面颜色都不同;但即使在物体旋转时,这些颜色也基本保持在原来的位置,这使得MeshNormalMaterial在需要保持颜色与面关联的场景中非常有用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.MeshNormalMaterial();
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial, camera);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
法向网格材质
四、面材质
MeshFaceMaterial 在 Three.js 中并不是一个真正的材质,它更像是一个 材质容器。其主要用途是为几何体的每个面指定不同的材质,从而允许每个面具有独特的视觉表现。
new THREE.MeshFaceMaterial(parameters: Object);
注:MeshFaceMaterial 在新版 Three.js 中已经被材质数组所取代。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.MeshFaceMaterial([
new THREE.MeshBasicMaterial({ color: 0x009e60 }),
new THREE.MeshBasicMaterial({ color: 0x0051ba }),
new THREE.MeshBasicMaterial({ color: 0xffd500 }),
new THREE.MeshBasicMaterial({ color: 0xc41e3a }),
new THREE.MeshBasicMaterial({ color: 0xffff00 }),
new THREE.MeshBasicMaterial({ color: 0xff5800 }),
]);
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial, camera);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
面材质
五、朗伯网格材质
朗伯网格材质是 一种非光泽表面的材质,没有镜面高光。
new THREE.MeshLambertMaterial(parameters: Object);
使用场景:适用于需要模拟漫反射光照效果的物体。这种材质对光源的方向和强度敏感,适合表现柔和的表面。
特点:根据光源方向和强度计算表面颜色,产生柔和的阴影。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial, camera);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
朗伯网格材质
六、Phong 网格材质
Phong 网格材质是一种 用于具有镜面高光的光泽表面的材质。
new THREE.MeshPhongMaterial(parameters: Object);
使用场景:适用于需要更高级光照效果的物体,如镜面反射和高光。这种材质可以模拟更真实的光照效果。
特点:支持漫反射、镜面反射和高光,可以产生更丰富的光影效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial, camera);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
Phong网格材质
七、着色器网格材质
着色器网格材质是一种 使用自定义shader渲染的材质。
const material = new THREE.ShaderMaterial( {
uniforms: {
time: { value: 1.0 },
resolution: { value: new THREE.Vector2() }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
使用场景:适用于需要自定义渲染逻辑的高级场景。通过编写自定义的 GLSL 着色器代码,可以实现各种独特的视觉效果。
特点:允许用户编写自定义的顶点和片段着色器,实现高度自定义的渲染效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const cubeMaterial = new THREE.ShaderMaterial({
uniforms: {
r: {
type: 'f',
value: 1.0
},
a: {
type: 'f', // float 类型
value: 1.0
}
},
// 顶点着色器
vertexShader: `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
// 片元着色器
fragmentShader: `
uniform float r;
uniform float a;
void main() {
gl_FragColor = vec4(r, 0.0, 0.0, a);
}
`,
transparent: true,
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(cubeMaterial, camera);
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
着色器网格材质
八、直线和虚线
基础线条材质(直线)是一种 用于绘制线框样式几何体的材质。
// 直线
const material = new THREE.LineBasicMaterial({
color: 0xff0000,
linewidth: 1,
})
虚线材质(虚线)是一种 用于绘制虚线样式几何体的材质。
// 虚线
const material = new THREE.LineDashedMaterial({
color: 0xff0000,
dashSize: 1, // 短划线的长度
gapSize: 1 // 间隔的长度
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加直线和虚线
const lines = new THREE.Geometry();
lines.vertices = [
new THREE.Vector3(0, 2, 5),
new THREE.Vector3(0, -2, 5)
]
// 直线
// const material = new THREE.LineBasicMaterial({
// color: 0xff0000,
// linewidth: 1,
// })
// 虚线
const material = new THREE.LineDashedMaterial({
color: 0xff0000,
dashSize: 1, // 短划线的长度
gapSize: 1 // 间隔的长度
});
const line = new THREE.Line(lines, material);
// 计算点到线的累积长度
lines.computeLineDistances();
scene.add(line);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
initControls(material, camera);
const animation = () => {
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
直线与虚线
九、联合材质
创建联合材质,需要使用 SceneUtils 场景工具,它一个用于操控场景的实用类。
.createMultiMaterialObject ( geometry : BufferGeometry, materials : Array ) : Group
geometry – 材料集的几何形状。
materials – 为物体准备的材料。
创建一个新组,囊括了在材质中定义的每种材质的新网格。请注意,这和为一个网格定义多种材质的材质数组不同。
该方法对于同时需要材质和线框绘制的物体非常有用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/three/three.js"></script>
<script src="../lib/three/dat.gui.js"></script>
<script src="../controls/index.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机 视野角度FOV、长宽比、近截面、远截面
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置
camera.position.set(0, 0, 20);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加立方体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 创建立方体材质
const lambert = new THREE.MeshLambertMaterial({
color: 0xff0000
});
const basic = new THREE.MeshBasicMaterial({
wireframe: true
});
const cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [
lambert, basic
]);
// 添加到场景
scene.add(cube);
// 添加灯光
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 10, 90);
scene.add(spotLight);
spotLight.shadowMapWidth = 3456; // 分辨率宽度
spotLight.shadowMapHeight = 3456; // 分辨率高度 越大越清晰但也越消耗性能
const animation = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
animation();
</script>
</body>
</html>
联合材质
总结
本篇文章我们讲解了几种常见材质的基本使用,包括基础材质、深度材质、法向材质、面材质、朗伯材质、Phong材质、着色器材质、直线和虚线、联合材质。
更多内容扩展请大家自行查阅 => three.js官方文档,真心推荐读一读!!
好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!
参考资料:
- Three.js 官方文档
- WebGL+Three.js 入门与实战【作者:慕课网_yancy】