【Three.JS零基础入门教程】第八篇:材质详解

 前期回顾:

【Three.JS零基础入门教程】第一篇:搭建开发环境

【Three.JS零基础入门教程】第二篇:起步案例

【Three.JS零基础入门教程】第三篇:开发辅助

【Three.JS零基础入门教程】第四篇:基础变换

【Three.JS零基础入门教程】第五篇:项目规划

【Three.JS零基础入门教程】第六篇:物体详解

【Three.JS零基础入门教程】第七篇:材质详解

上一期我们介绍了threejs中的材质,本期主要介绍纹理。

1) 基本概念

three.js中, 使用图片来模拟纹理效果, 将一张二维的图片包裹到三维的物体上

比如

  • 世界地图的图片包裹到球体上就可以模拟出地球的效果
  • 篮球的图片包裹到球体上就可以模拟出篮球的效果

2) 纹理加载器

three.js中通过纹理加载器加载图片

示例:

// 加载纹理贴图
const texture = new THREE.TextureLoader().load('/src/assets/texture/world.jpeg')
// 在设置材质时指定纹理贴图
const sphereMaterial = new THREE.MeshStandardMaterial({
  map: texture,
})

纹理贴图又可以细分为:

  • 普通纹理贴图
  • 凹凸纹理贴图
  • 法向纹理贴图
  • 环境纹理贴图

3) 普通纹理贴图

完整示例:

import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

// 导入封装的MeshGui
import { MeshGui } from '../gui'

// 一. 创建场景
const scene = new THREE.Scene()

// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)

// 三. 创建物体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32)
// 加载纹理贴图
const texture = new THREE.TextureLoader().load('/src/assets/texture/world.jpeg')
// 在设置材质时指定纹理贴图
const sphereMaterial = new THREE.MeshStandardMaterial({
  map: texture,
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)

new MeshGui({
  target: sphere,
})

// 创建灯光
const ambientLight = new THREE.AmbientLight(0xffffff, 1)
scene.add(ambientLight)

// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)

// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)

const axesHelper = new THREE.AxesHelper(10)
scene.add(axesHelper)

const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
scene.add(gridHelper)

function animation() {
  renderer.render(scene, camera)
}

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
})

效果:

4) 凹凸纹理贴图

为了模拟表面的粗糙凹凸效果, 可以多加一组贴图来模拟高度上的凹凸效果

注意

只有在可以产生阴影的光线环境下, 才可以观察到凹凸效果

完整示例:

import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

// 导入封装的MeshGui
import { MeshGui } from '../gui'

// 一. 创建场景
const scene = new THREE.Scene()

// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)

// 三. 创建物体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32)

// 加载纹理贴图
const texture = new THREE.TextureLoader().load('/src/assets/texture/world.jpeg')

// 加载法向贴图
const map = new THREE.TextureLoader().load(
  '/src/assets/texture/world_normal.jpg'
)
// 在设置材质时指定纹理贴图
const sphereMaterial = new THREE.MeshStandardMaterial({
  map: texture,
  bumpMap: map,
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)

new MeshGui({
  target: sphere,
})

// 添加环境灯光源
// const ambientLight = new THREE.AmbientLight(0xffffff, 1)
// scene.add(ambientLight)

// 添加点光源
const pointLight = new THREE.PointLight(0xffffff, 1)
pointLight.position.set(10, 10, 10)
scene.add(pointLight)

// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)

// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)

const axesHelper = new THREE.AxesHelper(10)
scene.add(axesHelper)

const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
scene.add(gridHelper)

function animation() {
  renderer.render(scene, camera)
}

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
})

效果:

5) 法向纹理贴图

使用法向贴图可以展示更多的细节, 更精细的控制

注意

如果设置了法向贴图, 凹凸贴图就会失效

完整示例:

import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

// 导入封装的MeshGui
import { MeshGui } from '../gui'

// 一. 创建场景
const scene = new THREE.Scene()

// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)

// 三. 创建物体
// 定义几何球体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32)

// 加载纹理贴图
const texture = new THREE.TextureLoader().load('/src/assets/texture/world.jpeg')

// 加载法向贴图
const map = new THREE.TextureLoader().load(
  '/src/assets/texture/world_normal.jpg'
)
// 在设置材质时指定纹理贴图
const sphereMaterial = new THREE.MeshStandardMaterial({
  map: texture,
  bumpMap: map,
  normalMap: map,
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)

new MeshGui({
  target: sphere,
})

// 添加环境灯光源
// const ambientLight = new THREE.AmbientLight(0xffffff, 1)
// scene.add(ambientLight)

// 添加点光源
const pointLight = new THREE.PointLight(0xffffff, 1)
pointLight.position.set(10, 10, 10)
scene.add(pointLight)

// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)

// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)

const axesHelper = new THREE.AxesHelper(10)
scene.add(axesHelper)

const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
scene.add(gridHelper)

function animation() {
  renderer.render(scene, camera)
}

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
})

效果:

6) 环境纹理贴图

