Arnold(C4DToA)阿诺德渲染教程(101) Open Shading Language (OSL) 开放的着色器语言

Arnold(C4DToA)阿诺德渲染教程(101) Open Shading Language (OSL) 开放的着色器语言 - R站|学习使我快乐! - 1
开放的着色器编程语言 (OSL)是一个由 Sony Pictures Imageworks (索尼影业旗下的 Imageworks 公司)开发的着色器编程语言,OSL 的表面和体积着色器,定义了物体的表面和体积,如何使用重要性采样来发散光线,因此,OSL 语言很适合支持光线追踪和全局光照的物理渲染器,比如:Arnold 渲染器。这种语言同时也被 V-Ray 3 和 Blender 里面的 Cycles 渲染器(从 Blender 2.65 开始)支持。

Arnold(C4DToA)阿诺德渲染教程(101) Open Shading Language (OSL) 开放的着色器语言 - R站|学习使我快乐! - 2

在 Arnold5.0 中,OSL 着色器可以实现简单的纹理图案到闭包材质,非常牛逼。它是一种替代 C++的着色器方案,并拥有简单高效的编写方法。

安装:
只需要将 OSL 着色器(.OSL,.MTD)放置在 plugins/C4DtoA/shaders 目录下即可使用,重启 Arnold 会自动加载生成节点,和其他着色器一样使用;
如果有 UI 资源文件(.Res,.h,.STR),可放置在/plugins/C4DtoA/res 中;
还可以使用 ARNOLD_PLUGIN_PATH,来指定着色器搜索路径。
使用 Kick 命令可以检测着色器及其参数:

$ kick -info gamma
node:         gamma
type:         shader
output:       RGB
parameters:   3
filename:     gamma.oso
version:      4.2.12.0
Type          Name                              Default
------------  --------------------------------  --------------------------------
RGB           Cin                               0, 0, 0
FLOAT         exponent                          1
STRING        name

局限性:
着色器名称必须唯一,否则不会加载,可以通过日志看到记录;
目前只支持一个输出参数,不支持多个输出。

Arnold(C4DToA)阿诺德渲染教程(101) Open Shading Language (OSL) 开放的着色器语言 - R站|学习使我快乐! - 3

工作流:
OSL 着色器一般为.OSL 文件,每个文件对应一个阿诺德着色器节点(可以在节点编辑器中找到),看例子:
Gamma.osl

shader gamma(   //与文件名一致
color Cin = color(0, 0, 0),
float exponent = 1,
output color Cout = color(0, 0, 0))
{
Cout = pow(Cin, 1/exponent);
}

着色器问见面 Gamma.osl,所以 shader 的名称需要与其一致;
着色器定义的输入输出参数很像 Arnold C++的着色器节点,但语法更紧凑;
这里 Cin 和 gamma 是输入参数,而 Cout 是输出参数,所有参数必须用默认初始化值。

编译:
阿诺德会自动搜索到着色器并进行自动编译,编译后在.OSL 文件的同目录中,会多出一个.OSO 文件.
如果没有对应的.OSO 或.OSL 被修改,通常会进行自动编译。
你也可以使 Arnold 的 OSLC 程序手动编译。

$ oslc gamma.osl
Compiled gamma.osl -> gamma.oso

.OSO 文件包含了与操作系统和 CPU 指令无关的中间代码。
在渲染的时候,.OSL 会动态的将着色器节点转换为机器代码,并且最大化的优化着色器,从分利用着色器节点的参数。

手动加载着色器
除了前面的可以自动搜素之外,还可以通过 OSL 节点手动加载着色器。
你可以将表达式插入到着色器节点中,让它加载别的着色器,从而进行更多的控制。
OSL 使用 shadername 参数来指定加载的着色器,不需要.osl 或.oso 后缀;
一旦用 shadername 参数,OSL 就会被添加到节点同,同时具有 param_ 前缀;

osl
{
 name myshader
 shadername somefolder/test  //加载着色器
 param_value 0.5
}

当然你也可以直接嵌入.OSL 代码

