跳转至

灯光与材质

LightsHero
影片代码
import manimgx as m


class LightsHero(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=70 * m.DEGREES, theta=-45 * m.DEGREES)
        self.add(m.SunLight(5 * m.UP + 3 * m.OUT), m.AmbientLight(intensity=0.2))
        spheres = m.Group()
        for roughness in [0.2, 0.5, 0.9]:
            sphere = m.Sphere(radius=0.8, resolution=(48, 48)).set_color(m.GOLD)
            spheres.add(
                sphere.set_material(m.Material(metallic=1, roughness=roughness))
            )
        spheres.arrange(buff=0.6)
        self.add(spheres)
        self.wait()

3D 场景由其灯光照明:像添加 mobject 一样添加它们。太阳从一个方向照亮一切;灯泡在周围照明, 随距离衰减;聚光灯照亮一个锥形区域;天空从四面八方将一切微微照亮。没有灯光时,场景保持 Manim 的普通着色。

mobject 的材质描述其曲面如何反射光线:粗糙或光滑,塑料或金属。

灯光

Light

一种光源:在其所在点处具有自身的颜色和亮度(每种类型以各自的方式读取该点)。

m.Light(location=ORIGIN, color=WHITE, intensity=1.0, **kwargs)
location

光源所在位置,以场景坐标表示。

color

光源的颜色。

intensity

光源的亮度:1 使得面向它的白色哑光表面呈现为白色。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\lights.py

def __init__(
    self,
    location: Point3DLike = ORIGIN,
    color: ParsableManimColor = WHITE,
    intensity: float = 1.0,
    **kwargs: Unpack[Look],
) -> None:
    self.light_color = ManimColor(color)
    self.intensity = intensity
    super().__init__(location, **kwargs)

kind

渲染器读取它的方式:0 环境光、1 太阳光、2 点光源、3 聚光灯、4 环境光照。

SunLight

代码
import manimgx as m


class SunLightExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=65 * m.DEGREES, theta=-45 * m.DEGREES)
        sun = m.SunLight(5 * m.RIGHT + 3 * m.OUT)
        self.add(sun, m.AmbientLight(intensity=0.15))
        self.add(m.Sphere(resolution=(48, 48)).set_material(m.Material()))
        self.play(
            m.Rotate(sun, m.PI, axis=m.OUT, about_point=m.ORIGIN), run_time=3
        )

来自远处的平行光,从其所在点相对于原点的方向射来: 围绕原点移动该点即可转动光源。

m.SunLight(location=4 * UP + 3 * LEFT + 5 * OUT, color=WHITE, intensity=1.0, shadows=True, **kwargs)
location

光源来自的方向:即其相对于原点的方向。

color

光源的颜色。

intensity

光源的亮度:1 使得面向它的白色哑光表面呈现为白色。

shadows

它所照亮的物体是否投射阴影(作用于带有材质的 mobject)。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\lights.py

def __init__(
    self,
    location: Point3DLike = 4 * UP + 3 * LEFT + 5 * OUT,
    color: ParsableManimColor = WHITE,
    intensity: float = 1.0,
    shadows: bool = True,
    **kwargs: Unpack[Look],
) -> None:
    self.shadows = shadows
    super().__init__(location, color, intensity, **kwargs)

PointLight

代码
import manimgx as m


class PointLightExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=70 * m.DEGREES, theta=-30 * m.DEGREES)
        lamp = m.PointLight(2 * m.OUT + 2 * m.LEFT, m.ORANGE, intensity=6)
        self.add(lamp, m.AmbientLight(intensity=0.05))
        floor = m.Surface(
            lambda u, v: [u, v, -1], u_range=[-4, 4], v_range=[-4, 4]
        )
        self.add(floor.set_material(m.Material(roughness=0.4)))
        self.play(lamp.animate.shift(4 * m.RIGHT), run_time=3)

从其所在点向各个方向发出的光,如同灯泡:其亮度随距离的平方衰减, 并在 radius 处完全消失。

m.PointLight(location=3 * OUT, color=WHITE, intensity=1.0, radius=20.0, **kwargs)
location

光源所在位置,以场景坐标表示。

color

光源的颜色。

intensity

距其一个单位距离处的亮度:1 使得在该处面向它的白色哑光表面 呈现为白色。

radius

光照到达的距离,以场景单位表示。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\lights.py

def __init__(
    self,
    location: Point3DLike = 3 * OUT,
    color: ParsableManimColor = WHITE,
    intensity: float = 1.0,
    radius: float = 20.0,
    **kwargs: Unpack[Look],
) -> None:
    self.radius = radius
    super().__init__(location, color, intensity, **kwargs)

SpotLight

SpotLightExample
代码
import manimgx as m


class SpotLightExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=60 * m.DEGREES, theta=-60 * m.DEGREES)
        self.add(
            m.SpotLight(
                4 * m.OUT, toward=m.ORIGIN, intensity=20, angle=m.PI / 8
            )
        )
        floor = m.Surface(
            lambda u, v: [u, v, 0], u_range=[-4, 4], v_range=[-4, 4]
        )
        self.add(floor.set_material(m.Material(roughness=0.7)))

