three.js使用环境贴图创建虚假的反光效果,使用CubeTextureLoader创建全景贴图,使用envMap创建静态环境贴图(vue中使用three.js82)

编程入门 行业动态 更新时间:2024-10-21 20:38:54

three.js使用环境<a href=https://www.elefans.com/category/jswz/34/1766749.html style=贴图创建虚假的反光效果,使用CubeTextureLoader创建全景贴图,使用envMap创建静态环境贴图(vue中使用three.js82)"/>

three.js使用环境贴图创建虚假的反光效果,使用CubeTextureLoader创建全景贴图,使用envMap创建静态环境贴图(vue中使用three.js82)

使用环境贴图创建虚假的反光效果

  • 1.demo效果
  • 2. 实现要点
    • 2.1 创建场景的全景贴图
    • 2.2 创建场景中的模型
    • 2.3 属性更新处理
    • 2.4 模型旋转更新
  • 3. demo代码

1.demo效果


2. 实现要点

2.1 创建场景的全景贴图

在创建场景函数中,使用 CubeTextureLoader 创建全景贴图,然后将全景贴图赋值给场景的 background 属性

// 创建场景
createScene() {this.scene = new THREE.Scene()const publicPath = process.env.BASE_URL//创建全景贴图设置为场景背景this.scene.background = new THREE.CubeTextureLoader().setPath(`${publicPath}textures/cubemap/parliament/`).load(['posx.jpg','negx.jpg','posy.jpg','negy.jpg','posz.jpg','negz.jpg'])
}

2.2 创建场景中的模型

模型包括一个立方体和一个球体,要注意一下几点

  • 创建材质
    创建好材质后把材质的环境贴图 (material.envMap属性) 设置为场景的背景,即上一步创建好的全景贴图
  • 创建方块
    只需要使用BoxGeometry创建一个立方体模型,然后和上面创建的材质共同创建Mesh对象即可
  • 创建球体
    使用SphereGeometry创建一个球体模型,这里需要 clone一下材质 ,然后使用克隆的材质和球体模型创建Mesh对象
// 创建模型
createModels() {const material = new THREE.MeshPhongMaterial()material.envMap = this.scene.background //场景背景设置为材质的环境贴图//创建方块const boxGeometry = new THREE.BoxGeometry(10, 15, 15)this.cube = new THREE.Mesh(boxGeometry, material)this.cube.rotation.y = 0.5this.cube.position.x = -12this.cube.position.y = 5this.scene.add(this.cube)//创建球体const sphereGeometry = new THREE.SphereGeometry(10, 15, 15)this.sphere = new THREE.Mesh(sphereGeometry, material.clone()) //材质需要克隆一份,否则方块材质改变球体也会跟着发生改变this.sphere.rotation.y = -0.5this.sphere.position.x = 12this.sphere.position.y = 5this.scene.add(this.sphere)
}

2.3 属性更新处理

为满足demo可以为方块选择不同的纹理贴图和对方块和球体调整反射光折射率,这里需要做一些处理

  • 方块纹理处理
    如果选择的纹理贴图不是none则加载对应的map贴图和normal贴图,赋值到方块材质的map属性和normalMap属性上,同时设置方块材质的normalScale属性,用来调整法线贴图的凹凸深度,如果没有为方块选择纹理贴图,将方块的材质重置为envMap是场景背景的材质
  • 反射光折射率处理
    方块和球体都需要处理,将球体和方块各自的材质中的material.reflectivity属性设置为页面中设置的值即可
  • 材质更新
    由于调整过参数后模型的材质会发生改变,所以需要显示的告诉计算机重新编译材质,将它们材质的material.needsUpdate 属性设置为true

2.4 模型旋转更新

demo中勾选了rotate后,方块可以立方体可以旋转,在这里需要支持一下

//模型旋转更新
updateRotation() {if (this.properties.rotate) {this.cube.rotation.x += 0.01this.cube.rotation.y += 0.01this.sphere.rotation.y -= 0.01}
}

3. demo代码

