目次
素材と質感を知る
three.js のマテリアルは、ジオメトリの表面のマテリアルです。すべてのマテリアルは Material から継承されます。ThreeJSの素材は、基本素材、深度素材、法線ベクトル素材、琥珀素材、フォン素材、標準素材、シェーダー素材、基本線素材、点線素材に分けられます。
マテリアルはオブジェクトの皮膚のようなもので、ジオメトリの外観を決定します。たとえば、マテリアルは、ジオメトリが金属または木に見えるかどうか、透明かどうか、色などを定義し、レンダリングのためにシーンに追加する前にメッシュに追加できます。この章では、Three.js の API によって提供されるすべてのマテリアルに慣れるようにガイドし、これらのマテリアルを使用して精巧な 3 次元オブジェクトを作成する方法も学びます。
テクスチャの基本クラスは Texture です。通常、このクラスを使用して、画像をそのプロパティ Image に渡すことによってテクスチャを構築します。テクスチャはマテリアルのプロパティであり、マテリアルとジオメトリ Geotry がメッシュを構成し、レンダリングのためにシーンに追加されます。テクスチャはオブジェクトの表面がどのように見えるかを決定し、マテリアルはオブジェクトが持つ「気質」の種類を決定します。
モデル マテリアルの色を変更する
たとえば、ジオメトリを設定し、後でその色を変更したい場合は、次の方法で行うことができます。
モデルにテクスチャを追加する
ジオメトリにテクスチャを追加するのは非常に簡単です。テクスチャ マップを準備してから、公式ドキュメントに記載されているケースを参照してください。
テクスチャ共通プロパティの使用
テクスチャには多くのプロパティがあります. 詳細については、次の公式ドキュメントを参照してください. 次に、いくつかの重要なプロパティに焦点を当てます。
テクスチャ オフセット設定:
テクスチャの回転設定:
// 设置纹理旋转 45deg
doorColorTexture.center.set(0.5,0.5) // 设置旋转原点
doorColorTexture.rotation = Math.PI / 4
テクスチャの繰り返し設定:
// 设置纹理重复
doorColorTexture.repeat.set(2,3)
// 设置纹理重复模式
doorColorTexture.wrapS = THREE.RepeatWrapping // 水平无限重复
doorColorTexture.wrapT = THREE.MirroredRepeatWrapping // 垂直镜像重复
テクスチャ表示アルゴリズム
テクスチャ表示のアルゴリズムは、弊社が提供する以下の公式 API 関数を通じて実現されます。
// texture纹理显示设置
doorColorTexture.minFilter = THREE.NearestFilter
doorColorTexture.magFilter = THREE.NearestFilter
// texture纹理显示设置
doorColorTexture.minFilter = THREE.LinearFilter
doorColorTexture.magFilter = THREE.LinearFilter
粗さを設定
次のように、ジオメトリに粗さを設定して表面を滑らかにし、反射光がより明確になるようにすることもできます。
もちろん、一部のテクスチャWeb サイトから提供された資料を使用して、特定のジオメトリに関連する詳細な機能を作成できます。
テクスチャの読み込みの進行状況
プロジェクトの画像リソースが大きすぎる場合、次の方法で読み込みの進行状況を視覚化できます。
ロード マネージャーを作成します。
// 设置加载管理器
const loadingManager = new THREE.loadingManager()
ロード後に 3 つによって提供されるパラメーターを入れます。
// 设置三种情况
const event = {}
event.onLoad = () =>{
console.log('图片加载成功');
}
event.onProgress = (url,num,total) =>{
console.log('图片加载完成:',url);
console.log('图片加载进度:',num);
console.log('图片总数:',total);
console.log('加载进度的百分比:',((num/total)*100).toFixed(2)+"%")
}
event.onError = (e) =>{
console.log('图片加载出现错误');
console.log(e);
}
// 设置加载管理器
const loadingManager = new THREE.LoadingManager(
event.onLoad,
event.onProgress,
event.onError
)
// 导入纹理
const textureLoader = new THREE.TextureLoader(loadingManager)
const doorColorTexture = textureLoader.load(img)
もちろん、次のようにインターフェイスに進行状況を表示できます。
var div = document.createElement("div")
div.style.width = "200px"
div.style.height = "200px"
div.style.position = "fixed"
div.style.right = 0
div.style.top = 0
div.style.color = "#fff"
document.body.appendChild(div)
私が書いたケースは 1 つの写真だけなので、読み込み速度は非常に高速です. 後の段階で多くのプロジェクト資料がある場合、これは次のように明らかな効果があります:
環境マップの設定
環境マップは、ジオメトリの全身に絵を貼り付けたようなもので、現在の空間にあるように感じさせます.もちろん、商店街や田園地帯などの実際の絵をここに使用することもできます.
注: 使用する画像の解像度とサイズは一貫している必要があります。一貫していないと、読み込まれません。
// 设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader()
const envMapTexture = cubeTextureLoader.load([img1,img2,img3,img4,img5,img6])
// 创建球物体
const sphereGeometry = new THREE.SphereGeometry(1,20,20)
// 球模型渲染几何体
const material = new THREE.MeshStandardMaterial({
metalness:0.7, // 设置金属材质
roughness:0.1, // 设置光滑度
envMap:envMapTexture
})
const mesh = new THREE.Mesh(sphereGeometry,material)
scene.add(mesh)
もちろん、次のように、背景を環境に追加して、スタイル全体をよりリアルにすることもできます。
// 给场景添加背景
scene.background = envMapTexture
もちろん、マテリアルの envMap 属性を設定する必要はありません。次の設定を設定して、現在のすべてのページに同じ背景を追加することもできます。
もちろん、必ずしも 6 枚の写真が必要というわけではありません. パノラマでも 3D ビジュアライゼーションを実現できます. この方法は、目の前に世界地図が表示されるのと似ていますが、平面図では表示されませんが、球体で表示すると、3D 効果も感じることができます. パノラマの実現は次のようになります。
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
// 添加hdr环境图
const rgbeLoader = new RGBELoader()
rgbeLoader.loadAsync("/src/public/2.hdr").then((texture)=>{
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture
scene.environment = texture
})
マテリアルとテクスチャの使用については以上です. 詳細については、公式 Web サイトを参照して、この記事のコード ノートを参照してください。
import * as THREE from 'three';
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// import img from '../public/木质纹理.jpg'
// import img1 from '../public/1.jpg'
// import img2 from '../public/2.jpg'
// import img3 from '../public/3.jpg'
// import img4 from '../public/4.jpg'
// import img5 from '../public/5.jpg'
// import img6 from '../public/6.jpg'
// import img7 from "../public/1.hdr"
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
// 添加hdr环境图
const rgbeLoader = new RGBELoader()
rgbeLoader.loadAsync("/src/public/2.hdr").then((texture)=>{
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture
scene.environment = texture
})
// 1.创建场景
const scene = new THREE.Scene();
// 2.创建相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
// 设置x、y、z轴坐标,即设置相机位置
camera.position.set(0,0,10)
// 将相机添加到场景之中
scene.add(camera)
// 3.添加物体,创建几何体
// const geometry = new THREE.BoxGeometry(3,3,3)
// var div = document.createElement("div")
// div.style.width = "200px"
// div.style.height = "200px"
// div.style.position = "fixed"
// div.style.right = 0
// div.style.top = 0
// div.style.color = "#fff"
// document.body.appendChild(div)
// // 设置三种情况
// const event = {}
// event.onLoad = () =>{
// console.log('图片加载成功');
// }
// event.onProgress = (url,num,total) =>{
// console.log('图片加载完成:',url);
// console.log('图片加载进度:',num);
// console.log('图片总数:',total);
// let value = ((num/total)*100).toFixed(2)+"%"
// div.innerHTML = value
// console.log('加载进度的百分比:',((num/total)*100).toFixed(2)+"%")
// }
// event.onError = (e) =>{
// console.log('图片加载出现错误');
// console.log(e);
// }
// // 设置加载管理器
// const loadingManager = new THREE.LoadingManager(
// event.onLoad,
// event.onProgress,
// event.onError
// )
// // 导入纹理
// const textureLoader = new THREE.TextureLoader(loadingManager)
// const doorColorTexture = textureLoader.load(img)
// // 设置纹理偏移
// doorColorTexture.offset.x = 0.5
// doorColorTexture.offset.y = 0.5
// doorColorTexture.offset.set(0.5,0,5)
// // 设置纹理旋转 45deg
// doorColorTexture.center.set(0.5,0.5) // 设置旋转原点
// doorColorTexture.rotation = Math.PI / 4
// // 设置纹理重复
// doorColorTexture.repeat.set(2,3)
// // 设置纹理重复模式
// doorColorTexture.wrapS = THREE.RepeatWrapping // 水平无限重复
// doorColorTexture.wrapT = THREE.MirroredRepeatWrapping // 垂直镜像重复
// texture纹理显示设置
// doorColorTexture.minFilter = THREE.NearestFilter
// doorColorTexture.magFilter = THREE.NearestFilter
// doorColorTexture.minFilter = THREE.LinearFilter
// doorColorTexture.magFilter = THREE.LinearFilter
// 设置cube纹理加载器
// const cubeTextureLoader = new THREE.CubeTextureLoader()
// const envMapTexture = cubeTextureLoader.load([img1,img2,img3,img4,img5,img6])
// 创建球物体
const sphereGeometry = new THREE.SphereGeometry(1,20,20)
// 球模型渲染几何体
const material = new THREE.MeshStandardMaterial({
metalness:0.7, // 设置金属材质
roughness:0.1, // 设置光滑度
// envMap:envMapTexture
})
const mesh = new THREE.Mesh(sphereGeometry,material)
scene.add(mesh)
// // 给场景添加背景
// scene.background = envMapTexture
// 给场景所有的物体添加默认的环境贴图
// scene.environment = envMapTexture
// // 网格模型渲染几何体
// const material = new THREE.MeshStandardMaterial({
// color:'#fffff00',
// })
// const mesh = new THREE.Mesh(geometry,material)
// scene.add(mesh)
// 4.初始化渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth,window.innerHeight)
document.body.appendChild(renderer.domElement)
// // 添加一个平行光
// const directionalLight = new THREE.DirectionalLight(0xffffff,1)
// // 设置光源方向
// directionalLight.position.set(8,10,5)
// // 方向光指向对象网格模型Mesh,即照射的对象,可以不设置,默认的位置是0,0,0
// directionalLight.target = mesh
// scene.add(directionalLight)
// 添加一个环境光
const ambient = new THREE.AmbientLight(0xffffff,0.9)
scene.add(ambient)
// // 创建一个点光源
// const pointLight = new THREE.PointLight(0xffffff,1.0)
// // 设置点光源位置
// pointLight.position.set(0,5,0)
// scene.add(pointLight)
// // 可视化点光源
// const pointLightHelper = new THREE.PointLightHelper( pointLight, 0.1 );
// scene.add(pointLightHelper)
// // 添加坐标轴辅助器
// const axesHelper = new THREE.AxesHelper(5) // 数值代表线的长度
// scene.add(axesHelper) // 添加到场景之中
// 创建轨道控制器
const controls = new OrbitControls(camera,renderer.domElement)
// 设置控制器阻尼,让控制器更有真实效果,但必须在动画循环里调用 .update()
controls.enableDamping = true
export function render(){
// 每次循环渲染时调用stats更新方法,来刷新时间
controls.update()
renderer.render(scene,camera) // 周期性执行相机的渲染功能,更新canvas画布上的内容
requestAnimationFrame(render) // 接下来渲染下一帧的时候就会调用render函数
}
// 先开始就渲染一下
render()