点光源的锥形光束:从其所在点指向 toward 点,在其轴线两侧各 angle 宽度内展开, 锥边在角度的外侧 softness 范围内柔和过渡。

m.SpotLight(location=4 * OUT, toward=ORIGIN, color=WHITE, intensity=1.0, radius=20.0, angle=PI / 6, softness=0.2, shadows=True, **kwargs)
location

光源所在位置,以场景坐标表示。

toward

光束所指向的点。

color

光源的颜色。

intensity

距其一个单位距离处、沿轴线方向的亮度。

radius

光照到达的距离,以场景单位表示。

angle

锥形光束开口的一半,以弧度表示。

softness

在锥边处 angle 的比例,光照在该范围内逐渐衰减。

shadows

它所照亮的物体是否投射阴影(作用于带有材质的 mobject)。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\lights.py

def __init__(
    self,
    location: Point3DLike = 4 * OUT,
    toward: Point3DLike = ORIGIN,
    color: ParsableManimColor = WHITE,
    intensity: float = 1.0,
    radius: float = 20.0,
    angle: float = PI / 6,
    softness: float = 0.2,
    shadows: bool = True,
    **kwargs: Unpack[Look],
) -> None:
    self.shadows = shadows
    self.toward = np.asarray(toward, dtype=float)
    self.angle = angle
    self.softness = softness
    super().__init__(location, color, intensity, radius, **kwargs)

AmbientLight

AmbientLightExample
代码
import manimgx as m


class AmbientLightExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=70 * m.DEGREES, theta=-40 * m.DEGREES)
        self.add(m.AmbientLight(m.BLUE_A, intensity=0.4))
        self.add(m.Sphere(resolution=(48, 48)).set_material(m.Material()))

来自各个方向均相同的光:天空,或房间灯光经墙壁反射回来的光。 它照亮其他光源无法触及的部分,使任何地方都不会变成纯黑。

m.AmbientLight(color=WHITE, intensity=0.1, **kwargs)
color

光源的颜色。

intensity

光源的亮度:1 使得从任何方向看白色哑光表面都呈现为白色。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\lights.py

def __init__(
    self,
    color: ParsableManimColor = WHITE,
    intensity: float = 0.1,
    **kwargs: Unpack[Look],
) -> None:
    super().__init__(ORIGIN, color, intensity, **kwargs)

EnvironmentLight

代码
import manimgx as m


class EnvironmentLightExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=70 * m.DEGREES, theta=-50 * m.DEGREES)
        studio = m.EnvironmentLight()
        self.add(studio)
        for i, roughness in enumerate([0.05, 0.35, 0.8]):
            ball = m.Sphere(radius=0.8, resolution=(64, 64)).set_color(m.GREY_A)
            ball.set_material(m.Material(metallic=1, roughness=roughness))
            self.add(ball.shift(2 * (i - 1) * m.RIGHT))
        self.play(m.Rotate(studio, m.TAU, axis=m.OUT), run_time=4)

来自周围环境的光:一张周围环境的图像,每个方向的光即图像中该方向处的光, 如同在拍摄地点所看到的那样。金属表面会镜像它,粗糙表面会模糊它, 哑光表面则从各个方向接收其光照。图像中的太阳如同太阳光源一样照明: 其光仅来自其方向,并投射阴影。一个场景由一张图像照明 (第二个环境光会显示第一个环境光所对应的图像)。

该图像为全景图(等距矩形投影:一种 Radiance .hdr 文件,宽度为高度的两倍), 其上方对应场景的上方(OUT),其中心朝向沿 RIGHT 方向看去。 旋转该光源即可转动其周围环境:其点表示光源所在位置,而距其一个单位距离处 分别为图像的 RIGHT 方向和上方。

m.EnvironmentLight(picture=None, color=WHITE, intensity=1.0, shadows=True, **kwargs)
picture

一个 Radiance(.hdr)文件的路径;为 None 时使用内置摄影棚 (内置提供:一间昏暗的房间,配有柔光箱:在 Manim 光源位置处的主光、 一盏补光、一条用于勾勒轮廓的条形光,以及一盏顶光)。

color

光源的色调:图像的光乘以此颜色。

intensity

光源的亮度:图像的光乘以此值(一张四周光强均为 1 的图像 会使白色哑光表面呈现为白色)。

shadows

图像中的太阳(若存在)是否投射阴影(作用于带有材质的 mobject)。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\lights.py

def __init__(
    self,
    picture: str | Path | None = None,
    color: ParsableManimColor = WHITE,
    intensity: float = 1.0,
    shadows: bool = True,
    **kwargs: Unpack[Look],
) -> None:
    # (None: the studio, which the engine makes)
    self.picture = None if picture is None else _picture(Path(picture).read_bytes())
    self.shadows = shadows
    super().__init__(ORIGIN, color, intensity, **kwargs)
    # its picture's right and up, a unit from its point: turned with it
    self.add(VectorizedPoint(RIGHT), VectorizedPoint(OUT))

