自定义摄像机

除了内置的摄像机类型(透视、正交和全景摄像机)外,Cycles 还支持使用开放式着色语言(OSL)实现自定义摄像机。

自定义摄像机以 OSL 着色器的形式实现。摄像机着色器接收传感器位置作为输入,并输出对应光线的位置、方向和通量。

OSL 着色和自定义摄像机是相互独立的,因此即使禁用了 OSL 着色,仍可使用自定义摄像机。

使用自定义摄像机

若要使用自定义摄像机,请将镜头类型设置为 自定义

这允许选择文本数据块或外部文件,类似于着色器中的脚本节点

如果所选的摄像机着色器带有参数,这些参数将显示在镜头面板下方。

编写摄像机着色器

输入

摄像机着色器的主要输入是传感器位置。该位置由函数 camera_shader_raster_position() 提供,该函数返回一个点,其 X 和 Y 分量存储了图像内 0-1 范围内的位置。

为了支持着色器中的随机采样,camera_shader_random_sample() 会提供一组随机数,该函数返回一个矢量,其 X 和 Y 分量中包含随机数。对于采样光圈的特定情况,最好使用 cam:aperture_position 属性(见下文),以确保与 Blender 通常的光圈选项兼容。

输出

着色器预计将输出三个变量:
  • position,一个类型为 point 的变量,其中包含生成的光线的起点。

  • direction,一个类型为 vector 的变量,其中包含生成的光线的规格化方向。

  • throughput,一个类型为 color 的变量,其中包含光线的通量 - 一个权重系数

可用于调暗或调整摄像机所见颜色的色调。

positiondirection 均采用摄像机坐标系,其中原点为摄像机本身的位置,Z 轴正方向为视线方向,Y 轴正方向为向上。

如果 throughput 为黑色,则跳过该光线。这可用于(例如)在全景映射中标记无效光线。

属性

由于摄像机着色器并非传统意义上的着色器,因此 OSL 的许多功能(如闭包或与几何体相关的属性)无法使用。

相反,可以通过 getattribute() 获取以下与摄像机相关的属性:

cam:sensor_size

摄像机传感器尺寸,单位为毫米。该值在摄像机属性中设置。

cam:image_resolution

渲染图像的分辨率。

cam:focal_distance

摄像机的焦点距离,单位为毫米。该值在景深属性中设置。

cam:aperture_aspect_ratio

摄像机光圈的宽高比,该值在景深属性中设置。

cam:aperture_size

摄像机光圈的大小,该值在景深属性中设置。

cam:aperture_position

光圈上的一个随机位置,该位置会考虑在景深属性中设置的光圈大小、形状和宽高比。请注意,此处使用的随机数与 camera_shader_random_sample() 提供的随机数相同,因此应避免同时使用这两者,否则会导致相关性问题。

导数

对于某些功能,例如线框节点,Cycles 需要光线起点和方向相对于图像 X 和 Y 坐标的导数。

默认情况下,将使用 OSL 自动求导来计算这些值。对于一些特殊情况,如果您能够更准确或更高效地计算导数,可以让着色器输出四个额外的变量:dPdxdPdydDdxdDdy。如果存在其中任何一个变量,系统将优先使用其值。请注意,您不能同时使用这两种选项 - 必须明确提供全部或完全不提供。

参数

着色器可以定义额外的输入参数。这些参数将在摄像机属性面板的镜头选项下向用户显示。

为了进一步控制其显示方式,可以使用以下 OSL 元数据:

[[ string help = "This is a parameter" ]]

参数的描述,显示在工具提示中。

[[ float sensitivity = 0.25 ]]

拖动或单击时,参数应增加或减少多少。

[[ int digits = 2 ]]

数值参数应显示多少位。

[[ float min = -5, float max = 5 ]]

该属性可以取哪些值。

[[ int slider = 1, float slidermin = -4, float slidermax = 4 ]]

将属性以滑块的形式显示,范围按给定值设置。

[[ string widget = "boolean" ]]

`int` 属性显示为复选框,其取值为 0 或 1。

[[ string widget = "filename" ]]

将参数显示为文件路径选择器。

[[ string widget = "mapper", string options = "left:0|right:1" ]]

将一个整数参数显示为下拉菜单。

options 字符串定义了一个由 | 分隔的标签-值对列表。

[[ string vecsemantics = "POINT" ]]

将矢量参数标记为平移输入(位置矢量)。

[[ string vecsemantics = "NORMAL" ]]

将矢量参数标记为法线输入(方向矢量)。

[[ string unit = "radians" ]]

将浮点参数标记为角度输入,以弧度显示。

[[ string unit = "m" ]]

将浮点参数标记为距离输入,以米显示。

[[ string unit = "mm" ]]

将浮点参数标记为距离输入,以毫米显示。

[[ string unit = "s" ]][[ string unit = "sec" ]]

将浮点参数标记为时间输入,以秒显示。

一个例子

这是一个实现透视摄像机的非常基本的着色器:

shader perspective_camera(
    float focal_length = 90.0 [[ float sensitivity = 0.2, float min = 0 ]],
    output point position = 0.0,
    output vector direction = 0.0,
    output color throughput = 1.0) {
  vector sensor_size;
  getattribute("cam:sensor_size", sensor_size);

  point Pcam = camera_shader_raster_position() - point(0.5);
  Pcam *= sensor_size / focal_length;
  direction = normalize(vector(Pcam.x, Pcam.y, 1.0));
}

更多示例可在此找到:文本编辑器 ‣ 模板 ‣ 开放式着色语言

局限

Important

自定义摄像机不支持 GPU 渲染,除非使用 OptiX 后端。

Cycles 中的某些功能(特别是矢量通道和窗口纹理坐标)需要从光线到图像坐标的逆映射。目前自定义摄像机尚不支持此功能。