以下代码是用Renderman语言:
纹理访问
Ct = texture("example.tx", s, t);
替换为
point Psh;
float ss, tt;
Psh = transform("shader", P);
ss = s + 0.2 * snoise(Psh);
tt = t + 0.2 * snoise(Psh+(l.5,6.7,3.4));
Ct = texture("example.tx", ss, tt);
转换从左到右的图像。
根据我不了解的内容,代替访问坐标$(s,t)\ in [0,1] $,我们访问了一点微扰协调$(ss,tt)$并将其显示在$(s,t)$处,从而创建看起来有些微扰的图像。
$ snoise(x)$被定义为$(noise (x)* 2)-1 $,将噪声从$ [0,1] $映射到$ [-1,1] $,并在RenderMan文档$ noise(P)$中,其中P是一个点,返回一个值基于某些噪音(很可能是Perlin或晶格)。
(http://renderman.pixar.com/resources/current/RenderMan/noiseFunctions.html)
我不做什么明白是什么transf orm函数可以,它应该将3d点P映射到“着色器”空间中,以及如何实现。
此外,我不确定noise(x)是否返回3d点(浮点数) (会更有意义),如果我可以使用Perlin噪声的简单2d实现来达到相同的期望效果。
#1 楼
如您所料,transform()
函数将点从一个坐标空间转换为另一个坐标空间。 (分别还有vtransform()
和ntransform()
分别用于转换方向向量和法向向量。)字符串参数命名要转换为的坐标空间。有关此内容的说明如下:
在开始执行着色器时,所有点,向量,法线和矩阵变量都在“当前”坐标系中表示。哪个坐标系是“当前”的确切位置取决于实现。恰好是PRMan *的“当前”是“相机”,但您永远不要指望这种行为-完全有可能其他兼容RenderMan的渲染器(包括来自Pixar的未来渲染器)可能会使用其他空间(例如“世界”)作为“当前”空间。
接着给出一个这样的例子作为例子。大多数照明计算应在相机空间中进行,但评估噪波功能应在对象的坐标系中,因为您希望噪波在对象在世界空间中移动时保持不变。
在C#实现中,还需要将要着色的点从摄影机空间转换为对象的坐标系。也许在计算纹理坐标之前已经完成了此操作。如果不是,则需要乘以对象的转换矩阵。请记住,此变换点的唯一用途是作为Perlin噪声生成器的输入(例如种子)。它设置了噪声变化的范围:世界空间坐标。
在RSL中,
noise()
函数可以返回任何您喜欢的类型:float
,color
,point
或vector
。将其添加到另一个float
(u
或v
)时,您将在此代码中得到一个float
。实际上,添加到noise()
和s
的两个t
调用用于生成单个2D噪声矢量。在您自己的代码中,如果使用2D向量存储纹理坐标,则可以使用返回2D向量的单个噪波函数在一行代码中获得相同的效果。如果您对制作一个出色的噪声发生器感兴趣,Shadertoy拥有许多噪声着色器,它们具有Perlin噪声的不同变体,具有不同的属性(各向同性或非同质性,可配置的平滑度和带宽),值得一看灵感以及实施提示。