本文 我们来说 灯光与阴影
之前 我们有接触到光照类的知识 但是阴影应该都是第一次接触
那么 我们先来看光
首先是 AmbientLight 环境光 你在官网中搜索 AmbientLight 官方是就写明了 环境光是不会产生阴影的
因为 它没有反向
然后是 DirectionalLight 平行光 它是可以投射阴影的
因为它是类似于太阳 那 太阳照下来 自然是有阴影的
还有就是 PointLight 点光源
点光源也是可以产生阴影 但 它是自身为中心 四处发光的
就好像一颗光球 会照向四周
SpotLight 聚光灯
这个就像舞台聚关灯的一个效果 中心点光很聚集 照向一个放心 越远光越分散 范围越大
RectAreaLight 平面光源
比较像 从窗户外面照进来的光
但官网也说明白了 平面光是不支持阴影的
大体可以总结为 环境光和平面光是无法产生阴影的
那么 还有一些材质 也是不支持阴影的
首当其冲的就是 MeshBasicMaterial 基础网格材质
官网会告诉你 它有没有光照都是一样的 自然不会有阴影类的反应
MeshStandardMaterial 标准网格材质
这种就是 使用Metallic-Roughness工作流程
和光照息息相关的 它就可以产生出阴影
MeshLambertMaterial 的话 也有光的效果 但是 这种比较粗糙 不光滑
比较适合做木材等表面粗糙的物体的反射效果
MeshPhongMaterial 则相反 它适合做一些表面光滑的物体
MeshLambertMaterial 和 MeshPhongMaterial,都是以性能好作为优势的 相对逼真的程度会弱一些
通常情况下 选择 MeshStandardMaterial 标准网格材质 就够了
那么 还有 MeshPhysicalMaterial 物理网格材质
它内部是更高级的渲染引擎 效果会比基础网格材质更加逼真
但是 会消耗更多的性能
他也是能够更光照发生作用的
OK 那 我们想在就代码搞起喽
我们先把代码搞成这样
import './style.css'
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//创建相机
const camera = new THREE.PerspectiveCamera(
45, //视角 视角越大 能看到的范围就越大
window.innerWidth / window.innerHeight,//相机的宽高比 一般和画布一样大最好
0.1,
1000
);
const scene = new THREE.Scene();
//c创建一个canvas容器 并追加到 body上
const renderer = new THREE.WebGLRenderer(0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//设置相机位置 这里 我们设置Z轴 大家可以试试 S Y 和 Z 都是可以的
camera.position.z = 5;
//设置相机默认看向哪里 三个 0 代表 默认看向原点
camera.lookAt(0, 0, 0);
//将内容渲染到元素上
renderer.render(scene, camera);
const controls = new OrbitControls(camera, renderer.domElement);
function animate() {
controls.update();
requestAnimationFrame(animate);
/*cube.rotation.x += 0.01;
cube.rotation.y += 0.01;*/
renderer.render(scene, camera);
}
animate();
运行起来 就是 一片黑 暂时什么都没有
我们加入如下代码
// 环境光
const light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light);
//直线光源
const directionallight = new THREE.DirectionalLight(0xffffff, 0.5);
directionallight.position.set(10, 10, 10);
scene.add(directionallight);
//创建球形几何体
const sphere1 = new THREE .Mesh(
new THREE.SphereGeometry(0.7, 32, 32),
new THREE.MeshStandardMaterial({
}))
scene.add(sphere1);
这里 我们设置了 环境光 然后创建了一个球形的几何体
球体材质是 普通的 MeshStandardMaterial
我们拖动一下 会发现 这个球还是有一个反光的效果
我们在他下面加一个平面
//添加平面
const plane = new THREE.Mesh(
new THREE.PlaneGeometry(3, 3),
new THREE.MeshStandardMaterial({})
);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
也是最普通的材质 然后 position y下移 到 负1的位置 然后 旋转rotation 负90度
我们转动一下平面
这里 虽然我们有灯光反射的一个效果 但是 显然没有出现阴影的效果
那么 想要有阴影 首先 你要有能达到阴影要求的光照
然后 我们渲染器 要开启这个渲染的计算
我们官网搜索 WebGLRenderer
下面就有一个 shadowMap 阴影贴图效果
这个属性 默认是false 不使用的
我们找到 渲染器所在位置 将他的 shadowMap字段下的 enabled 设置为true
开启了之后 我们要设置光照 投射我们的阴影
我们官网 进入平行直线光
找到属性中的 castShadow 投射阴影
他默认 为了避免性能消耗 是关闭的
我们直接在平行光这里 给他 castShadow 设为true即可开启
然后 物体 我们也要设置 让它能够投射我们的阴影
我们 官网进入 Object3D
它的这个属性也叫 castShadow
是否投射阴影
我们代码中 将球形几何体的 castShadow 给个true 把它打开
然后 这个阴影是要映射到我们平面上的
那么 这里 我们平面 要去接受这个阴影效果
Object3D 下的 receiveShadow 属性
平面这里 我们将 receiveShadow 属性设为true
这培 我们运行代码
阴影的效果 就出来啦
所有的步骤 一个不能少 否则就出不来
好 我们最后的代码就是这样的
import './style.css'
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//创建相机
const camera = new THREE.PerspectiveCamera(
45, //视角 视角越大 能看到的范围就越大
window.innerWidth / window.innerHeight,//相机的宽高比 一般和画布一样大最好
0.1,
1000
);
const scene = new THREE.Scene();
// 环境光
const light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light);
//直线光源
const directionallight = new THREE.DirectionalLight(0xffffff, 0.5);
directionallight.position.set(10, 10, 10);
directionallight.castShadow = true;
scene.add(directionallight);
//创建球形几何体
const sphere1 = new THREE .Mesh(
new THREE.SphereGeometry(0.7, 32, 32),
new THREE.MeshStandardMaterial({})
)
sphere1.castShadow = true;
scene.add(sphere1);
//添加平面
const plane = new THREE.Mesh(
new THREE.PlaneGeometry(3, 3),
new THREE.MeshStandardMaterial({})
);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add(plane);
//c创建一个canvas容器 并追加到 body上
const renderer = new THREE.WebGLRenderer(0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
//设置相机位置 这里 我们设置Z轴 大家可以试试 S Y 和 Z 都是可以的
camera.position.z = 5;
//设置相机默认看向哪里 三个 0 代表 默认看向原点
camera.lookAt(0, 0, 0);
//将内容渲染到元素上
renderer.render(scene, camera);
const controls = new OrbitControls(camera, renderer.domElement);
function animate() {
controls.update();
requestAnimationFrame(animate);
/*cube.rotation.x += 0.01;
cube.rotation.y += 0.01;*/
renderer.render(scene, camera);
}
animate();