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

Arnold(C4DtoA) Mr.R 11个月前 (08-12) 2505次浏览 已收录 2个评论 扫描二维码

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


QQ㊀群: 240424174;QQ㊁群: 749250816;QQ㊂群: 542382043;
㊄群: 860166303;⑥群: 738134262
常见问题:1、文件解压请使用Winrar5.5版本以上解压;
2、视频播放有声音无画面,请了解下PotPlayer播放器;
R大技术站 , 版权所有,如未注明 , 均为原创,如需转载请注明来源!
喜欢 (0)
[itdiy@qq.com]
分享 (0)
发表我的评论
取消评论

表情 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. 65666666666666666666
    村名小诸葛2018-08-22 17:18 回复 Windows 7 | Chrome 63.0.3239.26
  2. Alex
    666666
    Alex2018-08-12 15:56 回复 Windows 10 | Chrome 68.0.3440.106