Skip to content

BabylonJS - 镜头光晕

镜头光晕(Lens Flare)是一种光学效果,当明亮的光源(如太阳或强光灯)照射到相机镜头时发生,导致散射和内部反射,在图像中表现为光线、圆形或星芒图案。Babylon.js 允许您模拟这种效果,为场景增加真实感或特定的视觉风格。

镜头光晕由一个 LensFlareSystem(镜头光晕系统)管理。这个系统附加到一个发射源(emitter)上,发射源可以是光源、相机或任何网格(mesh)。当发射源可见时,系统沿着相机和发射源之间的视线渲染单独的光晕元素(纹理)。

首先,您需要创建 LensFlareSystem 并将其关联到一个发射源(例如一个光源)。

import * as BABYLON from '@babylonjs/core';
// Assuming 'scene' and 'lightSource' (e.g., a PointLight or DirectionalLight) are defined
// 假设 'scene' 和 'lightSource'(例如,一个 PointLight 或 DirectionalLight)已经定义
const lensFlareSystem = new BABYLON.LensFlareSystem(
"lensFlareSys",
lightSource, // The emitter object (Light, Camera, or Mesh)
// 发射源对象(光源、相机或网格)
scene
);

镜头光晕效果通常由多个单独的光晕元素组成,每个元素都由一个 BABYLON.LensFlare 对象表示。您需要将这些光晕添加到系统中。

// Parameters: size, position, color, texture URL, parent system
// 参数:大小,位置,颜色,纹理 URL,父系统
// size: Size of the flare element (relative size, e.g., 0.5 means half the system size)
// 大小:光晕元素的大小(相对大小,例如 0.5 表示系统大小的一半)
// position: Position along the line from emitter to camera (0 = at emitter, 1 = at camera)
// 位置:沿发射源到相机连线上的位置(0 = 在发射源处,1 = 在相机处)
// color: Color tint for the flare texture
// 颜色:光晕纹理的颜色叠加
// imgUrl: Path to the texture image for this flare element (often PNGs with transparency)
// 图片 URL:此光晕元素的纹理图像路径(通常是带有透明度的 PNG 图片)
// system: The LensFlareSystem this flare belongs to
// 系统:此光晕所属的 LensFlareSystem
// Example: Add a large central flare at the light source position
// 示例:在光源位置添加一个较大的中心光晕
const flare0 = new BABYLON.LensFlare(0.2, 0, new BABYLON.Color3(1, 1, 1), "textures/flare/flare1.png", lensFlareSystem);
// Example: Add smaller hexagonal flares along the line of sight
// 示例:沿视线方向添加较小的六边形光晕
const flare1 = new BABYLON.LensFlare(0.5, 0.2, new BABYLON.Color3(0.5, 0.8, 1), "textures/flare/flare2.png", lensFlareSystem);
const flare2 = new BABYLON.LensFlare(0.3, 0.4, new BABYLON.Color3(1, 0.8, 0.8), "textures/flare/flare3.png", lensFlareSystem);
const flare3 = new BABYLON.LensFlare(0.6, 0.6, new BABYLON.Color3(0.7, 1, 0.7), "textures/flare/flare2.png", lensFlareSystem);
const flare4 = new BABYLON.LensFlare(0.4, 0.8, new BABYLON.Color3(0.9, 0.7, 1), "textures/flare/flare1.png", lensFlareSystem);

通过组合多个具有不同大小、位置、颜色和纹理的 LensFlare 实例,您可以构建复杂且具有视觉吸引力的光晕效果。

