three.js之特殊材质效果
- IT业界
- 2025-08-23 09:06:02

*案例42 创建一个透明的立方体 <template> <div ref="container" className="container"></div> </template> <script setup> import * as THREE from 'three'; import WebGL from 'three/examples/jsm/capabilities/WebGL.js' // 引入轨道控制器扩展库OrbitControls.js import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js' import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; import {ref, onMounted} from 'vue' let container = ref(null) onMounted(() => { /* * * 创建场景(渲染必加代码) */ // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 创建场景 const scene = new THREE.Scene(); /* * * 创建摄像机(渲染必加代码) * */ // 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机) // 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的) // 控制相机能看到的角度范围。 // 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄 // 参数 2:aspect长宽比,控制相机看到的画面的宽高比。 // 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化 // 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1 // 1 表示距离相机 1 个单位以内的物体不会被渲染 // 参数 4:far远截面,控制相机能看到的最大距离 // 1000 表示距离相机 1000 个单位以外的物体不会被渲染 const camera = new THREE.PerspectiveCamera(30, containerWidth / containerHeight, 1, 100); // camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果 // 摄像机的位置 camera.position.set(5, 3.5, 4.7); // 摄像机聚焦的位置 camera.lookAt(0, 0, 0); // zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1 camera.zoom = 1 // 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】 camera.updateProjectionMatrix() /* * * 创建渲染器(渲染必加代码) * */ // 创建渲染器(three.js有好几种渲染器) const renderer = new THREE.WebGLRenderer(); // 设置渲染器尺寸 // 第三个参数(选填):false代表以较低分辨率渲染 renderer.setSize(containerWidth, containerHeight ); // 将渲染器放入文档中 container.value.appendChild(renderer.domElement); /* * 创建坐标轴对象(用于辅助创建3D场景) * */ // AxesHelper() 的参数代表坐标轴的线段长度 // 红色代表x轴,绿色代表y轴,蓝色代表z轴 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); /* * 创建轨道控制器 * */ const orbitControls = new OrbitControls(camera, renderer.domElement); // 更新控制器 orbitControls.update(); orbitControls.addEventListener('change', function () { // 输出相机位置 //console.log('camera.position', camera.position); }); /* * 创建一个透明的立方体 * (效果不太理想,立方体的背面没有显示) * */ // 新建立方体对象 const geometry = new THREE.BoxGeometry(1,1,1); // 创建材质 // MeshBasicMaterial材质不受光照影响 const material = new THREE.MeshBasicMaterial({ // 材质颜色 color: '#2ccdf1', // 启用透明 transparent: true, // 设置透明度 opacity: 0.35, // 渲染正面和背面 side: THREE.DoubleSide, }); // 新建网格(网格包含集合体和作用在几何体上面的材质) const cube = new THREE.Mesh(geometry, material); // 将网格添加到场景 scene.add(cube); /* * 渲染场景必加代码 (渲染循环) * */ // 渲染循环 function animate() { // 每秒执行60次 requestAnimationFrame(animate); // 更新控制器 orbitControls.update(); // 渲染场景 renderer.render(scene, camera); } // WebGL兼容性检查 if (WebGL.isWebGLAvailable()) { animate(); } else { const warning = WebGL.getWebGLErrorMessage(); container.value.appendChild(warning); } /** * 窗口变化自适应(必加代码) */ const onWindowResize = () => { // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 重置渲染器输出画布canvas尺寸 renderer.setSize(containerWidth, containerHeight); // aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高 // 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比 camera.aspect =containerWidth / containerHeight; // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix // 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) // 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效 camera.updateProjectionMatrix(); } // 监听浏览器窗口大小改变 window.addEventListener('resize', onWindowResize); }) </script> <style> </style> <style scoped> .container { height: 100vh; box-sizing: border-box; /* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/ overflow: hidden; } </style> *案例43 创建一个线框球体 <template> <div ref="container" className="container"></div> </template> <script setup> import * as THREE from 'three'; import WebGL from 'three/examples/jsm/capabilities/WebGL.js' // 引入轨道控制器扩展库OrbitControls.js import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js' import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; import {ref, onMounted} from 'vue' let container = ref(null) onMounted(() => { /* * * 创建场景(渲染必加代码) */ // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 创建场景 const scene = new THREE.Scene(); /* * * 创建摄像机(渲染必加代码) * */ // 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机) // 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的) // 控制相机能看到的角度范围。 // 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄 // 参数 2:aspect长宽比,控制相机看到的画面的宽高比。 // 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化 // 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1 // 1 表示距离相机 1 个单位以内的物体不会被渲染 // 参数 4:far远截面,控制相机能看到的最大距离 // 1000 表示距离相机 1000 个单位以外的物体不会被渲染 const camera = new THREE.PerspectiveCamera(30, containerWidth / containerHeight, 1, 100); // camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果 // 摄像机的位置 camera.position.set(5, 3.5, 4.7); // 摄像机聚焦的位置 camera.lookAt(0, 0, 0); // zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1 camera.zoom = 1 // 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】 camera.updateProjectionMatrix() /* * * 创建渲染器(渲染必加代码) * */ // 创建渲染器(three.js有好几种渲染器) const renderer = new THREE.WebGLRenderer(); // 设置渲染器尺寸 // 第三个参数(选填):false代表以较低分辨率渲染 renderer.setSize(containerWidth, containerHeight ); // 将渲染器放入文档中 container.value.appendChild(renderer.domElement); /* * 创建坐标轴对象(用于辅助创建3D场景) * */ // AxesHelper() 的参数代表坐标轴的线段长度 // 红色代表x轴,绿色代表y轴,蓝色代表z轴 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); /* * 创建轨道控制器 * */ const orbitControls = new OrbitControls(camera, renderer.domElement); // 更新控制器 orbitControls.update(); orbitControls.addEventListener('change', function () { // 输出相机位置 //console.log('camera.position', camera.position); }); /* * 创建一个线框球体 * */ // 新建球体 const geometry = new THREE.SphereGeometry( 1, 16, 16 ); // 创建材质 // MeshBasicMaterial材质不受光照影响 const material = new THREE.MeshBasicMaterial({ // 材质颜色 color: '#2ccdf1', // 将几何体渲染为线框。默认值为false(即渲染为平面多边形) wireframe: true, // 控制线框宽度(chrome上不好使) wireframeLinewidth: 5, // 定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round' wireframeLinejoin: 'round', }); // 新建网格(网格包含集合体和作用在几何体上面的材质) const cube = new THREE.Mesh(geometry, material); // 将网格添加到场景 scene.add(cube); /* * 渲染场景必加代码 (渲染循环) * */ // 渲染循环 function animate() { // 每秒执行60次 requestAnimationFrame(animate); // 更新控制器 orbitControls.update(); // 渲染场景 renderer.render(scene, camera); } // WebGL兼容性检查 if (WebGL.isWebGLAvailable()) { animate(); } else { const warning = WebGL.getWebGLErrorMessage(); container.value.appendChild(warning); } /** * 窗口变化自适应(必加代码) */ const onWindowResize = () => { // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 重置渲染器输出画布canvas尺寸 renderer.setSize(containerWidth, containerHeight); // aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高 // 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比 camera.aspect =containerWidth / containerHeight; // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix // 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) // 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效 camera.updateProjectionMatrix(); } // 监听浏览器窗口大小改变 window.addEventListener('resize', onWindowResize); }) </script> <style> </style> <style scoped> .container { height: 100vh; box-sizing: border-box; /* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/ overflow: hidden; } </style> *案例44 用深度网格材质创建一个立方体 <template> <div ref="container" className="container"></div> </template> <script setup> import * as THREE from 'three'; import WebGL from 'three/examples/jsm/capabilities/WebGL.js' // 引入轨道控制器扩展库OrbitControls.js import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js' import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; import {ref, onMounted} from 'vue' let container = ref(null) onMounted(() => { /* * * 创建场景(渲染必加代码) */ // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 创建场景 const scene = new THREE.Scene(); /* * * 创建摄像机(渲染必加代码) * */ // 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机) // 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的,一般为30) // 控制相机能看到的角度范围。 // 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄 // 参数 2:aspect长宽比,控制相机看到的画面的宽高比。 // 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化 // 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1 // 1 表示距离相机 1 个单位以内的物体不会被渲染 // 参数 4:far远截面,控制相机能看到的最大距离 // 1000 表示距离相机 1000 个单位以外的物体不会被渲染 const camera = new THREE.PerspectiveCamera(75, containerWidth / containerHeight, 0.1, 1000); // camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果 // 摄像机的位置 camera.position.set(2.35, 2.35, 2.35); // 摄像机聚焦的位置 camera.lookAt(0, 0, 0); // zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1 camera.zoom = 1 // 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】 camera.updateProjectionMatrix() /* * * 创建渲染器(渲染必加代码) * */ // 创建渲染器(three.js有好几种渲染器) const renderer = new THREE.WebGLRenderer(); // 设置渲染器尺寸 // 第三个参数(选填):false代表以较低分辨率渲染 renderer.setSize(containerWidth, containerHeight ); // 将渲染器放入文档中 container.value.appendChild(renderer.domElement); /* * 创建坐标轴对象(用于辅助创建3D场景) * */ // AxesHelper() 的参数代表坐标轴的线段长度 // 红色代表x轴,绿色代表y轴,蓝色代表z轴 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); /* * 创建轨道控制器 * */ const orbitControls = new OrbitControls(camera, renderer.domElement); // 更新控制器 orbitControls.update(); orbitControls.addEventListener('change', function () { // 输出相机位置 console.log('camera.position', camera.position); }); /* * 用深度网格材质创建一个立方体 * MeshDepthMaterial 是一种基于深度的材质。 * (这种材质不常用) * * 它会根据物体与相机的距离,将物体渲染为灰度颜色: * 距离相机近的物体显示为白色。 * 距离相机远的物体显示为黑色。 * 中间的物体显示为灰色。 * * MeshDepthMaterial 的特点: * 灰度显示:根据深度渲染为黑白灰颜色。 * 无光照:不受场景中灯光的影响。 * 简单高效:适合用于深度相关的效果。 * */ // 创建 深度网格材质 MeshDepthMaterial const depthMaterial = new THREE.MeshDepthMaterial(); // 创建几何体 const geometry = new THREE.BoxGeometry(0.5,0.5,0.5); // 创建网格对象 const cube1 = new THREE.Mesh(geometry, depthMaterial); cube1.position.set(2, 2, 2); scene.add(cube1); /* * 渲染场景必加代码 (渲染循环) * */ // 渲染循环 function animate() { // 每秒执行60次 requestAnimationFrame(animate); // 旋转立方体动画 cube1.rotation.x += 0.01; cube1.rotation.y += 0.01; // 更新控制器 orbitControls.update(); // 渲染场景 renderer.render(scene, camera); } // WebGL兼容性检查 if (WebGL.isWebGLAvailable()) { animate(); } else { const warning = WebGL.getWebGLErrorMessage(); container.value.appendChild(warning); } /** * 窗口变化自适应(必加代码) */ const onWindowResize = () => { // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 重置渲染器输出画布canvas尺寸 renderer.setSize(containerWidth, containerHeight); // aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高 // 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比 camera.aspect =containerWidth / containerHeight; // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix // 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) // 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效 camera.updateProjectionMatrix(); } // 监听浏览器窗口大小改变 window.addEventListener('resize', onWindowResize); }) </script> <style> </style> <style scoped> .container { height: 100vh; box-sizing: border-box; /* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/ overflow: hidden; } </style> *案例45 创建一个 标准网格材质(MeshStandardMaterial)的透明立方体 <template> <div ref="container" className="container"></div> </template> <script setup> import * as THREE from 'three'; import WebGL from 'three/examples/jsm/capabilities/WebGL.js' // 引入轨道控制器扩展库OrbitControls.js import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js' import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; import {ref, onMounted} from 'vue' let container = ref(null) onMounted(() => { /* * * 创建场景(渲染必加代码) */ // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 创建场景 const scene = new THREE.Scene(); /* * * 创建摄像机(渲染必加代码) * */ // 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机) // 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的,一般为30) // 控制相机能看到的角度范围。 // 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄 // 参数 2:aspect长宽比,控制相机看到的画面的宽高比。 // 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化 // 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1 // 1 表示距离相机 1 个单位以内的物体不会被渲染 // 参数 4:far远截面,控制相机能看到的最大距离 // 1000 表示距离相机 1000 个单位以外的物体不会被渲染 const camera = new THREE.PerspectiveCamera(30, containerWidth / containerHeight, 0.1, 1000); // camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果 // 摄像机的位置 camera.position.set(3.9, 3.9, 3.9); // 摄像机聚焦的位置 camera.lookAt(0, 0, 0); // zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1 camera.zoom = 1 // 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】 camera.updateProjectionMatrix() /* * * 创建渲染器(渲染必加代码) * */ // 创建渲染器(three.js有好几种渲染器) const renderer = new THREE.WebGLRenderer(); // 设置渲染器尺寸 // 第三个参数(选填):false代表以较低分辨率渲染 renderer.setSize(containerWidth, containerHeight ); // 将渲染器放入文档中 container.value.appendChild(renderer.domElement); /* * 创建轨道控制器 * */ const orbitControls = new OrbitControls(camera, renderer.domElement); // 更新控制器 orbitControls.update(); orbitControls.addEventListener('change', function () { // 输出相机位置 console.log('camera.position', camera.position); }); /* * 创建环境光 * MeshLambertMaterial材质的物体,没有光源对象是看不清的,所以要创建环境光 * */ // 第一个参数:环境光颜色 // 第二个参数:光照的强度,缺省值为 1 const AmbientLight = new THREE.AmbientLight( '#fff',2 ); // soft white light scene.add( AmbientLight ); /* * 创建一个 标准网格材质(MeshStandardMaterial)的透明立方体 * * */ // 新建立方体对象 const geometry = new THREE.BoxGeometry(1,1,1); // 创建材质 // MeshStandardMaterial是一种基于物理的标准材质 const material = new THREE.MeshStandardMaterial({ // 材质颜色 color: '#2ccdf1', // 启用透明 transparent: true, // 设置透明度 opacity: 0.35, // 渲染正面和背面 side: THREE.DoubleSide, }); // 新建网格(网格包含集合体和作用在几何体上面的材质) const cube = new THREE.Mesh(geometry, material); // 将网格添加到场景 scene.add(cube); /* * 创建平行光 * 常常用平行光来模拟太阳光 * */ // 第一个参数:光的颜色 // 第二个参数:光照强度 const DirectionalLight = new THREE.DirectionalLight( '#ffffff',3 ); scene.add( DirectionalLight ); // 设置平行光位置 DirectionalLight.position.set(1, 1.5, 0) /// 设置平行光的方向,让平行光照射球体 // target属性用于设置平行光的目标位置 // 平行光默认的目标位置为原点 (0,0,0) // 值可以是场景中的某个对象 DirectionalLight.target = cube /* * 渲染场景必加代码 (渲染循环) * */ // 渲染循环 function animate() { // 每秒执行60次 requestAnimationFrame(animate); // 更新控制器 orbitControls.update(); // 渲染场景 renderer.render(scene, camera); } // WebGL兼容性检查 if (WebGL.isWebGLAvailable()) { animate(); } else { const warning = WebGL.getWebGLErrorMessage(); container.value.appendChild(warning); } /** * 窗口变化自适应(必加代码) */ const onWindowResize = () => { // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 重置渲染器输出画布canvas尺寸 renderer.setSize(containerWidth, containerHeight); // aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高 // 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比 camera.aspect =containerWidth / containerHeight; // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix // 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) // 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效 camera.updateProjectionMatrix(); } // 监听浏览器窗口大小改变 window.addEventListener('resize', onWindowResize); }) </script> <style> </style> <style scoped> .container { height: 100vh; box-sizing: border-box; /* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/ overflow: hidden; } </style> *案例46 创建卡通风格材质的物体 <template> <div ref="container" className="container"></div> </template> <script setup> import * as THREE from 'three'; import WebGL from 'three/examples/jsm/capabilities/WebGL.js' // 引入轨道控制器扩展库OrbitControls.js import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js' import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; import {ref, onMounted} from 'vue' let container = ref(null) onMounted(() => { /* * * 创建场景(渲染必加代码) */ // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 创建场景 const scene = new THREE.Scene(); /* * * 创建摄像机(渲染必加代码) * */ // 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机) // 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的,一般为30) // 控制相机能看到的角度范围。 // 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄 // 参数 2:aspect长宽比,控制相机看到的画面的宽高比。 // 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化 // 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1 // 1 表示距离相机 1 个单位以内的物体不会被渲染 // 参数 4:far远截面,控制相机能看到的最大距离 // 1000 表示距离相机 1000 个单位以外的物体不会被渲染 const camera = new THREE.PerspectiveCamera(30, containerWidth / containerHeight, 0.1, 1000); // camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果 // 摄像机的位置 camera.position.set(3.9, 3.9, 3.9); // 摄像机聚焦的位置 camera.lookAt(0, 0, 0); // zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1 camera.zoom = 1 // 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】 camera.updateProjectionMatrix() /* * * 创建渲染器(渲染必加代码) * */ // 创建渲染器(three.js有好几种渲染器) const renderer = new THREE.WebGLRenderer(); // 设置渲染器尺寸 // 第三个参数(选填):false代表以较低分辨率渲染 renderer.setSize(containerWidth, containerHeight ); // 将渲染器放入文档中 container.value.appendChild(renderer.domElement); /* * 创建轨道控制器 * */ const orbitControls = new OrbitControls(camera, renderer.domElement); // 更新控制器 orbitControls.update(); orbitControls.addEventListener('change', function () { // 输出相机位置 console.log('camera.position', camera.position); }); /* * 创建坐标轴对象(用于辅助创建3D场景) * */ // AxesHelper() 的参数代表坐标轴的线段长度 // 红色代表x轴,绿色代表y轴,蓝色代表z轴 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); /* * 创建环境光 * MeshLambertMaterial材质的物体,没有光源对象是看不清的,所以要创建环境光 * */ // 第一个参数:环境光颜色 // 第二个参数:光照的强度,缺省值为 1 const AmbientLight = new THREE.AmbientLight( '#fff',1 ); // soft white light scene.add( AmbientLight ); /* * * 创建卡通风格材质的物体 * * MeshToonMaterial 是一种特殊的材质,它可以让 3D 物体看起来像卡通风格的画面 * MeshToonMaterial 是一种基于光照的材质,但它不像普通材质那样平滑过渡,而是将颜色分成几个明显的色块。 * 这种效果类似于卡通画中的阴影和高光,给人一种手绘的感觉。 * 在制作卡通风格的游戏或动画时需要用这种材质 * * MeshToonMaterial 的特点: * 色块化阴影:将阴影和高光分成明显的色块,而不是平滑过渡。 * 支持光照:可以根据场景中的灯光调整颜色。 * 简单易用:只需设置颜色和渐变贴图,就能实现卡通效果。 * */ // 创建 MeshToonMaterial 材质 const material = new THREE.MeshToonMaterial({ color: '#317fd7', // 设置颜色为绿色 gradientMap: null, // 渐变贴图(可选) }); // 创建一个立方体和一个球体 const sphereGeometry = new THREE.SphereGeometry( 0.5, 32, 16 ); const geometry = new THREE.BoxGeometry(0.8,0.8,0.8); // 创建球体网格 const sphere = new THREE.Mesh( sphereGeometry, material ); sphere.position.set(1.3,0,0) scene.add( sphere ); // 创建立方体网格 const cube = new THREE.Mesh(geometry, material); scene.add(cube); /* * 创建平行光 * 常常用平行光来模拟太阳光 * */ // 第一个参数:光的颜色 // 第二个参数:光照强度 const DirectionalLight = new THREE.DirectionalLight( '#ffffff',4 ); scene.add( DirectionalLight ); // 设置平行光位置 // .normalize()确保方向向量长度为1,使光照和阴影计算符合物理规律,避免因向量长度导致的意外结果 DirectionalLight.position.set(2, 2, 0).normalize() /// 设置平行光的方向,让平行光照射球体 // target属性用于设置平行光的目标位置 // 平行光默认的目标位置为原点 (0,0,0) // 值可以是场景中的某个对象 DirectionalLight.target = cube /* * 渲染场景必加代码 (渲染循环) * */ // 渲染循环 function animate() { // 每秒执行60次 requestAnimationFrame(animate); // 更新控制器 orbitControls.update(); // 渲染场景 renderer.render(scene, camera); } // WebGL兼容性检查 if (WebGL.isWebGLAvailable()) { animate(); } else { const warning = WebGL.getWebGLErrorMessage(); container.value.appendChild(warning); } /** * 窗口变化自适应(必加代码) */ const onWindowResize = () => { // 获取容器的实际宽高 const containerWidth = container.value.clientWidth; const containerHeight = container.value.clientHeight; // 重置渲染器输出画布canvas尺寸 renderer.setSize(containerWidth, containerHeight); // aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高 // 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比 camera.aspect =containerWidth / containerHeight; // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix // 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源) // 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效 camera.updateProjectionMatrix(); } // 监听浏览器窗口大小改变 window.addEventListener('resize', onWindowResize); }) </script> <style> </style> <style scoped> .container { height: 100vh; box-sizing: border-box; /* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/ overflow: hidden; } </style>
three.js之特殊材质效果由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“three.js之特殊材质效果”