three.js中物體的燈光與陰影設(shè)置
一、.設(shè)置物體陰影的核心步驟
1. 以平面上有一個球體為例,設(shè)置球體的陰影投射到平面上
核心步驟如下:
要讓球體的陰影照射到平面上,需要使用陰影映射技術(shù)。具體步驟如下:
在渲染器中啟用陰影:
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);
設(shè)置球體和聚光燈的關(guān)系:
sphere.add(light); // 球體作為聚光燈的子元素
現(xiàn)在打開瀏覽器預(yù)覽,就可以看到球體的陰影照射到了平面上。如果想讓陰影更加自然,可以調(diào)整陰影相關(guān)的參數(shù),例如增大陰影貼圖的分辨率、調(diào)整聚光燈的角度、調(diào)整陰影偏差等。
2. 設(shè)置正方體和球體的燈光與陰影:
效果如圖:
核心步驟和案例一一樣,就不在贅述,這里給出完整代碼,如下:
import * as THREE from "three"; // 導(dǎo)入軌道控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 目標(biāo):燈光與陰影 // 燈光陰影 // 1、材質(zhì)要滿足能夠?qū)庹沼蟹磻?yīng) // 2、設(shè)置渲染器開啟陰影的計(jì)算 renderer.shadowMap.enabled = true; // 3、設(shè)置光照投射陰影 directionalLight.castShadow = true; // 4、設(shè)置物體投射陰影 sphere.castShadow = true; // 5、設(shè)置物體接收陰影 plane.receiveShadow = true; // 1、創(chuàng)建場景 const scene = new THREE.Scene(); // 2、創(chuàng)建相機(jī) const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); // 設(shè)置相機(jī)位置 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)建標(biāo)準(zhǔn)材質(zhì) const sphere = new THREE.Mesh(sphereGeometry, material); // 根據(jù)幾何體和材質(zhì)創(chuàng)建球體 sphere.position.set(1, 0, 0); // 設(shè)置球體位置 // 設(shè)置球體顏色 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)建標(biāo)準(zhǔn)材質(zhì) const materialcube = new THREE.MeshStandardMaterial(); const cube = new THREE.Mesh(cubeGeometry, materialcube); // 根據(jù)幾何體和材質(zhì)創(chuàng)建立方體 cube.position.set(-1, 0, 2); // 設(shè)置立方體位置 // 設(shè)置立方體顏色 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)建標(biāo)準(zhǔn)材質(zhì) const materialplane = new THREE.MeshStandardMaterial(); const plane = new THREE.Mesh(planeGeometry, materialplane); // 根據(jù)幾何體和材質(zhì)創(chuàng)建平面 plane.position.set(0, -1, 0); // 設(shè)置平面位置 plane.rotation.x = -Math.PI / 2; // 設(shè)置平面旋轉(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ù):光源顏色、光源強(qiáng)度 directionalLight.position.set(10, 10, 10); // 設(shè)置光源位置 directionalLight.castShadow = true; // 設(shè)置光照投射陰影 scene.add(directionalLight); // 初始化渲染器 const renderer = new THREE.WebGLRenderer(); // 設(shè)置渲染的尺寸大小 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); // 設(shè)置控制器阻尼,讓控制器更有真實(shí)效果,必須在動畫循環(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; // 更新攝像機(jī)的投影矩陣 camera.updateProjectionMatrix(); // 更新渲染器 renderer.setSize(window.innerWidth, window.innerHeight); // 設(shè)置渲染器的像素比 renderer.setPixelRatio(window.devicePixelRatio); });
二、直行光源DirectionalLightShadow的陰影屬性和相機(jī)原理介紹
在three.js中,使用new THREE.DirectionalLight可以創(chuàng)建一個方向光源。這個光源可以通過設(shè)置陰影屬性來讓場景中的對象產(chǎn)生陰影。設(shè)置陰影屬性需要使用DirectionalLight類的shadow屬性,它是一個DirectionalLightShadow對象,可以設(shè)置以下屬性:
- mapSize:陰影貼圖的大小??梢允褂肨HREE.Vector2或者數(shù)字類型的參數(shù)來設(shè)置。
- bias:偏移量,用于保持陰影的正確性??梢允褂脭?shù)字類型的參數(shù)來設(shè)置。
- camera:陰影相機(jī)。使用DirectionalLightShadow.camera屬性可以獲取到DirectionalLightShadow對應(yīng)的Camera對象,從而可以對相機(jī)進(jìn)行設(shè)置。
相機(jī)原理:在three.js中,相機(jī)是場景中的虛擬相機(jī),用于模擬真實(shí)世界中的相機(jī)。相機(jī)的工作原理類似于真實(shí)世界中的相機(jī),它可以控制場景的可見區(qū)域、切換視角、實(shí)現(xiàn)景深等效果。在場景中添加相機(jī)之后,可以通過設(shè)置相機(jī)的各個屬性來控制相機(jī)的位置、旋轉(zhuǎn)、縮放等,從而實(shí)現(xiàn)不同的視角和效果。
相機(jī)相關(guān)屬性設(shè)置:在three.js中,可以通過設(shè)置相機(jī)的各個屬性來控制相機(jī)的行為和效果。以下是一些常用的相機(jī)屬性:
- position:相機(jī)的位置。
- near:相機(jī)的近裁剪面距離。
- far:相機(jī)的遠(yuǎn)裁剪面距離。
- fov:相機(jī)的視角。
舉例說明:下面是一個用于產(chǎn)生陰影的DirectionalLight對象的創(chuàng)建和設(shè)置陰影屬性的代碼示例:
核心代碼
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(20, 30, -5); directionalLight.castShadow = true; directionalLight.shadow.mapSize.width = 1024; // 設(shè)置陰影貼圖的寬度 directionalLight.shadow.mapSize.height = 1024; // 設(shè)置陰影貼圖的高度 directionalLight.shadow.bias = -0.01; // 設(shè)置陰影的偏移量 directionalLight.shadow.camera.near = 1; // 設(shè)置陰影相機(jī)的近裁剪面距離 directionalLight.shadow.camera.far = 100; // 設(shè)置陰影相機(jī)的遠(yuǎn)裁剪面距離 directionalLight.shadow.camera.fov = 45; // 設(shè)置陰影相機(jī)的視角
完整示例效果如上圖所示,完整示例代碼如下:
import * as THREE from "three"; // 導(dǎo)入軌道控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 導(dǎo)入dat.gui import * as dat from "dat.gui"; const gui = new dat.GUI(); // 1、創(chuàng)建場景 const scene = new THREE.Scene(); // 2、創(chuàng)建相機(jī) const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); // 設(shè)置相機(jī)位置 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; // 設(shè)置陰影貼圖模糊度 directionalLight.shadow.radius = 20; // 設(shè)置陰影貼圖的分辨率 directionalLight.shadow.mapSize.set(4096, 4096); // 設(shè)置平行光投射相機(jī)的屬性 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(); // 設(shè)置渲染的尺寸大小 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); // 設(shè)置控制器阻尼,讓控制器更有真實(shí)效果,必須在動畫循環(huán)里調(diào)用.update()。 controls.enableDamping = true; // 添加坐標(biāo)軸輔助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 設(shè)置時鐘 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; // 更新攝像機(jī)的投影矩陣 camera.updateProjectionMatrix(); // 更新渲染器 renderer.setSize(window.innerWidth, window.innerHeight); // 設(shè)置渲染器的像素比 renderer.setPixelRatio(window.devicePixelRatio); });
到此這篇關(guān)于three.js中物體的燈光與陰影設(shè)置的文章就介紹到這了,更多相關(guān)three.js 物體燈光與陰影內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于div自適應(yīng)高度/左右高度自適應(yīng)一致的js代碼
在DIV和CSS進(jìn)行網(wǎng)頁布局中,DIV的自適應(yīng)高度和自適應(yīng)寬度是一個很常見的問題,本文將介紹左右自適應(yīng)高度一致的Jquery與DIV高度自適應(yīng)屏幕的js2013-03-03echarts中幾種漸變方式的具體實(shí)現(xiàn)方式
在使用echarts繪制圖表時,有的時候需要使用漸變色,下面這篇文章主要給大家介紹了關(guān)于echarts中幾種漸變方式的具體實(shí)現(xiàn)方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11js實(shí)現(xiàn)的復(fù)制兼容chrome和IE
這篇文章主要介紹了js在chrome和IE下分別實(shí)現(xiàn)復(fù)制,需要的朋友可以參考下2014-04-04javascript實(shí)現(xiàn)的制作特殊字的腳本
javascript實(shí)現(xiàn)的制作特殊字的腳本...2007-06-06