聚光灯就如同手电筒一样,点光源就如同一个电灯泡甚至是萤火虫那样。如何使用他们呢?
我们还是一样,先做一个小球和一个平面,用来展示光线。并且加入基本的环境光。
// 做一个球体
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(SphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 创建平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 接收阴影
plane.receiveShadow = true;
scene.add(plane);
// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff);
scene.add(light);
聚光灯
Threejs 聚光灯手册
使用聚光灯就将之前的直线光源换成聚光灯就可以,当然,聚光灯有一些新的属性,比如说角度、衰减、半影衰减、沿着光照距离衰减等。我们可以直接使用gui做测试。
// 聚光源
const spotLight = new THREE.SpotLight(0xffffff, 2);
spotLight.position.set(5, 5, 5);
spotLight.intensity = 2;
// 设置直线光源产生阴影
spotLight.castShadow = true;
//设置阴影贴图模糊度
spotLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
spotLight.shadow.mapSize.set(4096, 4096);
//设置打在小球上
spotLight.target = sphere;
//聚光灯的角度
spotLight.angle = Math.PI / 6;
//聚光灯的衰减
spotLight.distance = 0;
//聚光灯的半影的衰减
spotLight.penumbra = 0.5;
//聚光灯 沿着光照距离的衰减
spotLight.decay = 0;
// 透视相机的属性设置(一般不用更改)
scene.add(spotLight);
gui.add(sphere.position, "x").min(-5).max(5).step(0.1);
gui
.add(spotLight, "angle")
.min(0)
.max(Math.PI / 2)
.step(0.01);
gui.add(spotLight, "distance").min(0).max(10).step(0.1);
gui.add(spotLight, "penumbra").min(0).max(10).step(0.1);
gui.add(spotLight, "decay").min(0).max(1).step(0.1);
这里我们要注意,需要将我们的物理渲染器打开
//开启物理渲染器
renderer.physicallyCorrectLights = true;
聚光灯全部代码
//点光源(灯泡) 和 聚光灯(手电筒)
//导入 threejs
import * as THREE from "three";
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//导入lil.gui
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
45, // 视角
window.innerWidth / window.innerHeight, // 宽高比 窗口的宽高进行设置的
0.1, // 近平面 相机最近最近能看到的物体
1000 // 远平面 相机最远能看到的物体
);
//设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的大小 (窗口大小)
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;
//开启物理渲染器
renderer.physicallyCorrectLights = true;
// 将渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);
//添加世界坐标辅助器 (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
const axesHelper = new THREE.AxesHelper(6);
//添加到场景之中
scene.add(axesHelper);
// 添加轨道控制器 (修改侦听位置) 一般监听画布的事件 不监听document.body
const controls = new OrbitControls(camera, renderer.domElement);
//渲染函数
function animate() {
controls.update();
//请求动画帧
requestAnimationFrame(animate);
//渲染
renderer.render(scene, camera);
}
//渲染
animate();
// 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
window.addEventListener("resize", () => {
// 重新设置渲染器的大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 重新设置相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 重新计算相机的投影矩阵
camera.updateProjectionMatrix();
});
//创建gui实例
const gui = new GUI();
// 做一个球体
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(SphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 创建平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 接收阴影
plane.receiveShadow = true;
scene.add(plane);
// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff);
// 聚光源
const spotLight = new THREE.SpotLight(0xffffff, 2);
spotLight.position.set(5, 5, 5);
spotLight.intensity = 2;
// 设置直线光源产生阴影
spotLight.castShadow = true;
//设置阴影贴图模糊度
spotLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
spotLight.shadow.mapSize.set(4096, 4096);
//设置打在小球上
spotLight.target = sphere;
//聚光灯的角度
spotLight.angle = Math.PI / 6;
//聚光灯的衰减
spotLight.distance = 0;
//聚光灯的半影的衰减
spotLight.penumbra = 0.5;
//聚光灯 沿着光照距离的衰减
spotLight.decay = 0;
// 透视相机的属性设置(一般不用更改)
scene.add(spotLight);
scene.add(light);
gui.add(sphere.position, "x").min(-5).max(5).step(0.1).name("球体x轴位置");
gui
.add(spotLight, "angle")
.min(0)
.max(Math.PI / 2)
.step(0.01)
.name("聚光灯角度");
gui.add(spotLight, "distance").min(0).max(10).step(0.1).name("聚光灯距离");
gui.add(spotLight, "penumbra").min(0).max(10).step(0.1).name("聚光灯半影");
gui.add(spotLight, "decay").min(0).max(1).step(0.1).name("聚光灯衰减");
点光源
Threejs 点光源手册
点光源就相当于我们生活中的萤火虫 或者电灯泡。这里我们直接将聚光灯的代码换成点光源。
聚光灯中的部分属性在点光源中是没有的,比如说角度,半影。
const pointLight = new THREE.PointLight(0xff0000, 2);
pointLight.position.set(2, 2, 2);
//光照强度
// pointLight.intensity = 2;
// 设置直线光源产生阴影
pointLight.castShadow = true;
//设置阴影贴图模糊度
pointLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
pointLight.shadow.mapSize.set(512, 512);
scene.add(pointLight);
然后我们可以用gui控制点光源的部分属性。
gui.add(pointLight.position, "x").min(-5).max(5).step(0.1);
gui.add(pointLight, "distance").min(0).max(5).step(0.001);
gui.add(pointLight, "decay").min(0).max(1).step(0.1);
我们做出一个灯光,但是看不到灯光的源头,不过我们可以做一个更小的小球,来模拟灯光的出口,并且可以利用它做出一些效果。
const smallBox = new THREE.Mesh(
new THREE.SphereGeometry(0.1, 20, 20),
new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
smallBox.position.set(2, 2, 2);
// 点光源
const pointLight = new THREE.PointLight(0xff0000, 2);
//光照强度
// pointLight.intensity = 2;
// 设置直线光源产生阴影
pointLight.castShadow = true;
//设置阴影贴图模糊度
pointLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
pointLight.shadow.mapSize.set(512, 512);
smallBox.add(pointLight);
scene.add(smallBox);
我们可以利用时钟。来让这个点光源旋转。
//设置时钟
const clock = new THREE.Clock();
//渲染函数
function render() {
let time = clock.getElapsedTime();
//通过时间设置小球的位置
smallBox.position.x = Math.sin(time) * 3;
smallBox.position.z = Math.cos(time) * 3;
smallBox.position.y = 2 + Math.sin(time*10);
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
点光源全部代码
//点光源(灯泡) 和 聚光灯(手电筒)
//导入 threejs
import * as THREE from "three";
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//导入lil.gui
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
45, // 视角
window.innerWidth / window.innerHeight, // 宽高比 窗口的宽高进行设置的
0.1, // 近平面 相机最近最近能看到的物体
1000 // 远平面 相机最远能看到的物体
);
//设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);
// 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
window.addEventListener("resize", () => {
// 重新设置渲染器的大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 重新设置相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 重新计算相机的投影矩阵
camera.updateProjectionMatrix();
});
//创建gui实例
const gui = new GUI();
// 做一个球体
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(SphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);
// 创建平面
const planeGeometry = new THREE.PlaneGeometry(50, 50);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
// 接收阴影
scene.add(plane);
// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff);
const smallBox = new THREE.Mesh(
new THREE.SphereGeometry(0.1, 20, 20),
new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
smallBox.position.set(2, 2, 2);
// 点光源
const pointLight = new THREE.PointLight(0xff0000, 2);
pointLight.position.set(2, 2, 2);
//光照强度
// pointLight.intensity = 2;
// 设置直线光源产生阴影
pointLight.castShadow = true;
//设置阴影贴图模糊度
pointLight.shadow.radius = 20;
//设置阴影贴图的分辨率(让它变得更加细致)
pointLight.shadow.mapSize.set(512, 512);
smallBox.add(pointLight);
scene.add(smallBox);
scene.add(light);
gui.add(pointLight.position, "x").min(-5).max(5).step(0.1);
gui.add(pointLight, "distance").min(0).max(5).step(0.001);
gui.add(pointLight, "decay").min(0).max(1).step(0.1);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的大小 (窗口大小)
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 将渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);
//添加世界坐标辅助器 (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
const axesHelper = new THREE.AxesHelper(6);
//添加到场景之中
scene.add(axesHelper);
// 添加轨道控制器 (修改侦听位置) 一般监听画布的事件 不监听document.body
const controls = new OrbitControls(camera, renderer.domElement);
//设置时钟
const clock = new THREE.Clock();
//渲染函数
function render() {
let time = clock.getElapsedTime();
//通过时间设置小球的位置
smallBox.position.x = Math.sin(time) * 3;
smallBox.position.z = Math.cos(time) * 3;
smallBox.position.y = 2 + Math.sin(time*10);
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
//渲染
render();