对于表面光滑的物体, 是可以反射出周围环境的效果, 环境贴图主要就是用于实现这个效果

效果:

示例:

import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

// 导入封装的MeshGui
import { MeshGui } from '../gui'

// 一. 创建场景
const scene = new THREE.Scene()

// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)

// 三. 创建物体
// 创建一个盒子, 模拟周围环境
const envGeometry = new THREE.BoxGeometry(1000, 1000, 1000)

const loader = new THREE.TextureLoader().setPath('/src/assets/texture/bridge/')

// 分别加载6个面的图片, 构成全景图
const imgs = ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']

const mats = []
for (const item of imgs) {
  mats.push(
    new THREE.MeshBasicMaterial({
      map: loader.load(item),
      side: THREE.DoubleSide,
    })
  )
}
const env = new THREE.Mesh(envGeometry, mats)

// 创建一个球体, 能更好的显示效果
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32)
const texture = new THREE.CubeTextureLoader()
  .setPath('/src/assets/texture/bridge/')
  .load(imgs)

const sphereMaterial = new THREE.MeshStandardMaterial({
  envMap: texture,
  roughness: 0.0, // 粗糙程度, 0表示镜面, 非常光滑
  metalness: 1, // 金属度
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)

scene.add(env)
scene.add(sphere)

new MeshGui({
  target: sphere,
})

// 添加环境灯光源
// const ambientLight = new THREE.AmbientLight(0xffffff, 1)
// scene.add(ambientLight)

// 添加点光源
const pointLight = new THREE.PointLight(0xffffff, 1)
pointLight.position.set(10, 10, 10)
scene.add(pointLight)

// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)

// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)

const axesHelper = new THREE.AxesHelper(10)
// scene.add(axesHelper)

const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
// scene.add(gridHelper)

function animation() {
  renderer.render(scene, camera)
}

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
})

我们不仅提供优质课程,助你学习更进一步!新中地学生threejs作品:

三维GIS开发特训营即将开班,免fei领视频版教程戳↓↓↓

GIS资料免费领icon-default.png?t=N7T8https://www.wjx.cn/vm/Qm8Ful2.aspx

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果你想开始学习three.js,可以从教程源代码入手。教程源码提供了一些示例和实例,可以启发你的创作灵感,也可以让你更快地理解three.js的基础知识。 在查看源码之前,你需要先安装three.js和web开发环境。安装完成后,你就可以开始查看源码了。 教程源码一般会有一些说明和注释,这些注释可以帮助你更好地理解代码的功能和实现方法。你可以先阅读这些注释,然后尝试运行代码,看代码是如何运作的。 当你理解了一些基础的代码后,你可以尝试自己写一些小程序,练习three.js的使用。这些小程序可能简单,但是可以帮助你加深对three.js的理解,并为今后更复杂的项目做好准备。 最重要的是,遇到问题不要担心,可以参考three.js社区和文档,也可以在网上寻找相关的教程和视频。通过不断摸索和学习,你一定能掌握three.js的使用技巧,创作出自己喜欢的作品。 ### 回答2: three.js是一个能够在网页上实现3D图形和动画效果的JavaScript库,可以用于创建各种有趣的3D场景和游戏。针对初学者,有很多的入门教程和示例代码可供学习和练习。 在网上搜索“three.js入门教程源代码”可以找到很多优秀的教程和示例代码,如three.js官方文档、CodePen、Github等。此外,同类的OpenGL和WebGL等技术也有很多优秀的资源可供参考。 对于初学者来说,建议先了解three.js的基本知识,如坐标系、场景、相机、灯光、材质、几何体等等。然后可以通过实践来加深理解,例如创建一个简单的立方体、平面、球体等。同时也可以尝试调整相机、灯光和材质等参数,看看会发生什么变化。 在学习过程中,遇到问题可以查阅文档或者在相关社区寻求帮助。同时也要多注重实践,通过参考示例代码和自己实践来提升技能。 ### 回答3: three.js是一个非常流行的JavaScript 3D图形库,很多人想要学习它,但是对于初学者来说,这可能会让他们感到非常困难。因此,一些网站和博客提供了一些入门教程以帮助初学者了解并开始使用three.js,其中一些包括源代码。 这些源代码提供一些基础教学,帮助用户通过编写一些简单的three.js代码并观察结果来学习three.js的基础知识。 用户可以下载源代码,并使用它们在自己的计算机上运行三维场景。 这些源代码通常提供了许多有关three.js的基础知识,包括: 1. 创建场景,灯光和相机。 2. 从文件中加载3D模型和纹理。 3. 使用材质和纹理来渲染对象。 4. 添加动画和控制器。 5. 处理鼠标和键盘输入。 6. 在网页上嵌入three.js场景。 这些源代码通常以注释的形式提供,说明每个代码块的功能。此外,这些源代码通常遵循良好的编程实践,使读者易于理解和跟踪整个过程。 总的来说,three.js零基础入门教程源代码非常适合那些想要学习three.js的初学者,他们可以通过这些源代码快速入门,并了解更多three.js知识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值