使用凹凸贴图创建皱纹
1.demo效果2. 实现要点2.1 创建地板2.2 创建凹凸贴图的物体2.3 创建普通贴图的物体 3. demo代码1.demo效果
2. 实现要点
2.1 创建地板
createFloor() {const publicPath = process.env.BASE_URLconst floorTex = new THREE.TextureLoader().load(`${publicPath}textures/general/floor-wood.jpg`)const plane = new THREE.Mesh(new THREE.BoxGeometry(200, 100, 0.1, 30),new THREE.MeshPhongMaterial({color: 0x3c3c3c,map: floorTex}))plane.position.y = -7.5plane.rotation.x = -0.5 * Math.PIthis.scene.add(plane)}
2.2 创建凹凸贴图的物体
通过凹凸贴图可以实现材质表面不同深度的凹凸,使物体更有真实感,实现过程很简单
需要准备两个纹理贴图
一个用来设置material.map 属性,用作材质的普通贴图
一个用来设置material.bumpmap属性,用作材质的凹凸贴图
除此之外要想审查凹凸纹理效果material还有一个bumpScale属性要设置
createMesh(geom, imageFile, bump) {const publicPath = process.env.BASE_URLconst texture = new THREE.TextureLoader().load(`${publicPath}textures/general/` + imageFile)puteVertexNormals()const mat = new THREE.MeshPhongMaterial()mat.map = textureif (bump) {const bump = new THREE.TextureLoader().load(`${publicPath}textures/general/` + bump)mat.bumpMap = bumpmat.bumpScale = 0.2}const mesh = new THREE.Mesh(geom, mat)return mesh}
//创建带凹凸贴图的物体this.cube2 = this.createMesh(new THREE.BoxGeometry(15, 15, 2),'stone.jpg','stone-bump.jpg')this.cube2.rotation.y = 0.5this.cube2.position.x = -12this.scene.add(this.cube2)
2.3 创建普通贴图的物体
//创建没有凹凸贴图的物体this.cube1 = this.createMesh(new THREE.BoxGeometry(15, 15, 2),'stone.jpg')this.cube1.rotation.y = -0.5this.cube1.position.x = 12this.scene.add(this.cube1)
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: 'stone',label: 'stone'},{value: 'weave',label: 'weave'}],properties: {bumpScale: {name: 'bumpScale',value: 0.2,min: -2,max: 2,step: 0.1},textureType: 'stone',rotate: false},cube1: null,cube2: null,camera: null,scene: null,renderer: null,controls: null}},mounted() {this.init()},methods: {formatTooltip(val) {return val},// 初始化init() {this.createScene() // 创建场景this.createModels() // 创建模型this.createLight() // 创建光源this.createCamera() // 创建相机this.createRender() // 创建渲染器this.createControls() // 创建控件对象this.render() // 渲染},// 创建场景createScene() {this.scene = new THREE.Scene()},// 创建模型createModels() {//创建没有凹凸贴图的物体this.cube1 = this.createMesh(new THREE.BoxGeometry(15, 15, 2),'stone.jpg')this.cube1.rotation.y = -0.5this.cube1.position.x = 12this.scene.add(this.cube1)//创建带凹凸贴图的物体this.cube2 = this.createMesh(new THREE.BoxGeometry(15, 15, 2),'stone.jpg','stone-bump.jpg')this.cube2.rotation.y = 0.5this.cube2.position.x = -12this.scene.add(this.cube2)// console.log(this.cube2.geometry.faceVertexUvs)this.createFloor()},createMesh(geom, imageFile, bump) {const publicPath = process.env.BASE_URLconst texture = new THREE.TextureLoader().load(`${publicPath}textures/general/` + imageFile)puteVertexNormals()const mat = new THREE.MeshPhongMaterial()mat.map = textureif (bump) {const bump = new THREE.TextureLoader().load(`${publicPath}textures/general/` + bump)mat.bumpMap = bumpmat.bumpScale = 0.2}const mesh = new THREE.Mesh(geom, mat)return mesh},createFloor() {const publicPath = process.env.BASE_URLconst floorTex = new THREE.TextureLoader().load(`${publicPath}textures/general/floor-wood.jpg`)const plane = new THREE.Mesh(new THREE.BoxGeometry(200, 100, 0.1, 30),new THREE.MeshPhongMaterial({color: 0x3c3c3c,map: floorTex}))plane.position.y = -7.5plane.rotation.x = -0.5 * Math.PIthis.scene.add(plane)},// 创建光源createLight() {// 环境光const ambientLight = new THREE.AmbientLight(0x242424, 0.1) // 创建环境光this.scene.add(ambientLight) // 将环境光添加到场景const spotLight = new THREE.SpotLight(0xffffff) // 创建聚光灯spotLight.position.set(0, 30, 30)spotLight.intensity = 1.2this.scene.add(spotLight)},// 创建相机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, 38) // 设置相机位置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_URLconst texture = new THREE.TextureLoader().load(`${publicPath}textures/general/` + this.properties.textureType + '.jpg')this.cube1.material.map = texturethis.cube2.material.map = textureconst bump = new THREE.TextureLoader().load(`${publicPath}textures/general/` +this.properties.textureType +'-bump.jpg')this.cube2.material.bumpMap = bumpthis.cube2.material.bumpScale = this.properties.bumpScale.value},updateRotation() {if (this.properties.rotate) {this.cube1.rotation.y += 0.01this.cube2.rotation.y -= 0.01}},render() {this.updateRotation()this.renderer.render(this.scene, this.camera)requestAnimationFrame(this.render)},// 创建控件对象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>