自定义摄像机¶
除了内置的摄像机类型(透视、正交和全景摄像机)外,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的变量,其中包含光线的通量 - 一个权重系数
可用于调暗或调整摄像机所见颜色的色调。
position 和 direction 均采用摄像机坐标系,其中原点为摄像机本身的位置,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 自动求导来计算这些值。对于一些特殊情况,如果您能够更准确或更高效地计算导数,可以让着色器输出四个额外的变量:dPdx、dPdy、dDdx 和 dDdy。如果存在其中任何一个变量,系统将优先使用其值。请注意,您不能同时使用这两种选项 - 必须明确提供全部或完全不提供。
参数¶
着色器可以定义额外的输入参数。这些参数将在摄像机属性面板的镜头选项下向用户显示。
为了进一步控制其显示方式,可以使用以下 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 中的某些功能(特别是矢量通道和窗口纹理坐标)需要从光线到图像坐标的逆映射。目前自定义摄像机尚不支持此功能。