three.js中物體的燈光與陰影設置
一、.設置物體陰影的核心步驟
1. 以平面上有一個球體為例,設置球體的陰影投射到平面上
核心步驟如下:
要讓球體的陰影照射到平面上,需要使用陰影映射技術。具體步驟如下:
在渲染器中啟用陰影:
renderer.shadowMap.enabled = true;
創(chuàng)建一個平面和一個球體:
// 創(chuàng)建平面
var planeGeometry = new THREE.PlaneGeometry(5, 5);
var planeMaterial = new THREE.MeshStandardMaterial({ color: 0x888888 });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2; // 將平面旋轉(zhuǎn)至水平方向
plane.receiveShadow = true; // 接收陰影
scene.add(plane);
// 創(chuàng)建球體
var sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
var sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.y = 1; // 將球體放置在平面上方
sphere.castShadow = true; // 投射陰影
scene.add(sphere);創(chuàng)建一個聚光燈:
var light = new THREE.SpotLight(0xffffff, 1, 100, Math.PI / 4); light.position.set(0, 5, 0); light.target.position.set(0, 0, 0); light.castShadow = true; // 投射陰影 light.shadow.bias = -0.002; // 減少陰影失真 light.shadow.mapSize.width = 1024; light.shadow.mapSize.height = 1024; scene.add(light);
設置球體和聚光燈的關系:
sphere.add(light); // 球體作為聚光燈的子元素
現(xiàn)在打開瀏覽器預覽,就可以看到球體的陰影照射到了平面上。如果想讓陰影更加自然,可以調(diào)整陰影相關的參數(shù),例如增大陰影貼圖的分辨率、調(diào)整聚光燈的角度、調(diào)整陰影偏差等。
2. 設置正方體和球體的燈光與陰影:
效果如圖:

核心步驟和案例一一樣,就不在贅述,這里給出完整代碼,如下:
import * as THREE from "three";
// 導入軌道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 目標:燈光與陰影
// 燈光陰影
// 1、材質(zhì)要滿足能夠?qū)庹沼蟹磻?
// 2、設置渲染器開啟陰影的計算 renderer.shadowMap.enabled = true;
// 3、設置光照投射陰影 directionalLight.castShadow = true;
// 4、設置物體投射陰影 sphere.castShadow = true;
// 5、設置物體接收陰影 plane.receiveShadow = true;
// 1、創(chuàng)建場景
const scene = new THREE.Scene();
// 2、創(chuàng)建相機
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 設置相機位置
camera.position.set(0, 0, 10);
scene.add(camera);
// 創(chuàng)建球體
const sphereGeometry = new THREE.SphereBufferGeometry(1, 20, 20); // 參數(shù):半徑、水平分段數(shù)、垂直分段數(shù)
const material = new THREE.MeshStandardMaterial(); // 創(chuàng)建標準材質(zhì)
const sphere = new THREE.Mesh(sphereGeometry, material); // 根據(jù)幾何體和材質(zhì)創(chuàng)建球體
sphere.position.set(1, 0, 0); // 設置球體位置
// 設置球體顏色
sphere.material.color = new THREE.Color(0x00ff00);
// 投射陰影
sphere.castShadow = true;
scene.add(sphere);
// 創(chuàng)建立方體
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1); // 參數(shù):長、寬、高
// 創(chuàng)建標準材質(zhì)
const materialcube = new THREE.MeshStandardMaterial();
const cube = new THREE.Mesh(cubeGeometry, materialcube); // 根據(jù)幾何體和材質(zhì)創(chuàng)建立方體
cube.position.set(-1, 0, 2); // 設置立方體位置
// 設置立方體顏色
cube.material.color = new THREE.Color(0xff0000);
// 投射陰影
cube.castShadow = true;
scene.add(cube);
// // 創(chuàng)建平面
const planeGeometry = new THREE.PlaneBufferGeometry(10, 10); // 參數(shù):寬度、高度
// 創(chuàng)建標準材質(zhì)
const materialplane = new THREE.MeshStandardMaterial();
const plane = new THREE.Mesh(planeGeometry, materialplane); // 根據(jù)幾何體和材質(zhì)創(chuàng)建平面
plane.position.set(0, -1, 0); // 設置平面位置
plane.rotation.x = -Math.PI / 2; // 設置平面旋轉(zhuǎn)
// 接收陰影
plane.receiveShadow = true;
scene.add(plane);
// 燈光
// 環(huán)境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light
scene.add(light);
//直線光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 參數(shù):光源顏色、光源強度
directionalLight.position.set(10, 10, 10); // 設置光源位置
directionalLight.castShadow = true; // 設置光照投射陰影
scene.add(directionalLight);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 設置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 開啟場景中的陰影貼圖
renderer.shadowMap.enabled = true;
// 將webgl渲染的canvas內(nèi)容添加到body
document.body.appendChild(renderer.domElement);
// 創(chuàng)建軌道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 設置控制器阻尼,讓控制器更有真實效果,必須在動畫循環(huán)里調(diào)用.update()。
controls.enableDamping = true;
function render() {
controls.update();
renderer.render(scene, camera);
// 渲染下一幀的時候就會調(diào)用render函數(shù)
requestAnimationFrame(render);
}
render();
// 監(jiān)聽畫面變化,更新渲染畫面
window.addEventListener("resize", () => {
// console.log("畫面變化了");
// 更新攝像頭
camera.aspect = window.innerWidth / window.innerHeight;
// 更新攝像機的投影矩陣
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 設置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});二、直行光源DirectionalLightShadow的陰影屬性和相機原理介紹
在three.js中,使用new THREE.DirectionalLight可以創(chuàng)建一個方向光源。這個光源可以通過設置陰影屬性來讓場景中的對象產(chǎn)生陰影。設置陰影屬性需要使用DirectionalLight類的shadow屬性,它是一個DirectionalLightShadow對象,可以設置以下屬性:
- mapSize:陰影貼圖的大小??梢允褂肨HREE.Vector2或者數(shù)字類型的參數(shù)來設置。
- bias:偏移量,用于保持陰影的正確性??梢允褂脭?shù)字類型的參數(shù)來設置。
- camera:陰影相機。使用DirectionalLightShadow.camera屬性可以獲取到DirectionalLightShadow對應的Camera對象,從而可以對相機進行設置。
相機原理:在three.js中,相機是場景中的虛擬相機,用于模擬真實世界中的相機。相機的工作原理類似于真實世界中的相機,它可以控制場景的可見區(qū)域、切換視角、實現(xiàn)景深等效果。在場景中添加相機之后,可以通過設置相機的各個屬性來控制相機的位置、旋轉(zhuǎn)、縮放等,從而實現(xiàn)不同的視角和效果。
相機相關屬性設置:在three.js中,可以通過設置相機的各個屬性來控制相機的行為和效果。以下是一些常用的相機屬性:
- position:相機的位置。
- near:相機的近裁剪面距離。
- far:相機的遠裁剪面距離。
- fov:相機的視角。
舉例說明:下面是一個用于產(chǎn)生陰影的DirectionalLight對象的創(chuàng)建和設置陰影屬性的代碼示例:
核心代碼
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(20, 30, -5); directionalLight.castShadow = true; directionalLight.shadow.mapSize.width = 1024; // 設置陰影貼圖的寬度 directionalLight.shadow.mapSize.height = 1024; // 設置陰影貼圖的高度 directionalLight.shadow.bias = -0.01; // 設置陰影的偏移量 directionalLight.shadow.camera.near = 1; // 設置陰影相機的近裁剪面距離 directionalLight.shadow.camera.far = 100; // 設置陰影相機的遠裁剪面距離 directionalLight.shadow.camera.fov = 45; // 設置陰影相機的視角

