打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Writing?Surface?Shaders
RSL
Writing Surface Shaders编写表面材质
Overview
This tutorial covers the basics of using the RenderMan Shading Language for the
purpose of writing surface shaders. Several shaders are presented that can serve
as starting points for the readers own explorations. The reader is encouraged
to use the Cutter text editor for shader writing. Details of how it should be
set up are given in the tutorial "Cutter: Shader Writing". This tutorial
develops a series of variations of a basic constant shader. Finally, issues of
diffuse lighting are addressed. The shading techniques used in this tutorial do
not require ray tracing.
A Basic Surface Shader 一个基本的表面sheder
Renderman在渲染一个物体着色前会将物体以mirco-polygons方式细分。 他的作用是每个
mirco-polygons表面材质的不透明度和颜色. 第一个设置将采用"Constant" 的表面模板.
To create a new shader document
select either "Diffuse" or "Constant"
尽管一个constant shader 不考虑灯光效果,但是, 适对于编写shader的话是一个非常好的开始.
The Constant Color Shader
surface constant_test(float Kfb = 1 ) { color surfcolor = 1; Oi = Os; Ci = Oi * Cs * surfcolor * Kfb; }
In STEP 1
将表面透明度与真实表面透明度设置为相同的值
Opacity 1 1 1 # 这将定义数值 "Os" Color 1 1 1 # this will define the value of
"Cs" Surface "constant_test" "Kfd" 1 Polygon "P" [data....]
全局变量中表面显示透明度与表面真实透明度为 Oi 与 Os
Oi = Os;
ensures that nothing fancy is being done to the opacity of an object.
In STEP 2
表面显示颜色 (Ci) 适表面颜色的值 (Cs) 用一个内部定义的颜色变量 surfcolor.
Colors are "combined" by their red, green and blue components being multiplied together. Color multiplication, filters (or tints) one color by another color. Because surfcolor is white ie. its rgb components are all equal to 1.0, it has no effect on the resulting color. In later examples, surfcolor will have a noticable effect on the final apparent color of a surface.
The multiplication by the apparent surface opacity (Oi) ensures the resulting color of each micro-polygon is pre-multiplied by its opacity. This enables the renderer to correctly composite the micro-polygons of foreground surfaces over micro-polygons of surfaces in the background.
Assigning a Color 指定一个颜色
颜色可以被定义为单独的一个灰度值或者是3个分别的不同的值,例如
color c; c = 0.8; c = color(0.3, 0.9, 0.5);
"RGB" 将是默认的颜色空间. Listing 1 将指定一个绿色给表面颜色.
Listing 1
surface constant_test1(float Kfb = 1) { color surfcolor = color(0.3, 0.9, 0.5); Oi = Os; Ci = Oi * Cs * surfcolor * Kfb; }
Figure 1 - a polygon of constant color
Adding Color Parameters(添加颜色参数)
两个颜色参数将被添加在 listing 2. mix() 函数 用三个颜色创建一个渐变效果基于
`t` 着个纹理坐标.
Listing 2
surface constant_test2(float Kfb = 1; color top = 1, lower = 0) { color surfcolor = mix(top, lower, t); Oi = Os; Ci = Oi * Cs * surfcolor * Kfb; }
The Surface statement in the rib file that referenced the shader is shown below.
Surface "constant_test2" "Kfb" 1.0 "top" [0.878 0.996 0.474] "lower" [0.580 0.690 0.988]
Figure 2 - a color ramp based on the 't' texture coordinate
颜色将可以修改为一个复数 ie.
setcomp(c, 0, 0.9);
上面例子的解释, 函数 setcomp() has been used to set the red component to 0.9. The indices 0, 1 and 2 reference the red, green and blue components respectively.
颜色阵列参数说明
颜色参数也可以被指定为一个阵列. Listing 3 同样使用 't' 纹理坐标 但这次将结合
spline() 函数.
Listing 3
surface spline_test(float Kfb = 1; color c[4] = {1,0,1,0}) { color surfcolor = spline(t,c[0],c[0],c[1],c[2],c[3],c[3]); Oi = Os; Ci = Oi * Cs * surfcolor * Kfb; }
For simplisity, 默认颜色值被指定为黑与白 ie {1,0,1,0}. However, color() 函数
可以被阵列用于赋值 ie.
color c[4] = {color(1,1,1), color(1,1,0), color(1,0,0), color(0,1,0}
The Surface statement in the rib file that referenced the shader is shown below.
Surface "spline_test" "Kfb" 1.0 "c" [0.878 0.996 0.474 0.580 0.690 0.988 0.623 0.305 0.658 0.349 0.674 0.427]
Figure 3a - a color spline based on the 't' texture coordinate
Cutter provides a simple color picker to help users interactively define the
"rgb" values of a color. To use the picker, select the three values of a color
and click the right mouse button (Windows & Linux) or Control + mouse click
(MacOSX). Cutter颜色指定的使用方法
Figure 3b
Using Cutter's popup menu to edit "rgb" values.
Adding Uniform Noise 使用均匀的噪波
例子中 mix() 函数 用于创建一个渐变 基于 't' 纹理坐标但这次  noise() 函数 将使用平缓的抖动渐变.
Listing 4
surface noise_test1(float Kfb = 1, amp = 0, freq = 4; color top = 1, lower = 0) { // Noise values range from 0 to 1. float ns =noise(s * freq, t * freq); // Offset the true value of 't'. The 'amp' parameter will allow // the artist to strengthen or weaken the visual effect. float tt = t + ns * amp; color surfcolor = mix(top, lower, tt); Oi = Os; Ci = Oi * Cs * surfcolor * Kfb; }
The Surface statement that referenced the shader is shown below.
Surface "noise_test1" "Kfb" 1.0 "amp" 0.8 "freq" 9 "top" [0.984 0.976 0.364] "lower" [0.925 0.317 0.317]
Figure 4a - a noisey color ramp
To ensure the "jittering" occurs around the mid-point of the range of values generated by the noise() function it is common practice to subtract 0.5 from the "raw" noise value. A slightly different visual effect, figure 4b, is obtained by using the code shown below.
float ns = abs(noise(s * freq, t * freq) - 0.5);
Figure 4b
Adding Non-Uniform Noise
The following shader is similiar to listing 3 except that the two input colors are noisely mixed, more or less uniformly, across a surface. The frequency of the noise in 's' and 't' can be individually controlled - hence the stretching shown in figure 5a.
Listing 5
surface noise_test2(float Kfb = 1, sfreq = 4, tfreq = 4, lo = 0.4, hi = 0.5; color hiColor = color(0.490,0.894,0.478), loColor = color(0.286,0.411,0.678)) { float ns = noise(s * sfreq, t * tfreq); float blend = smoothstep(lo, hi, ns); color surfcolor = mix(loColor, hiColor, blend); Oi = Os; Ci = Oi * Cs * surfcolor * Kfb; }
The smoothstep function ensures that mix returns either "hiColor" or "loColor" above and below the thresholds of "lo" and "hi". However, between those thresholds, smoothstep returns a value between 0.0 and 1.0. The shader blends the two colors in the transition "zone" between "lo" and "hi" and gives a fairly good anti-aliased pattern.
Figure 5a
Figure 5b - noise visualized as a height field.
3D Noise
The previous two shaders generated noise values on the basis of the 'st' texture coordinates of a surface and as a result their patterns were based on 2D noise. Using the 'st' coordinates in this way generates a pattern that is "stuck" to the surface of an object to which the shader is assigned. There are ocassions, however, when a pattern based on 3D noise is required. The shader in listing 6 uses the surface point (P) as an input to the noise function.
Listing 6
surface noise_test3(float Kfb = 1, freq = 4, lo = 0.4, hi = 0.5) { float ns = noise(P * freq); Oi = smoothstep(lo, hi, ns); Ci = Oi * Cs * Kfb; }
To illustrate what is meant by "3D noise" the shader modifies the apparent opacity of a surface - in effect acting as an irregular "cookie-cutter". To further emphasize the 3D nature of the effect, figure 6 shows a rendering of a stack of square polygons all of which share the "noise_test3" shader.
Figure 6
3D Noise & Coordinate Space
The problem with the "noise_test3" shader is that the xyz location of surface point P is measured from the origin of the camera coordinate system - it is said to be in "camera space". Careful comparison of the following three images shows there is a problem with noise that uses a point defined in camera space. Although the polygonal objects have been rotated, the "holes" created by 3D noise are in the same location relative to the picture frame. For emphasis, one of the static features is outlined in red.
Rotations of 40, 50 and 60 degrees
Th noise() function can calculate a value based on xyz values measured from the origin of any coordinate system. The transform() function is used to convert a location defined in one coordinate system into the corresponding location measured in another coordinate system. The result of using a copy of point P that has been transformed (re-measured) is that a visual effect based on 3D noise can be "parented" to any (named) coordinate system. Listing 7 demonstrates the use of the transform() function.
Listing 7
surface noise_test4(float Kfb = 1, freq = 4, lo = 0.4, hi = 0.5; string space = "shader") { point pp = transform(space, P); float ns = noise(pp * freq); float blend = smoothstep(lo, hi, ns); Oi = blend; Ci = Oi * Cs * Kfb; }
Because the 3D noise is parented to "shader" space, which in this example is effectively the same as "object" space, the irregular holes remain in fixed locations relative to the stack of polygons - figure 7a.
Figure 7a
User Defined Coordinates Systems
In addition to using any of the four predefined space names ie. "camera", "world", "object", and "shader", users can create custom coordinate systems with which they can control a shader. Cutter's Rman Tools palette enables the rib statements that define a coordinate system to be conveniently inserted into a rib file.
Figure 7b
TransformBegin Translate 0 0 0 Rotate 0 1 0 0 Rotate 0 0 1 0 Rotate 0 0 0 1 Scale 1 0.25 1 CoordinateSystem "myspace" TransformEnd TransformBegin Surface "constant_test7" "Kfb" 1.0 "freq" 1 "space" ["myspace"] ReadArchive "stack.rib" TransformEnd Using Cutter's drop-down menu to add a custom coordinate system to a rib file and accessing the custom coordinate system via the shaders "space" parameter.
Figure 7c shows the effect of scaling a user-defined coordinate system named "myspace".
Diffuse Illumination
The next set of shaders calculate the color of the diffuse illumination on a micro-polygon. The diffuse, also known as Lambert, illumination is derived from the angle between the surface normal and the (incident) ray of light striking a surface. When a micro-polygon directly "faces" the incident light it receives maximum illumination. When its normal makes an oblique angle to the incident light the illumination on the micro-polygon diminishes (drops off) in proportion to the cosine of the angle.
The diffuse() function "steps over" all the lights in a scene and returns a single color that represents the combined diffuse illumination striking a micro-polygon.
Listing 8
surface diffuse_test1(float Kd = 1, doFace = 1) { normal n = normalize(N); normal nf = n; if(doFace) nf = faceforward(n, I); Oi = Os; color diffusecolor = Kd * diffuse(nf); Ci = Oi * Cs * diffusecolor; }
The faceforward() function returns a copy of the true surface normal forced to face the incident ray. The xyz coordinates of the incident ray are stored in the global variable I. Because ray tracing is not being used the incident ray will always be the camera ray, otherwise known as the viewing vector.
The effect of not using faceforward() can be seen on the quadric sphere shown below on the left. The darkness of the interior surface of the sphere represents the diffuse illumination of the rear of the object. When an interior surface is viewed in this way we are, in effect, viewing the front of the rear surface! Unless the stereo rendering capabilities of Pixar's prman renderer are being used, it is traditional for shaders always to flip their normals using the faceforward() function. In general, the first two lines of code of a surface shader are usually these,
normal n = normalize(N); normal nf = faceforward(n, I);
Figure 8
Illumination with and without the use of faceforward(n,I)
Cartoon Shading
High contrast or cartoon-like lighting can be obtained by thresholding the diffuse illumination. In the rendering shown in figure 9 values of diffuse less than 0.5 are treated as if they were black. Values slightly higher ie. adjusted by the "blur" parameter, are considered to be white. Using the smoothstep() function ensures there is a narrow trasition zone of gray between the white and black areas.
Listing 9a
surface cartoon_test1(float Kd = 1, midpoint = 0.5, blur = 0.02) { normal n = normalize(N); normal nf = faceforward(n, I); color surfcolor = 1; color diffusecolor = Kd * diffuse(nf); float value = comp(ctransform("hsv", diffusecolor), 2); color bw = smoothstep(midpoint, midpoint + blur, value); Oi = Os; Ci = Oi * Cs * surfcolor * bw; }
Figure 9a
Illumination with and without high contrast
Figure 9b
Banding using the mod() function
As a variation of the cartoon "theme" the next shader, listing 9b, applies a repeating pattern to the threshold to produce a series of bands. For more information about the use of the mod() function and repeat patterning refer to the tutorial,RSL: Repeating Patterns.
Listing 9b
surface cartoon_test2(float Kd = 1, midpoint = 0.5, blur = 0.2, repeats = 5) { normal n = normalize(N); normal nf = faceforward(n, I); color surfcolor = 1; color diffusecolor = Kd * diffuse(nf); float value = comp(ctransform("hsv", diffusecolor), 2); value = mod(value * repeats, 1); color bw = smoothstep(midpoint, midpoint + blur, value); Oi = Os; Ci = Oi * Cs * surfcolor * bw; }
Inside/Outside Shading
Some unusual visual effects can be obtained by combining the high contrast shading of listings 9a/9b with the diffuse shading of listing 8. The next shader, listing 10, uses the high contrast values to alter the apparent opacity of a surface. In effect, the shader causes the light that strikes a surface to behave like a "cookie-cutter". However, the apparent surface color is not effected by the high contrast but instead is shaded by the color returned from the diffuse() function.
Listing 10
surface in_out_test1(float Kd = 1, midpoint = 0.5, blur = 0.2, repeats = 5) { normal n = normalize(N); normal nf = faceforward(n, I); color surfcolor = 1; color diffusecolor = Kd * diffuse(nf); float value = comp(ctransform("hsv", diffusecolor), 2); value = mod(value * repeats, 1); color bw = smoothstep(midpoint, midpoint + blur, value); Oi = bw * Os; Ci = Oi * Cs * surfcolor * diffusecolor; }
Figure 10
High contrast shading controls surface opacity while diffuse shading is used for the surface color.
Texture Mapping
When a surface is texture mapped the 'st' coordinates of its micro-polygons are used to sample a color from the corresponding 'st' location of an image. A slightly blurred (anti-aliased) color sample from the image is returned as a single color by the texture() function. The 'st' texture coordinates are equivalent to latitude and longitude - figure 11a.
RenderMan's 'st' texture space is the equivalent to the 'uv' texture coordinates of Maya and Houdini. Note, however, the origin of the 'st' space of the image is in the top-left whereas for Maya and Houdini the origin of 'uv' space is in the lower-left hand corner of an image.
Figure 11a
Texture coordinates, mapping from an image to a quadric cylinder.
With the introduction of Pixar's RenderMan Studio (RMS) the situation with regard to the relative orientation of 'st' and 'uv' space is now different compared to the way that 'st' was handled by their earlier product, RenderMan Artist Tools. Figure 11b illustrates the issue of 'st' orientation for several Maya surfaces. It appears that RMS is swapping the 's' and 't' axes!
Figure 11b
Left to Right
Rear: a quadric cylinder, a nurbs cylinder and a poly cylinder.
Front: a nurbs sphere, a poly sphere, a nurbs hemi-sphere a poly hemi-sphere.
The surfaces shown above can be accessed as pre-baked ribs via the RMan Tools menu - figure 11c. Copies of the pre-baked ribs can be opened using the Templates menu - figure 11d.
Figure 11c
Selecting nCylinder would insert the following text into a rib document.
ReadArchive "nCylinder.rib"
Figure 11d
Reading Texture Maps for Surface Coloration
The majority of RenderMan complient renderers do not directly use an image file for texture mapping but insted require the file to be converted to a texture file. Texture files contain representations of the original image at different scales. During convertion the pixel data in the texture file is filtered and this, combined with the texture files multiple images (mip maps), results in the renderer being able to perform efficient anti-aliased texturing.
Most RenderMan complient rendering systems have a utility application that converts images to textures. In the case of Pixar's system the utility is called txmake. Cutter has a simple Texture Tool, figures 11e and 11f, that enables image files to be converted and automatically saved to the users textures directory - refer to section "Setting up User Paths" at the beginning of this tutorial.
Figure 11e
Figure 11f
Rather than using the Texture Tool it is often more convenient to execute a line of text. For example, selecting the following line of text and using the keyboard short cut Alt+e, Control+e or Apple+e is the same as executing the txmake command from the command prompt, shell or terminal.
A comment at the beginning of a line is ignored when Cutter executes the text. Text may also be broken over sever lines.
Listing 11 provides the code for the texture mapping shader used to render figure 11b.
Listing 11
surface texture_test1(float Kd = 1; string texname = "") { normal n = normalize(N); normal nf = faceforward(n, I); color surfcolor = 1; if(texname != "") surfcolor = texture(texname); Oi = Os; color diffusecolor = Kd * diffuse(nf); Ci = Oi * Cs * surfcolor * diffusecolor; }
Using a Texture Map for Surface Opacity
The texture() function can return a color or a float. In the case of a float the value corresponds to the red channel of the texture map. For example, the image shown in figure 12a was used as a texture map to render the square polygon seen in figure 12b. The red shape and the white border have contributed full opacity while the green and blue shapes have been ignored. The border is opaque because white has a red channel value of 1.0.
Figure 12a
Figure 12b
Listing 12
surface texture_test2(float Kd = 1; string texname = "") { normal n = normalize(N); normal nf = faceforward(n, I); color surfcolor = 1; Oi = Os; if(texname != "") Oi = float texture(texname) * Os; color diffusecolor = Kd * diffuse(nf); Ci = Oi * Cs * surfcolor * diffusecolor; }
To ensure an opacity mapper, such as texture_test2 shown in listing 12, handles a colored image map "properly" it would be better to use the average value of the red, green and blue channels ie.
if(texname != "") { color c = texture(texname); float ave = (comp(c, 0) + comp(c, 1) + comp(c, 2))/3; Oi = ave * Os; }
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
佛语图
待用模板素材--梅竹截图
!!!ie7 ie6 使用jQuery生成视差效果的广告栏设计
div中图片和文字同一行实现垂直居中
MARIES IDEER
SDL Lib笔记 (一) 基本框架
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服