所以在Threejs的畫布世界之中,一個物體有自己的影子呢?
陰影效果的實現
你需要先知道在threejs世界中,有哪些燈光或者材質是可以產生陰影效果的
環境光沒有陰影 平行光有陰影(太陽) 點光源有陰影(燈泡) 聚光燈有陰影(手電筒) 平面光源沒有陰影(明亮的窗戶)
基礎網格材質不支持陰影 標準網格材質支持陰影 并且很逼真 代價是性能犧牲 Lambert網格材質(非光澤表面) 支持 Phong網格材質(光澤表面) 支持 ?物理網格材質 支持 比標準網格更逼真 代價是性能犧牲 MeshToon 支持
1.做一個平面,一個球體
// 做一個球體
const SphereGeometry = new THREE.SphereGeometry(1, 20, 20);
// 材質
const material = new THREE.MeshStandardMaterial({});
const sphere = new THREE.Mesh(SphereGeometry, material);
scene.add(sphere);// 創建平面
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
2.添加光源
小球由于沒有光照,所以我們還看不見他,所以給他添加一個光照。添加一個環境光和一個直線光源。
// 燈光
// 環境光
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.渲染器設置開啟陰影效果
我們的渲染器是默認關閉陰影效果的,主要是為了性能考慮,所以在我們需要使用陰影效果的時候需要給他開啟。
// 開啟場景中的陰影貼圖
renderer.shadowMap.enabled = true;
4.各種陰影效果開啟
在實現陰影效果的時候,所有有關的參數都是需要打開的,比如說我們需要設置平面接受陰影,然后小球開啟產生陰影,然后光源開啟產生陰影。
// 小球投射陰影
sphere.castShadow = true;// 平面接收陰影
plane.receiveShadow = true;//設置直線光源產生陰影
directionalLight.castShadow = true;
這時候,我們的陰影效果就產生了。
全部代碼
// 環境光沒有陰影 平行光有陰影(太陽) 點光源有陰影(燈泡) 聚光燈有陰影(手電筒) 平面光源沒有陰影(明亮的窗戶)// 基礎網格材質不支持陰影 標準網格材質支持陰影 并且很逼真 代價是性能犧牲 Lambert網格材質(非光澤表面) 支持 Phong網格材質(光澤表面) 支持 物理網格材質 支持 比標準網格更逼真 代價是性能犧牲 MeshToon 支持//導入 threejs
import * as THREE from "three";
//導入軌道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//導入補時動畫庫
import * as TWEEN from "three/examples/jsm/libs/tween.module.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;// 將渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);//設置相機的焦點 (相機看向哪個點)
camera.lookAt(0, 0, 0);//添加世界坐標輔助器 (紅色x軸,綠色y軸,藍色z軸)一個線段 參數為 線段長度
const axesHelper = new THREE.AxesHelper(5);//添加到場景之中
scene.add(axesHelper);// 添加軌道控制器 (修改偵聽位置) 一般監聽畫布的事件 不監聽document.body
const controls = new OrbitControls(camera, renderer.domElement);//渲染函數
function animate() {controls.update();//請求動畫幀requestAnimationFrame(animate);//渲染renderer.render(scene, camera);//更新補時動畫TWEEN.update();
}//渲染
animate();// 監聽窗口的變化 重新設置渲染器的大小 畫布自適應窗口
window.addEventListener("resize", () => {// 重新設置渲染器的大小renderer.setSize(window.innerWidth, window.innerHeight);// 重新設置相機的寬高比camera.aspect = window.innerWidth / window.innerHeight;// 重新計算相機的投影矩陣camera.updateProjectionMatrix();
});// 做一個球體
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(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);// 燈光
// 環境光
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);