<template><div><div id="container" /><div class="controls-box"><section><el-row><el-checkbox v-model="properties.rotate">rotate</el-checkbox></el-row><el-row><div v-for="(item,key) in properties" :key="key"><div v-if="item&&item.name!=undefined"><el-col :span="8"><span class="vertice-span">{{ item.name }}</span></el-col><el-col :span="13"><el-slider v-model="item.value" :min="item.min" :max="item.max" :step="item.step" :format-tooltip="formatTooltip" @change="propertiesChange" /></el-col><el-col :span="3"><span class="vertice-span">{{ item.value }}</span></el-col></div></div></el-row><el-row><el-col :span="8" class="label-col"><label>texture</label></el-col><el-col :span="16"><el-select v-model="properties.textureType" placeholder="请选择" @change="propertiesChange"><el-option v-for="item in texturesOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-col></el-row></section></div></div>
</template><script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
export default {data() {return {texturesOptions: [{value: 'bathroom',label: 'bathroom'},{value: 'plaster',label: 'plaster'},{value: 'metal-floor',label: 'metal-floor'},{value: 'none',label: 'none'}],properties: {normalScale: {name: 'normalScale',value: 1,min: -2,max: 2,step: 0.1},reflectivity: {name: 'reflectivity',value: 1,min: 0,max: 2,step: 0.1},textureType: 'none',rotate: false},cube: null,sphere: null,camera: null,scene: null,renderer: null,controls: null,sphereLightMesh: null,pointLight: null,invert: 1,phase: 0}},mounted() {this.init()},methods: {formatTooltip(val) {return val},// 初始化init() {this.createScene() // 创建场景this.createCamera() // 创建相机this.createLight() // 创建光源this.createModels() // 创建模型this.createRender() // 创建渲染器this.createControls() // 创建控件对象this.render() // 渲染},// 创建场景createScene() {this.scene = new THREE.Scene()const publicPath = process.env.BASE_URL//创建全景贴图设置为场景背景this.scene.background = new THREE.CubeTextureLoader().setPath(`${publicPath}textures/cubemap/parliament/`).load(['posx.jpg','negx.jpg','posy.jpg','negy.jpg','posz.jpg','negz.jpg'])},// 创建模型createModels() {const material = new THREE.MeshPhongMaterial()material.envMap = this.scene.background //场景背景设置为材质的环境贴图//创建方块const boxGeometry = new THREE.BoxGeometry(10, 15, 15)this.cube = new THREE.Mesh(boxGeometry, material)this.cube.rotation.y = 0.5this.cube.position.x = -12this.cube.position.y = 5this.scene.add(this.cube)//创建球体const sphereGeometry = new THREE.SphereGeometry(10, 15, 15)this.sphere = new THREE.Mesh(sphereGeometry, material.clone()) //材质需要克隆一份,否则方块材质改变球体也会跟着发生改变this.sphere.rotation.y = -0.5this.sphere.position.x = 12this.sphere.position.y = 5this.scene.add(this.sphere)},// 创建光源createLight() {// 环境光const ambientLight = new THREE.AmbientLight(0xffffff) // 创建环境光this.scene.add(ambientLight) // 将环境光添加到场景const spotLight = new THREE.SpotLight(0xffffff) // 创建聚光灯spotLight.position.set(0, 30, 30)spotLight.intensity = 2.2this.scene.add(spotLight)// 点光源const pointColor = '#ff5808'this.pointLight = new THREE.PointLight(pointColor)this.pointLight.intensity = 4.5this.scene.add(this.pointLight)this.createSmallSphereLight()},// 创建球形光源createSmallSphereLight() {const sphereLight = new THREE.SphereGeometry(0.2)const sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25})this.sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial)this.sphereLightMesh.castShadow = true// this.sphereLightMesh.position = new THREE.Vector3(3, 3, 3)this.scene.add(this.sphereLightMesh)},// 创建相机createCamera() {const element = document.getElementById('container')const width = element.clientWidth // 窗口宽度const height = element.clientHeight // 窗口高度const k = width / height // 窗口宽高比// PerspectiveCamera( fov, aspect, near, far )this.camera = new THREE.PerspectiveCamera(45, k, 0.1, 1000)this.camera.position.set(0, 12, 68) // 设置相机位置this.camera.lookAt(new THREE.Vector3(0, 0, 0)) // 设置相机方向this.scene.add(this.camera)},// 创建渲染器createRender() {const element = document.getElementById('container')this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })this.renderer.setSize(element.clientWidth, element.clientHeight) // 设置渲染区域尺寸this.renderer.shadowMap.enabled = true // 显示阴影// this.renderer.shadowMap.type = THREE.PCFSoftShadowMapthis.renderer.setClearColor(0xeeeeee, 1) // 设置背景颜色element.appendChild(this.renderer.domElement)},propertiesChange() {const publicPath = process.env.BASE_URL//如果不为none为方块加载纹理贴图if (this.properties.textureType !== 'none') {const texture = new THREE.TextureLoader().load(`${publicPath}textures/general/` +this.properties.textureType +'.jpg')this.cube.material.map = textureconst normal = new THREE.TextureLoader().load(`${publicPath}textures/general/` +this.properties.textureType +'-normal.jpg')this.cube.material.normalMap = normal// 更新法线缩放this.cube.material.normalScale.set(this.properties.normalScale.value,this.properties.normalScale.value) // normalScale(x,y)} else {this.cube.material = new THREE.MeshPhongMaterial({envMap: this.scene.background})}//更新模型的材质折射率this.cube.material.reflectivity = this.properties.reflectivity.valuethis.sphere.material.reflectivity = this.properties.reflectivity.value//更新材质中的纹理this.cube.material.needsUpdate = truethis.sphere.material.needsUpdate = true},//模型旋转更新updateRotation() {if (this.properties.rotate) {this.cube.rotation.x += 0.01this.cube.rotation.y += 0.01this.sphere.rotation.y -= 0.01}},//球形光运动smallShpereLightAnimation() {if (this.phase > 2 * Math.PI) {this.invert = this.invert * -1this.phase -= 2 * Math.PI} else {this.phase += 0.03}this.sphereLightMesh.position.z = +(21 * Math.sin(this.phase))this.sphereLightMesh.position.x = -14 + 14 * Math.cos(this.phase)if (this.invert < 0) {const pivot = 0this.sphereLightMesh.position.x =this.invert * (this.sphereLightMesh.position.x - pivot) + pivot}this.pointLight.position.copy(this.sphereLightMesh.position) // 把小球光源的坐标复制给点光源},render() {requestAnimationFrame(this.render)this.smallShpereLightAnimation() //球形光位置更新this.updateRotation() //模型旋转更新this.renderer.render(this.scene, this.camera)},// 创建控件对象createControls() {this.controls = new OrbitControls(this.camera, this.renderer.domElement)}}
}
</script><style>
#container {position: absolute;width: 100%;height: 100%;
}
.controls-box {position: absolute;right: 5px;top: 5px;width: 300px;padding: 10px;background-color: #fff;border: 1px solid #c3c3c3;
}
.label-col {padding: 8px 5px;
}.vertice-span {line-height: 38px;padding: 0 2px 0 10px;
}
</style>

更多推荐

three.js使用环境贴图创建虚假的反光效果,使用CubeTextureLoader创建全景贴图,使用envMap创建静态环境贴图(vue中使用three.j

本文发布于:2024-03-09 05:52:26,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1724055.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:贴图   全景   环境   反光   静态

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!