three.js之特殊材质效果
*案例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属性可以获取或者设置摄像机的缩放倍数,其默认值为1camera.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属性可以获取或者设置摄像机的缩放倍数,其默认值为1camera.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属性可以获取或者设置摄像机的缩放倍数,其默认值为1camera.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 的特点:* 灰度显示:根据深度渲染为黑白灰颜色。* 无光照:不受场景中灯光的影响。* 简单高效:适合用于深度相关的效果。* */// 创建 深度网格材质 MeshDepthMaterialconst 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属性可以获取或者设置摄像机的缩放倍数,其默认值为1camera.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材质的物体,没有光源对象是看不清的,所以要创建环境光* */// 第一个参数:环境光颜色// 第二个参数:光照的强度,缺省值为 1const AmbientLight = new THREE.AmbientLight( '#fff',2 ); // soft white lightscene.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属性可以获取或者设置摄像机的缩放倍数,其默认值为1camera.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材质的物体,没有光源对象是看不清的,所以要创建环境光* */// 第一个参数:环境光颜色// 第二个参数:光照的强度,缺省值为 1const AmbientLight = new THREE.AmbientLight( '#fff',1 ); // soft white lightscene.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之特殊材质效果
*案例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 // 引…...
Qt常用控件之日历QCalendarWidget
日历QCalendarWidget QCalendarWidget 是一个日历控件。 QCalendarWidget属性 属性说明selectDate当前选中日期。minimumDate最小日期。maximumDate最大日期。firstDayOfWeek设置每周的第一天是周几(影响日历的第一列是周几)。gridVisible是否显示日历…...
vxe-table 如何实现跟 Excel 一样的数值或金额的负数自动显示红色字体
vxe-table 如何实现跟 Excel 一样的数值或金额的负数自动显示红色字体,当输入的值为负数时,会自动显示红色字体,对于数值或者金额输入时该功能就非常有用了。 查看官网:https://vxetable.cn gitbub:https://github.co…...
DINOv2 + yolov8 + opencv 检测卡车的可拉拽雨覆是否完全覆盖
最近是接了一个需求咨询图像处理类的,甲方要在卡车过磅的地方装一个摄像头用检测卡车的车斗雨覆是否完全, 让我大致理了下需求并对技术核心做下预研究 开发一套图像处理软件,能够实时监控经过的卡车并判断其车斗的雨覆状态。 系统需具备以下…...
算法日记27:完全背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
一、暴力搜索(DFS) O ( n 2 ) O(n^2) O(n2) 1.1)思路解析 1、注意和01背包的区别在于每个物品可以无限次选择 注意在完全背包中,当一个物品被选择过一次,我们仍然需要考虑是否继续选择这个物品 01背包: …...
Linux 命令大全完整版(14)
5. 文件管理命令 chgrp(change group) 功能说明:变更文件或目录的所属群组。语 法:chgrp [-cfhRv][–help][–version][所属群组][文件或目录…] 或 chgrp [-cfhRv][–help][–version][–reference<参考文件或目录>][文件或目录…]补充说明&…...
基于 DeepSeek LLM 本地知识库搭建开源方案(AnythingLLM、Cherry、Ragflow、Dify)认知
写在前面 博文内容涉及 基于 Deepseek LLM 的本地知识库搭建使用 ollama 部署 Deepseek-R1 LLM知识库能力通过 Ragflow、Dify 、AnythingLLM、Cherry 提供理解不足小伙伴帮忙指正 😃,生活加油 我站在人潮中央,思考这日日重复的生活。我突然想,…...
Could not initialize class io.netty.util.internal.Platfor...
异常信息: Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.PlatformDependent0 Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.reflect.InaccessibleObjec…...
【书生大模型实战营】玩转HF/魔搭/魔乐社区-L0G4000
本文是书生大模型实战营系列的第4篇,本文的主题是:玩转HF/魔搭/魔乐社区。 1.开源大模型社区总览 开源不仅仅是一种技术模式,更是一种精神的体现。它打破了知识的壁垒,让技术平权成为可能。近年来,开源大模型社区蓬勃…...
2025年华为手机解锁BL的方法
注:本文是我用老机型测试的,新机型可能不适用 背景 华为官方已经在2018年关闭了申请BL解锁码的通道,所以华为手机已经无法通过官方获取解锁码。最近翻出了一部家里的老手机华为畅玩5X,想着能不能刷个系统玩玩,但是卡…...
了解 RAG 第二部分:经典 RAG 的工作原理
在本系列的第一篇文章中,我们介绍了检索增强生成 (RAG) ,解释了扩展传统大型语言模型 (LLM)功能的必要性。我们还简要概述了 RAG 的核心思想:从外部知识库检索上下文相关的信息,以确保 LLM 生成准确且最新的信息,而不会…...
50周学习go语言:第四周 函数与错误处理深度解析
第四周 函数与错误处理深度解析 以下是第4周函数基础的深度教程,包含两个完整案例和详细实现细节: 第四周:函数与错误处理深度解析 一、函数定义与参数传递 1. 基础函数结构 // 基本语法 func 函数名(参数列表) 返回值类型 {// 函数体 }// …...
debian 12安装 postgresql 17
按照官方文档安装,即可安装成功 https://www.postgresql.org/download/linux/debian/ 添加存储库 #添加存储库 sudo apt install -y postgresql-common#执行 存储库内 命令,自动处理某些东西 sudo /usr/share/postgresql-common/pgdg/apt.postgresql.o…...
C++....................4
1. using namespace std; class mystring { private:char* p;int len;// 辅助函数:复制字符串void copy(const char* source) {len strlen(source);p new char[len 1];strcpy(p, source);}// 辅助函数:释放内存void release() {if (…...
图书馆系统源码详解
本项目是一个基于Scala语言开发的图书馆管理系统。系统主要由以下几个部分组成:数据访问层(DAO)、数据模型层(Models)、服务层(Service)以及用户界面层(UI)。以下是对项目…...
Node.js中如何修改全局变量的几种方式
Node.js中如何修改全局变量。我需要先理解他们的需求。可能他们是在开发过程中遇到了需要跨模块共享数据的情况,或者想要配置一些全局可访问的设置。不过,使用全局变量可能存在一些问题,比如命名冲突、难以维护和测试困难,所以我得…...
基于javaweb的SpringBoot个人博客系统设计和实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
厦大团队:DeepSeek大模型概念、技术与应用实践 140页PDF完整版下载
DeepSeek使用教程系列: 厦门大学: DeepSeek大模型概念、技术与应用实践 140页PDF完整版文件 厦大团队:DeepSeek大模型概念、技术与应用实践(140页PPT读懂大模型).pdf https://pan.baidu.com/s/1de4UIxqPsvMBIYcpen_M-…...
【Blender】二、建模篇--05,阵列修改器与晶格形变
阵列修改器是bender里面一个比较常用的修改器,所以我们单独开口来讲,我们会先从几片树叶出发,然后我们用阵列修改器把这几片树叶变成这样的造型和这样的造型。这两个造型分别就代表着阵列修改器最常用的两种偏移方法,我们现在就开始我们先来做几个树叶。 1.树叶建模 首先…...
#渗透测试#批量漏洞挖掘#畅捷通T+远程命令执行漏洞
免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 一、漏洞概况 二、攻击特征 三、应急处置…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
