threejs教程-灯光对物体的影响

简介

本系列教程需要具备threejs的基础入门知识,了场景、几何体、相机等基础概念。

学习本教程之前,建议学习【几何体】的基础知识。

根据前置知识,我们能够实现一个如下的3D效果

在这个示例中,我们使用PlaneGeometry创建了平面几何体

js 复制代码
const geometry = new THREE.PlaneGeometry(5, 5);

使用texture设置了其纹理贴图

js 复制代码
// 创建纹理
const texture = new THREE.TextureLoader().load("/bg.jpg");

并且通过uv坐标设置了其纹理贴图的渲染范围

js 复制代码
// 创建平面几何体
const geometry = new THREE.PlaneGeometry(5, 5);

// 创建纹理
const texture = new THREE.TextureLoader().load("/bg.jpg");
// 定义uv的取值范围,左上、右上、左下、右下
const uv = new Float32Array([0, 1, 0.5, 1, 0, 0, 0.5, 0]);
geometry.attributes.uv = new THREE.BufferAttribute(uv, 2);

const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

光照对物体的影响

实际生活中物体表面的明暗 效果是会受到光照的影响,比如晚上不开灯,你就看不到物体,灯光比较暗,物体也比较暗。在threejs中,咱们用网格模型Mesh模拟生活中物体,所以threejs中模拟光照Light对物体表面的影响,就是模拟光照Light对网格模型Mesh表面的影响。

上述代码示例中,我们使用了MeshBasicMaterial设置了物体的材质,这种材质是不受光照影响的,所以有没有光都无所谓。

我们将MeshBasicMaterial材质换成一种漫反射材质MeshLambertMaterial 试试

很明显,这种材质如果没有光照就会是一团黑。

我们给他加一个环境光试试

js 复制代码
// 添加光源
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);

可见,这种受到光照影响的材质有了光源后才能被我们看见。

现在,我们对光源已经有了初步的了解,现在我们学习一下光照影响的材质光源等更详细的知识

受光照影响材质

threejs提供的网格材质,有的受光照影响,有的不受光照影响。

基础网格材质 MeshBasicMaterial(opens new window)不会受到光照影响。

js 复制代码
//MeshBasicMaterial不受光照影响
const material = new THREE.MeshBasicMaterial(); 

漫反射网格材质 MeshLambertMaterial(opens new window)会受到光照影响。受光照影响的材质,在相同光源下,表现的特性也是不一样的。

创建光影观察模型

为了更好的演示灯光对物体的影响,我们创建一个面

js 复制代码
// 2.1创建地面模型
const floorMesh = new THREE.Mesh(
  new THREE.PlaneGeometry(10, 10),
  // 使用高光材质
  new THREE.MeshPhongMaterial({ side: THREE.DoubleSide, color: 0x1b5e20 })
);
scene.add(floorMesh);

面上有一个立方体

js 复制代码
// 2.2创建一个立方体
const boxMesh = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  // 使用高光材质
  new THREE.MeshPhongMaterial({ color: 0x0099ff })
);
scene.add(boxMesh);

上述代码中,我们使用了高光材质,但是没有设置光源,因此,物体表面是黑色的。

不同光源下的物体渲染效果

光源简介

Three.js提供了多种模拟生活中光源的API,文档搜索关键词light就可以看到。

环境光AmbientLight

环境光会均匀的照亮场景中的所有物体,它没有方向,不能用来投射阴影。

API:threejs.org/docs/?q=Amb...

构造函数

js 复制代码
AmbientLight( color : Color, intensity : Float )
  • color -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 Color 对象。
  • intensity -(可选)光照的强度。默认值为 1。

我们试着添加一个环境光源

js 复制代码
// 添加光源
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);

可以看出,环境光会照亮所有物体,而且物体的每个位置光照颜色是一致的。

我们更改光照强度试试

物体位置移动

现在立方体的位置卡在平面中间,看着很难受,我们把它抬高一点。

点光源PointLight

点光源PointLight(opens new window)可以类比为一个发光点,就像生活中一个灯泡以灯泡为中心向四周发射光线。

PointLight构造函数:

js 复制代码
PointLight( color : Color, intensity : Float, distance : Number, decay : Float )
  • color -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 Color 对象。
  • intensity -(可选)光照强度。默认值为 1。
  • distance - 光源照射的最大距离。默认值为 0(无限远)。
  • decay - 沿着光照距离的衰退量。默认值为 2。

我们试着添加一个点光源

js 复制代码
// 添加点光源
const pointLight = new THREE.PointLight(0xffffff, 100, 100);
// 设置光源位置
pointLight.position.set(5, 3, 5);
scene.add(pointLight);

反光强度

MeshPhongMaterial材质的物体在点光源下可以设置不同的反光程度

API:threejs.org/docs/index....

js 复制代码
// 2.2创建一个立方体
const boxMesh = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  // 使用高光材质
  new THREE.MeshPhongMaterial({ 
    color: 0x0099ff, 
  + shininess: 800 
  })
);

实现物体阴影效果

在光照下,立方体盒子应该在地面上有个阴影,实现这个效果需要以下几步

打开物体的投射光源功能

js 复制代码
// 物体投射光源
boxMesh.castShadow = true;

打开地面的接受光源光源功能

js 复制代码
// 地面接受光源
floorMesh.receiveShadow = true;

打开点光源的投射光源功能

js 复制代码
// 投射光源
pointLight.castShadow = true;

启用渲染器的阴影渲染开关

js 复制代码
// 渲染器的阴影渲染开关
renderer.shadowMap.enabled = true;
相关推荐
汪子熙10 分钟前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ19 分钟前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
Мартин.4 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。6 小时前
案例-表白墙简单实现
前端·javascript·css
数云界6 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd6 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常6 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer6 小时前
Vite:为什么选 Vite
前端
小御姐@stella6 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing6 小时前
【React】增量传输与渲染
前端·javascript·面试