完整示例效果如上圖所示,完整示例代碼如下:
import * as THREE from "three";
// 導入軌道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 導入dat.gui
import * as dat from "dat.gui";
const gui = new dat.GUI();
// 1、創(chuàng)建場景
const scene = new THREE.Scene();
// 2、創(chuàng)建相機
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 設置相機位置
camera.position.set(0, 0, 10);
scene.add(camera);
const sphereGeometry = new THREE.SphereBufferGeometry(1, 20, 20);
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(sphereGeometry, material);
// 投射陰影
sphere.castShadow = true;
scene.add(sphere);
// // 創(chuàng)建平面
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;
// 接收陰影
plane.receiveShadow = true;
scene.add(plane);
// 燈光
// 環(huán)境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light
scene.add(light);
//直線光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(5, 5, 5);
directionalLight.castShadow = true;
// 設置陰影貼圖模糊度
directionalLight.shadow.radius = 20;
// 設置陰影貼圖的分辨率
directionalLight.shadow.mapSize.set(4096, 4096);
// 設置平行光投射相機的屬性
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);
gui
.add(directionalLight.shadow.camera, "near")
.min(0)
.max(10)
.step(0.1)
.onChange(() => {
directionalLight.shadow.camera.updateProjectionMatrix();
});
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 設置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 開啟場景中的陰影貼圖
renderer.shadowMap.enabled = true;
// 將webgl渲染的canvas內(nèi)容添加到body
document.body.appendChild(renderer.domElement);
// 創(chuàng)建軌道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 設置控制器阻尼,讓控制器更有真實效果,必須在動畫循環(huán)里調(diào)用.update()。
controls.enableDamping = true;
// 添加坐標軸輔助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 設置時鐘
const clock = new THREE.Clock();
function render() {
controls.update();
renderer.render(scene, camera);
// 渲染下一幀的時候就會調(diào)用render函數(shù)
requestAnimationFrame(render);
}
render();
// 監(jiān)聽畫面變化,更新渲染畫面
window.addEventListener("resize", () => {
// console.log("畫面變化了");
// 更新攝像頭
camera.aspect = window.innerWidth / window.innerHeight;
// 更新攝像機的投影矩陣
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 設置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});到此這篇關于three.js中物體的燈光與陰影設置的文章就介紹到這了,更多相關three.js 物體燈光與陰影內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