osl
{
 name myshader
 code "shader test(float value = 0, output float result = 0)//嵌入着色器
       {
          result = value * 10;
       }"
 param_value 0.5
}

支持特性
参数
通常情况下,OSL 的默认参数会被转换成相应的 Arnold 参数,因为 Arnold 只目前只支持一个输出参数,因此如果有多个输出参数,将以第一个为准。

OSL 类型
Arnold 类型
int INT
int (with metadata)
BOOLEAN
int (with metadata)
ENUM
float FLOAT
color RGB
color RGBA
point VECTOR
vector VECTOR
normal VECTOR
point POINT2
matrix MATRIX
array of any type ARRAY
closure color CLOSURE
struct POINTER

布尔和枚举参数使用的是 OSL 元数据的整数创建的。

#define OPTION_A 0
#define OPTION_B 1
#define OPTION_C 2
 
shader example(
    int booleanvalue = 0 [[ string widget = "boolean" ]],
    int enumvalue = 0 [[ string widget = "popup", string options = "OptionA|OptionB|OptionC" ]])
{
    if (booleanvalue)
        ...
    if (enumvalue == OPTION_B)
        ...
}

属性
节点参数和用户数据可通过 getattribute()方法获得。

// 对象参数
int id;
getattribute("id", id);
 
// 对象用户数据
color Cs;
getattribute("Cs", Cs);
 
// 来自其他节点的参数
int AA_samples;
getattribute("options", "AA_samples", AA_samples);

标准参数
使用以下属性,如果 getattribute()函数指定 objectname 参数,就会检索特定于该对象的值。如果没有指定特定对象,则表示当前对象。

名称
类型
描述
"geom:type" string 对象类型
"geom:name" string 对象名称
"geom:bounds point[2] 世界空间中的对象边界框 (min, max)
"geom:objbounds" point[2] 对象空间中的对象边界框 (min, max)

标准相机属性

使用以下属性,如果 getattribute()函数指定了 objectname 参数,并且它是有效摄像机的名称,则检索特定于该摄像机的值。如果没有指定特定的摄像机,则表示全局摄像机或默认摄像机。

名称
类型
描述
"camera:screen_window" int[2] 图像分辨率
"camera:pixelaspect" float 像素长宽比
"camera:projection" string 摄像机类型
"camera:fov" float 视野
"camera:clip_near" float 近端修剪距离
"camera:clip_far" float 远端修剪距离
"camera:clip" float[2] 近端和远端修剪距离
"camera:shutter_open" float 快门打开时间
"camera:shutter_close" float 快门关闭时间
"camera:shutter" float[2] 快门打开和关闭时间
"camera:screen_window" float[4] 屏幕窗口 (xmin, ymin, xmax, ymax)

着色器全局

Arnold 支持大多数 OSL 着色器全局格式,如 P, u, v, N, Ng 和 time。它们的含义与 c++ shading API 中的含义相同。
目前不支持 Ps(用于光滤镜)、surfacearea()、dtime 和 dPdtime 着色器全局。
所有着色器全局都被认为是只读的,我们不支持对 Ci 和 P 进行写操作以输出闭包或置换。应该使用输出参数。标准相机属性
使用以下属性,如果 getattribute()函数指定了 objectname 参数,并且它是有效摄像机的名称,则检索特定于该摄像机的值。
如果没有指定特定的摄像机,则表示全局摄像机或默认摄像机。

纹理

通过内置的 texture()和 gettextureinfo()函数访问纹理。函数的作用是:接受一个可选的 colorspace 参数来表示要转换的纹理的颜色空间。
注意,与 Arnold c++ shading API 不同的是,为了与 OSL 标准保持一致,纹理原点假设位于左上角而不是左下角。
为了匹配,在 UDIM 纹理的情况下,v 坐标可以翻转到 1 - v,或者 floor(v) + 1 - mod(v, 1)。

// 目标纹理颜色
color tex = texture(filename, u, v);
 
// 查询纹理分辨率
int resolution;
gettextureinfo(filename, "resolution", resolution);

