目标:灯光与阴影
- 环境光无阴影
- 平行光(太阳光),点光源(电灯泡-四处发光),聚光灯(八)
1、材质要满足能够对光照有反应
- 最常用-标准网格材质(MeshStandardMaterial)
- 更消耗性能-物理网格材质(MeshPhysicalMaterial)-MeshStandardMaterial的扩展,提供了更高级的基于物理的渲染属性:
2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
3、设置光照投射阴影 directionalLight.castShadow = true;
4、设置物体投射阴影 sphere.castShadow = true;
5、设置物体接收阴影 plane.receiveShadow = true;
/*
* @Description: 灯光与阴影的关系与设置 -- 五个步骤缺一不可
*/
import * as THREE from "three";
// 导入轨道控制器(鼠标控制)
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
/**
* 目标:灯光与阴影--环境光无阴影,平行光(太阳光),点光源(电灯泡-四处发光),聚光灯(八)
* 灯光阴影
* 1、材质要满足能够对光照有反应
--最常用-标准网格材质(MeshStandardMaterial)
* --更消耗性能-物理网格材质(MeshPhysicalMaterial)-MeshStandardMaterial的扩展,
提供了更高级的基于物理的渲染属性:
* 2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
* 3、设置光照投射阴影 directionalLight.castShadow = true;
* 4、设置物体投射阴影 sphere.castShadow = true;
* 5、设置物体接收阴影 plane.receiveShadow = true;
*/
/*
*1. 创建场景
*/
const scene = new THREE.Scene();
/*
* 2.创建相机(这里是 透视摄像机--用来模拟人眼所看到的景象)
*/
const camera = new THREE.PerspectiveCamera(
75, // 视野角度
window.innerWidth / window.innerHeight, // 长宽比
0.1, // 进截面
1000 // 远截面
);
// 设置相机位置
camera.position.set(7, 7, 7);
scene.add(camera); // 将相机添加到场景中
/*
* 添加物体
*/
// 创建几何体
const sphereGeometry = new THREE.SphereBufferGeometry(1, 20, 20);
// 1). 设置材质-标准网格材质
const material = new THREE.MeshStandardMaterial();
// 生成几何体
const sphere = new THREE.Mesh(sphereGeometry, material);
// 4). 投射阴影 --对象是否被渲染到阴影贴图中--三维物体(Object3D)
sphere.castShadow = true;
scene.add(sphere);
/**
* 创建底部平面
*/
const planeGeometry = new THREE.PlaneBufferGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 5). 接收阴影
plane.receiveShadow = true;
scene.add(plane);
/**
* 灯光
*/
// 环境光
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);
// 3). 设置平行光产生动态阴影
directionalLight.castShadow = true;
scene.add(directionalLight);
/**
* 3.初始化渲染器
*/
const renderer = new THREE.WebGL1Renderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 2). 开启场景中的阴影贴图--允许在场景中使用阴影贴图
renderer.shadowMap.enabled = true;
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);
/**
* 创建轨道控制器(OrbitControls)
* 可以使得相机围绕目标进行轨道运动
*/
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真是效果,必须在动画循环render()中调用update()
controls.enableDamping = true;
// controls.autoRotate = true;
// controls.autoRotateSpeed = 2; // 自转速度
/**
* 辅助三维坐标系
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
*/
var axesHelper = new THREE.AxesHelper(7);
scene.add(axesHelper);
// 定义循环渲染方法
function render() {
renderer.render(scene, camera); // 执行渲染操作
controls.update(); // 加不加都行
requestAnimationFrame(render); // 渲染下一帧的时候就会调用render函数
}
render();
// 监听尺寸变化实现自适应画面
window.addEventListener("resize", () => {
// console.log("画面变化了");
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
介绍:
平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。
构造器:
DirectionalLight( color : Integer, intensity : Float )
color - (可选参数) 16进制表示光的颜色。 缺省值为 0xffffff (白色)。
intensity - (可选参数) 光照的强度。缺省值为1。与点光源和聚光灯的区别:
最大的区别就是,点光源和聚光灯光源距离物体越远光线越暗。光是从一点发出的。
而被平行光照亮的整个区域接收到的光强是一样的。光是平行的。平行光的特点:
由于模型的阴影渲染会消耗很多的性能,所以我们需要设置平行光相关的区域能够显示阴影,和阴影显示的良好程度。如下几个属性:
//这两个值决定使用多少像素生成阴影 默认512
directionalLight.shadow.mapSize.height = 2048;
directionalLight.shadow.mapSize.width = 2048;或者
directionalLight.shadow.mapSize.set(2048, 2048);
// 设置阴影贴图模糊度
directionalLight.shadow.radius = 20;
// 设置平行光投射相机的属性
directionalLight.shadow.camera.near = 0.5; //产生阴影的最近距离
directionalLight.shadow.camera.far = 500; //产生阴影的最远距离
directionalLight.shadow.camera.left = -5; //产生阴影距离位置的最左边位置
directionalLight.shadow.camera.right = 5; //最右边
directionalLight.shadow.camera.top = 5; //最上边
directionalLight.shadow.camera.bottom = -5; //最下面
通过 near 的变化:
// 设置阴影贴图模糊度
directionalLight.shadow.radius = 20;
// 设置阴影贴图的分辨率
directionalLight.shadow.mapSize.set(2048, 2048);
// 设置平行光投射相机的属性
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
通过更改分辨率(2048 --> 512):
// 设置阴影贴图模糊度
directionalLight.shadow.radius = 20;
// 设置阴影贴图的分辨率
directionalLight.shadow.mapSize.set(512, 512);
// 设置平行光投射相机的属性
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
通过更改模糊度(20 -- > 120):
// 设置阴影贴图模糊度
directionalLight.shadow.radius = 120;
// 设置阴影贴图的分辨率
directionalLight.shadow.mapSize.set(2048, 2048);
// 设置平行光投射相机的属性
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
/*
* @Description: 平行光(DirectionalLight)阴影属性与阴影相机原理
*/
// 导入dat.gui可视化工具
import * as dat from "dat.gui";
import * as THREE from "three";
// 导入轨道控制器(鼠标控制)
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
/**
* 目标:灯光与阴影--环境光无阴影,平行光(太阳光),点光源(电灯泡-四处发光),聚光灯(八)
* 灯光阴影
* 1、材质要满足能够对光照有反应
--最常用-标准网格材质(MeshStandardMaterial)
* --更消耗性能-物理网格材质(MeshPhysicalMaterial)-MeshStandardMaterial的扩展,
提供了更高级的基于物理的渲染属性:
* 2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
* 3、设置光照投射阴影 directionalLight.castShadow = true;
* 4、设置物体投射阴影 sphere.castShadow = true;
* 5、设置物体接收阴影 plane.receiveShadow = true;
*/
/*
*1. 创建场景
*/
const scene = new THREE.Scene();
/*
* 2.创建相机(这里是 透视摄像机--用来模拟人眼所看到的景象)
*/
const camera = new THREE.PerspectiveCamera(
75, // 视野角度
window.innerWidth / window.innerHeight, // 长宽比
0.1, // 进截面
1000 // 远截面
);
// 设置相机位置
camera.position.set(7, 7, 7);
scene.add(camera); // 将相机添加到场景中
/*
* 添加物体
*/
// 创建几何体
const sphereGeometry = new THREE.SphereBufferGeometry(1, 20, 20);
// 1). 设置材质
const material = new THREE.MeshStandardMaterial();
// 生成几何体
const sphere = new THREE.Mesh(sphereGeometry, material);
// 4). 投射阴影 --对象是否被渲染到阴影贴图中--三维物体(Object3D)
sphere.castShadow = true;
scene.add(sphere);
/**
* 创建平面
*/
const planeGeometry = new THREE.PlaneBufferGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 5). 接收阴影
plane.receiveShadow = true;
scene.add(plane);
/**
* 灯光
*/
// 环境光
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);
// 3). 设置平行光产生动态阴影
directionalLight.castShadow = true;
// 设置阴影贴图模糊度
directionalLight.shadow.radius = 20;
// 设置阴影贴图的分辨率
directionalLight.shadow.mapSize.set(2048, 2048);
// 设置平行光投射相机的属性
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
scene.add(directionalLight);
const gui = new dat.GUI();
gui
.add(directionalLight.shadow.camera, "near")
.min(0)
.max(20)
.step(0.1)
.onChange(() => {
directionalLight.shadow.camera.updateProjectionMatrix();
});
/**
* 3.初始化渲染器
*/
const renderer = new THREE.WebGL1Renderer();
// 设置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 2). 开启场景中的阴影贴图--允许在场景中使用阴影贴图
renderer.shadowMap.enabled = true;
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);
/**
* 创建轨道控制器(OrbitControls)
* 可以使得相机围绕目标进行轨道运动
*/
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真是效果,必须在动画循环render()中调用update()
controls.enableDamping = true;
// controls.autoRotate = true;
// controls.autoRotateSpeed = 2; // 自转速度
/**
* 辅助三维坐标系
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
*/
var axesHelper = new THREE.AxesHelper(7);
scene.add(axesHelper);
// 定义循环渲染方法
function render() {
renderer.render(scene, camera); // 执行渲染操作
controls.update(); // 加不加都行
requestAnimationFrame(render); // 渲染下一帧的时候就会调用render函数
}
render();
// 监听尺寸变化实现自适应画面
window.addEventListener("resize", () => {
// console.log("画面变化了");
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});