此示例创建了一个简单的场景,其中包含一个光源,并将一个多元素镜头光晕系统附加到该光源上。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Babylon.js - Lens Flare Demo</title>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<style>
html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; }
#renderCanvas { width: 100%; height: 100%; touch-action: none; }
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script type="text/javascript">
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = function () {
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0.05, 0.05, 0.1, 1.0); // Dark blue background
// 深蓝色背景
const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2.5, 20, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
camera.wheelPrecision = 100;
// Use a point light as the emitter for the flare
// 使用点光源作为光晕的发射源
const lightSource = new BABYLON.PointLight("lightSource", new BABYLON.Vector3(0, 0, 0), scene);
lightSource.intensity = 0; // We don't need the light to illuminate, just act as emitter position
// 我们不需要光源照明,只需它作为发射源的位置
// Optional: Add a mesh to represent the light source visually
// 可选:添加一个网格以视觉上表示光源
const sunMesh = BABYLON.MeshBuilder.CreateSphere("sun", {diameter: 1}, scene);
const sunMat = new BABYLON.StandardMaterial("sunMat", scene);
sunMat.emissiveColor = new BABYLON.Color3(1, 1, 0.8);
sunMesh.material = sunMat;
sunMesh.position = lightSource.position; // Position mesh at light source
// 将网格定位在光源处
// --- Lens Flare Setup ---
// --- 镜头光晕设置 ---
const lensFlareSystem = new BABYLON.LensFlareSystem("lensFlareSys", lightSource, scene);
// Ensure flare textures exist in 'textures/flare/' folder
// 确保光晕纹理存在于 'textures/flare/' 文件夹中
try {
// Flare definitions (size, position, color, textureURL, system)
// 光晕定义(大小,位置,颜色,纹理 URL,系统)
new BABYLON.LensFlare(0.2, 0, new BABYLON.Color3(1, 1, 1), "textures/flare/flare1.png", lensFlareSystem);
new BABYLON.LensFlare(0.5, 0.2, new BABYLON.Color3(0.5, 0.5, 1), "textures/flare/flare3.png", lensFlareSystem);
new BABYLON.LensFlare(0.3, 0.4, new BABYLON.Color3(1, 0.5, 0.5), "textures/flare/flare2.png", lensFlareSystem);
new BABYLON.LensFlare(0.1, 0.6, new BABYLON.Color3(1, 1, 0.7), "textures/flare/flare1.png", lensFlareSystem);
new BABYLON.LensFlare(0.4, 0.8, new BABYLON.Color3(0.7, 1, 0.7), "textures/flare/flare3.png", lensFlareSystem);
new BABYLON.LensFlare(0.25, 1.0, new BABYLON.Color3(0.8, 0.7, 1), "textures/flare/flare2.png", lensFlareSystem);
console.log("Lens flare textures presumably loaded (check console for 404s).");
// 镜头光晕纹理可能已加载(检查控制台是否有 404 错误)。
} catch(err) {
console.error("Error creating lens flares - likely texture loading issue:", err);
// 创建镜头光晕时出错 - 可能是纹理加载问题:
}
// ------------------------
// Animate the light source / sun mesh position
// 动画化光源 / 太阳网格的位置
let angle = 0;
scene.onBeforeRenderObservable.add(() => {
angle += 0.01;
lightSource.position.x = 8 * Math.sin(angle);
lightSource.position.z = 8 * Math.cos(angle);
sunMesh.position = lightSource.position; // Keep visual mesh synced
// 保持视觉网格同步
});
return scene;
};
const scene = createScene();
engine.runRenderLoop(function () {
scene.render();
});
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>

此示例演示需要几个位于 textures/flare/ 文件夹(相对于 HTML 文件)中的 PNG 图片文件(flare1.png、flare2.png、flare3.png)。这些图片通常应为圆形或星芒形状,并带有透明背景,以创建光晕效果。

该示例演示显示一个深蓝色场景,其中有一个发光的黄色球体(代表太阳或光源)在中心周围沿圆形路径移动。当黄色球体在屏幕上可见时,会出现一个镜头光晕效果,它源自球体并朝向视野中心延伸。光晕由多个彩色、带有纹理的元素(圆形、六边形等,取决于加载的 PNG 图片)组成,沿此线排列。随着球体移动和您旋转相机,镜头光晕会根据球体相对于相机视野的位置出现、消失并改变强度。

与复杂的几何体或后处理效果相比,镜头光晕系统的渲染成本相对较低,但拥有许多复杂的系统或非常高分辨率的光晕纹理仍可能影响性能。仅在它们能显著增加视觉效果的地方使用它们。