
ursina 引擎本身不支持物理光照衰减、点光源阴影或体积光等高级光照特性;官网示例中的“聚光灯效果”实为基于 projector_shader 的纹理叠加假象,本质是无光照计算的视觉模拟。
ursina 引擎本身不支持物理光照衰减、点光源阴影或体积光等高级光照特性;官网示例中的“聚光灯效果”实为基于 projector_shader 的纹理叠加假象,本质是无光照计算的视觉模拟。
Ursina 是一个面向教育与快速原型开发的 Python 3D 框架,其设计哲学强调简洁性与易用性,因此并未内置完整的 PBR 光照管线或实时阴影系统(如 PCF 阴影贴图、shadow mapping)。官网首页展示的“聚光灯照射地面”的效果(见 原始截图)常被误认为是真实光照,但实际源码揭示:它来自 ursina/shaders/projector_shader.py 中的 projector_shader —— 一种纯屏幕空间纹理投射技术,而非 Light 类的渲染结果。
该 shader 的核心逻辑是:将一张带渐变透明度的圆形 vignette 纹理(如 circle.png 或自定义光斑图),以透视方式“投射”到场景几何体表面,模拟聚光灯高亮区域。它不参与光照计算,不响应材质 albedo/emission,也不产生任何阴影或光强衰减(例如无距离平方反比衰减、无角度余弦衰减)。你无法通过调整 Light.intensity 或 Light.color 来控制它,因为它根本不是 Light 实例。
✅ 正确使用方式示例:
from ursina import *
from ursina.shaders import projector_shader
app = Ursina()
# 创建一个接收“投影”的平面(如地板)
floor = Entity(
model='plane',
scale=(10, 10),
texture='white_cube',
collider='box'
)
# 创建一个“投影器”实体(位置即光心,rotation 决定投射方向)
projector = Entity(
parent=camera, # 通常绑定相机,实现“随视角移动”的聚光灯效果
position=(0, 2, 5), # 相对于相机的偏移
rotation=(0, 0, 0)
)
# 应用 projector_shader 到地板,并指定投影源
floor.shader = projector_shader
floor.set_shader_input('projector', projector)
floor.set_shader_input('texture', 'circle') # 使用内置 circle 纹理(边缘透明)
app.run()⚠️ 关键注意事项:
- projector_shader 仅作用于单个 Entity,需显式调用 set_shader_input 绑定投影源与纹理;
- 投影方向由 projector 实体的 forward 向量决定,建议用 parent=camera + look_at() 动态对齐;
- 若需多区域投影(如多个聚光灯),需为每个目标 Entity 单独设置 shader 及输入,不可复用同一 shader 实例;
- 真正的动态阴影目前仅支持 DirectionalLight(通过 DirectionalLight(shadow_map_resolution=1024) 启用,但需模型启用 cast_shadow=True 且光源 receive_shadows=True);
- 点光源(PointLight)和聚光灯(SpotLight)在当前 Ursina 版本(v4.1+)中仅影响着色器基础亮度,不生成阴影,也无衰减模型——它们更像“全局乘数开关”,而非物理光源。
? 总结:
若你的项目需要视觉引导(如 UI 式聚光提示、舞台追光效果),projector_shader 是轻量高效的选择;但若目标是写实光照(如室内漫反射、软阴影、IBL 环境光),建议导出至支持完整光照管线的引擎(如 Blender Cycles、Godot 或 Unity),或在 Ursina 中结合后处理(如自定义 glow shader)进行风格化增强。理解 Ursina 的“渲染抽象层级”——它封装了 OpenGL 基础,但有意省略了复杂光照子系统——是合理设定开发预期的关键。