体积通道
体积通道可以通过使用对象空间坐标的 texture3d()获得。

point Po = transform("object", P);
float density = texture3d("density", Po, "interp", "bicubic");

闭包
支持以下闭包,与c++ shader API中的闭包相匹配。

closure color emission();
closure color background();
closure color diffuse(normal N);
closure color oren_nayar (normal N, float sigma);
closure color translucent(normal N);
closure color microfacet(string distribution, normal N, vector U,
                         float xalpha, float yalpha, float eta, int refract);
closure color microfacet(string distribution, normal N,
                         float alpha, float eta, int refr);
closure color reflection(normal N, float eta);
closure color reflection(normal N);
closure color refraction(normal N, float eta);
closure color transparent();
closure color holdout();
closure color empirical_bssrdf(vector mfp, color albedo);
closure color volume_absorption();
closure color volume_emission();
closure color volume_henyey_greenstein(color absorption, color scattering,
                                       color emission, float g);

示例着色器输出一个闭包:

shader simple_diffuse(
    color albedo = 0.8,
    float opacity = 1.0,
    output closure color result = 0)
{
    result = opacity * albedo * diffuse(N) + (1 - opacity) * transparent();
}

跟踪

支持 OSL trace()函数,用于跟踪射线。不支持执行着色的阴影参数。
traceset 参数是受支持的,默认情况下使用一个包含的 traceset,如果 traceset 名称的前缀是- character eter,则为 exclusive。
有关命中的信息可以使用 getmessage()检索,支持命中、hitdist、P、N、u、v 以及对命中对象的任意用户数据和参数查找。

int hit = trace(origin, direction, "traceset", tracesetname);
 
if (hit)
{
    // query hit distance
    float hitdist;
    getmessage("trace", "hitdist", hitdist);
 
    // query parameter on object that was hit
    string name;
    getmessage("trace", "name", name);
 
    // query user data on position where object was hit
    color Cs;
    if (getmessage("trace", "Cs", Cs))
        ...;
}

光线类型
OSL raytype()函数返回 1,如果被着色的光线是给定类型的,返回 1,
返回 0,则射线不是这种类型,或者射线类型名称不被渲染程序识别。

支持射线类型
'camera"
"shadow"
'diffuse_transmit"
'specular_transmit"
'volume_scatter"
'diffuse_reflect"
'specular_reflect"
'subsurface"

性能

OSL 和 c++着色器可以链接到一个单一的着色器节点。
然而,在将 OSL 着色器的输出连接到 c++着色器时,会有少量的开销(可能是总渲染时间的 1- 2%)。
为了使 OSL 优化器能够进行积极的全节点优化,应该使用尽可能多的 OSL 着色器节点。
评估着色器发生在第一次编译和优化时。这增加了第一个像素的时间,但可以在减少渲染时间的整体上得到回报。

调试

OSL_OPTIONS 环境变量可以用来调试着色器中的常见错误或者打印更详细的信息:

# 查找超出边界访问的数组、NaN/Infs 和未初始化变量的使用的昂贵代码
OSL_OPTIONS="range_checking=1,debug_nan=1,debug_uninit=1"
 
#为每个已编译的着色器发出消息
OSL_OPTIONS="compile_report=1"
 
# 每个线程应该处理调用数量的警告
OSL_OPTIONS="max_warnings_per_thread=100"

更多参考信息

Open Shading Language 介绍
Open Shading Language 规范
本文译自 Arnold 官方文档:OSL Shaders

Arnold(C4DtoA)

【R站译制】中文字幕 《Arnold5阿诺德渲染器终极指南》之龙材质 The Dragon Shader 视频教程

2018-7-26 20:07:57

Arnold(C4DtoA)

Arnold(C4DToA)阿诺德渲染教程(102) : 新特性 Sheen 布料着色器 (版本2.4.0\核心5.2)

2018-8-12 16:15:37

2 条回复 A文章作者 M管理员
  1. 65666666666666666666

  2. 666666

搜索