材质

Material

MaterialExample
代码
import manimgx as m


class MaterialExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(phi=70 * m.DEGREES, theta=-45 * m.DEGREES)
        self.add(
            m.SunLight(5 * m.UP + 3 * m.OUT), m.AmbientLight(intensity=0.2)
        )
        for i, roughness in enumerate([0.2, 0.5, 0.9]):
            sphere = m.Sphere(radius=0.8, resolution=(48, 48))
            sphere.set_color(m.GOLD).shift(2 * (i - 1) * m.RIGHT)
            self.add(
                sphere.set_material(m.Material(metallic=1, roughness=roughness))
            )

表面如何反射光线:一种基于物理的模型,其基色为 mobject 的填充色。

带有材质的 mobject 由场景中的光源 (SunLight、PointLight、 SpotLight、AmbientLight、 EnvironmentLight)在三维场景中照亮,未带材质者保持 Manim 的着色 (shade_in_3d)。表面会被照亮,平面填充形状亦然(其填充:形状的描边保持其 颜色);场景中所展示物体的阴影会落在其上。固定于画面中的内容不在场景中,亦不被照亮。 材质可补间:其数值按颜色方式混合。

m.Material(metallic=0.0, roughness=0.5, reflectance=0.5)
metallic

金属感的程度,从 0(电介质:塑料、油漆、石头、皮肤)到 1 (金属,其反射取其颜色)。

roughness

粗糙程度,从 0(镜面光洁:锐利高光)到 1(哑光)。

reflectance

电介质正对时反射多少,取值从 0 到 1(0.5:4%, 多数材料;0.35:水的 2%;1:16%,宝石)。

set_material

代码
import manimgx as m


class MobjectSetMaterialExample(m.ThreeDScene):
    def construct(self) -> None:
        self.set_camera_orientation(
            phi=65 * m.DEGREES, theta=-50 * m.DEGREES
        )
        self.add(
            m.SunLight(4 * m.LEFT + 6 * m.OUT),
            m.AmbientLight(intensity=0.15),
        )
        torus = m.Torus(resolution=(48, 24)).set_color(m.TEAL)
        self.add(torus.set_material(m.Material(roughness=0.25)))
        self.play(
            torus.animate.set_material(
                m.Material(metallic=1, roughness=0.6)
            )
        )

为 mobject 赋予一个场景光照可从其反射的表面,在三维 场景中:其填充颜色为该表面的基础颜色。

mobject.set_material(material, family=True)
material

表面如何反射光照(参见 Material);None 表示 Manim 的着色方式。

family

其整个家族是否采用该材质,还是仅 mobject 本身。

返回 此 mobject,用于链式调用。

源码

manimgx\mobject.py

def set_material(self, material: Material | None, family: bool = True) -> Self:
    """为 mobject 赋予一个场景光照可从其反射的表面,在三维
    场景中:其填充颜色为该表面的基础颜色。

    Args:
        material: 表面如何反射光照(参见 [Material][manimgx.Material]);None
            表示 Manim 的着色方式。
        family: 其整个家族是否采用该材质,还是仅 mobject 本身。

    Returns:
        此 mobject,用于链式调用。

    Examples:
        ```python
        import manimgx as m


        class MobjectSetMaterialExample(m.ThreeDScene):
            def construct(self) -> None:
                self.set_camera_orientation(
                    phi=65 * m.DEGREES, theta=-50 * m.DEGREES
                )
                self.add(
                    m.SunLight(4 * m.LEFT + 6 * m.OUT),
                    m.AmbientLight(intensity=0.15),
                )
                torus = m.Torus(resolution=(48, 24)).set_color(m.TEAL)
                self.add(torus.set_material(m.Material(roughness=0.25)))
                self.play(
                    torus.animate.set_material(
                        m.Material(metallic=1, roughness=0.6)
                    )
                )
        ```
    """
    for mob in self.get_family() if family else [self]:
        mob.paint = mob.paint.but(material=material)
    return self

set_shade_in_3d

设置三维场景的光照是否对路径及其家族着色。

path.set_shade_in_3d(value=True, z_index_as_group=False)
value

光照是否对它们着色。

z_index_as_group

家族的每个成员是否也将该路径作为 其 z-index 组,保留此选项用于 Manim 兼容性(渲染器按深度绘制三维场景)。

源码

manimgx\mobject.py

def set_shade_in_3d(
    self, value: bool = True, z_index_as_group: bool = False
) -> Self:
    """设置三维场景的光照是否对路径及其家族着色。

    Args:
        value: 光照是否对它们着色。
        z_index_as_group: 家族的每个成员是否也将该路径作为
            其 z-index 组,保留此选项用于
            Manim 兼容性(渲染器按深度绘制三维场景)。
    """
    for mob in self.get_family():
        mob.paint = mob.paint.but(shade_in_3d=value)
        if z_index_as_group:
            mob.z_index_group = self
    return self