SlideShare une entreprise Scribd logo
1  sur  15
Télécharger pour lire hors ligne
Multi Camera Rendering (prman)
翻译:张邵杰
简述
Prman13.5 开始引入 multiple, arbitrary camera 的概念。主要是为了实现在单独
的 renderpass 中实现多个 viewpoints 的输出结果,这相比用多个 renderpass 输出
要节省大量的时间,现在对这项功能进行一个介绍。




Renderman Interface

一个新的 RI Call 用来定义相机

 RiCamera (RtToken name, ..parameterlist...)

Rib Binding:
  Camera name ...parameterlist...
例子:

 Camera "rightcamera"

这个函数可以将摄像机进行标记,用 name 进行记录。可以在解析来的 RiAttribute 或
者 RiDisplay 中调用 name 调用相应的 Camera
相机的一些其他的属性同样可以被调用:
Screen window          RiScreenWindow
Image dimension        RiFromat RiFrameAspectRation
Depth of field setting RiDepthOfField
Clipping planes        RiClipping
World to camera transformation
Camera projection      RiProjection


RiCamera 必须要在 RiWorldBegin 前声明才有效,因为对“相机描述”本身其实是一个
option。
RiCamera 同时创建了一个以 name 为标记的坐标系(类似于 RiCoordinateSystem)。
Shader 或者 RiTrasformPoints 可以通过调用 name 来使用这个坐标系。

Prman 有两个默认就定义的摄像机,一个叫“frame”是在 RiFrameBegin 时定义的,另
一个是"world"是在 RiWorldBegin 时定义的,所以用户自定义的摄像机不能是这两个名
字。
Dicing Cameras

现在 dicing camera 可以支持 RiCamera 声明的相机了。如果在 Attribute "dice"
中应用 RiCamera 声明的相机,这个相机将在 dicing 的过程中比其他 dicing camera
优先级高。


Muli-Camera Output

一旦创建了 multiple camera ,一个单独的 render pass 就可以在渲染时同时输出多
个 viewpoints.而多相机渲染那需要配合 aov(arbitray output variable)输
出.RiDisplay 增加了一条新的参数 "string camera". 这个参数可以用来接收由
RiCamera 声明的自定义相机。

当多相机渲染时,所有的几何体只被 shade 一次。这也正是 single pass 渲染比
multiple pass 渲染快的原因:即几何体 shade 的结果可以被多个相机同时使用。但是
因为 shading 只发生一次,与 view 相关的 shading 就需要特别注意(比如高光,反射
等。 )这将在下面的章节详细介绍。

下面的代码是一个定义了"right"camera 的 rib 文件,其中 right camera 比 world
camera 不同的是 ScreenWindow 参数:

##RenderMan RIB
Projection "perspective" "fov" [45]
Formate 256 256 1.0
PixelSamples 5 5
ShadingRate 0.25

Translate 0 -1 10

TransformBegin
   ScreenWindow -0.75 1.25 -1 1
   Camera "right"
TransformEnd

ScreenWindow -1.25 0.75 -1 1

Display "left.tif" "tiff" "rgba"
DisplayChannel "float a"
DisplayChannel "color Ci"

Display "+right.tif" "tiff"    "Ci,a"   "quantize"   [0   255   0   255]
 string
"string camera" ["right"]
FrameBegin 5
   TransformBegin
       LightSource "shadowspot" "mylight" "float intensity" [250]
          "point from" [0 3 -15]"point to " [0 0 0 ] "shadowname"
       "raytrace"
   TransformEnd
   WorldBegin
       AttributeBegin
          Attribute "visibility" "string transmission" ["opaque"]
          Color [1 0.25 0.25]
          Surface "plastic" "float roughness" [0.05] "color
       specularcolor" [0 1 1]
          Translate 0 -1 0
          Rotate -90 1 0 0
          Geometry "teapot"
       AttributeEnd
       AttributeBegin
          Surface "texmap" "string texname" "ratGrid.tex"
          Scale 6 6 1
          Patch "bilinear" "P" [ -1 1 4 1 1 4 1-1 -1 4 1 -1 4]
       AttributeEnd
   WorldEnd
FrameEnd




left.tif:   ScreenWindow   -1.25    right.tif:   ScreenWindow   -0.75
0.75 -1 1                           1.25 -1 1

在这个例子中,因为只有 screen window 被修改,而两个渲染相机的位置并没有区别所
以 实 际 观 看 时 并 不 会 出 现 立 体 效 果 。 在 下 面 的 例 子 中 我 们 用 Translate 来 替 换
screenwindow 偏移,两个相机只在 x 轴做偏移
##RenderMan RIB
Projection "perspective" "fov" [45]
Format 256 256 1.0
Translate 0 -1 10

TransfromBegin
   Translate -1 0 0
   Caemra "right"
TransformEnd

Translate 1 0 0
Display "left.tif" "tiff" "rgba"
DisplayChannel "float a"
DisplayChannel "color Ci"

Display "+right.tif" "tiff" "Ci,a" "quantize" [0 255 0 255]
"string camera" [ "right"]
FrameBegin 5
   TranformBegin
       LightSource "shadowspot" "mylight" "float intensity" [250]
          "point from" [0 3 -15] "point to " [0 0 0] "shadowname"
       "raytrace"
   TransformEnd
   WorldBegin
       Attribute "visitbility" "string transmission" ["opaque"]
       Color [1 0.25 0.25]
       Surface   "plastic"  "float   roughness"  [   0.05]  "color
   sepcularcolor" [0 1 1 ]
       Rotate -90 1 0 0
       Geometry "teapot"
   WorldEnd
FrameEnd
left.tif: Translate 1.0 0 0           right.tif: Translate -1.0 0 0

和上个 ScreenWindow 的版本相比,这次的立体效果更加明显:移动镜头产生的立体效果
可以从 teapot 和背景的前后对比中分辨出来。  注意两个图片中 teapot 的 diffuse 效果
也不一样。更明显的是 teapot 的高光位置也不一样了




Shading Considerations

需要再次强调的是,在进行 multiple-camera output 时,shading 过程只执行一次,
并且只与 wolrd camera 进行计算。这就会使图片产生错误。例如在上面的例子中,你会
发现右面图片的高光位置相比左面的图片要离得更远。在大部分情况下,这种
artifacts(不真实)是难以察觉的,但是这也与实际使用的 shader 与相机的相关计算的
程度有关。

为了便于我们介绍怎样修正 multiple-camera rendering 使用的 shader,我们首先
将上面例子中出现的 artifacts 效果放大,以方便我们查看,具体是将右相机与左相机成
90 度夹角:

#RenderMan RIB
Projection "perspective" "fov" [45]
Formate 256 256 1.0
PixelSample 5 5
ShadingRate 0.25
Translate 0 0 10
TransformBegin
   Rotate 45.0 0 1 0
   Camera "right"
TransformEnd
Rotate -45 0 1 0
Display "left.tif" "tiff" "rgba"
DisplayChannel "float a"
DisplayChannel "color Ci"
Display "+right.tif" "tiff" "Ci,a" "quantize" [ 0 255 0 255]
 string
"string camera" ["right"]
FrameBegin 5
   TransformBegin
       LightSource "shadowspot" "mylight" "float intensity" [250]
   "point from " [ 0 30 -15] "point to " [0 0 0 ] "shadowname"
   "raytrace"
   TransformEnd
   WorldBegin
       AttributeBegin
          Attribut "visibility" "string transmission" ["opaque"]
          Color [ 1 0.25 0.25]
          Surface "plastic" "float roughness" [0.05] "color
       specularcolor" [0 1 1 ]
          Translate 0 -1 0
          Rotate -90 1 0 0
          Geometry "teapot"
       AttributeEnd
       AttributeBegin
          Surface "texmap" "string texname" "ratGrid.tex"
          Scale 6 6 1
          Patch "bilinear" "P" [ -1 1 4 1 1 4 -1 1 4 1 -1 4]
       AttributeEnd
   WorldEnd
FrameEnd
right.tif: incorrect diffuse and
left.tif: correct
                                  specula

在这个例子中,右相机输出的图片明显是错误的。Diffuse 效果看起来就像是被切掉了,
高光也在错误的位置。下面我们看一下上面例子中使用的 shader plastic,经典的
plastic 如下:

surface
plastic( float Ks = .5,
             Kd = .5,
             Ka = 1,
             roughtnesss = .1;
          color sepcularcolor = 1)
{
   normal Nf = faceforward(normalize(N),I);
   vector V = -normalize(I);
   Oi = Os;
   Ci = Os * ( Cs * ( Ka* ambient()+ Kd * diffuse(Nf))           +
specularcolor * Ks * specular(Nf, V , roughness));
   }

=================================================================
diffuse 之 所 以 产 生 问 题 是 因 为 shader 的 计 算 与 view 相 关 , 即 faceforward
normal N. 内置的变量 I 是应该随着 camera 变化(主要是指位置方向)而变化的,但
是因为 shading 只跟 world camera(left camera)计算一次,     所以右相机输出的图片
就会有错误。下面的图示中,P 点在左相机中是正确渲染的(被遮挡状态)                     ,而在右相机中
虽然被渲染出来但是确实黑的,因为实际计算中使用了左相机的信息。因为在函数
faceforward 中使用了左相机的向量 I,在右相机的 diffuse 计算中,P 点的 diffuse
信息丢失。
首先我们可以不使用 faceforward 来避免这中情况。但是这就需要在建模的时候所有的
面的法线都是朝外的。下面是修改以后的 shader:

surface
stereoplastic ( float Ks = .5,
                    Kd = ,5,
                    Ka = 1,
                    roughtness = .1;
                 color specularcolor = 1)
   normal Nf = normalize(N)
   vector V = -nromalize(I)
   Oi = Os;
   Ci = Os * (Cs*(Ka * ambient() + Kd * diffuse(Nf))          +
   specularcolor * Ks * specular(Nf, V, roughness));
   }




left.tif: correct             right.tif: incorrect specular
   我们可以看到,虽然经过了这样的修改,右相机中高光的位置仍然是错误的。原因很简
   单因为 plastic shader 中的 spelucar 的计算方式仍然是和 view 相关的。在计
   算右相机的 specular 函数中使用的参数 I 仍然是左相机的值,所以结果是错误的。
   由此我们可以看到解决这个问题的核心是: 所有与参数 I 和 E 相关的计算都应该在
   multicamera output 的时候修正。
   因为 shading 只计算一次,为了得到"right" 相机的正确的结果,我们需要处理下
   面的问题:
   � 处理与右相机相关的 shading
   � 与相机无关的计算可以在相机间共享,以避免重复计算和资源的浪费。
   � 将右相机的结果使用新的 ouput color 单独输出。
第一个问题:
   将 右 相 机 "right" camera 的 位 置 转 换 到 current space. 我 们 可 以 使 用
RiCamera 声明 camera 时储存的坐标系统.这个坐标系统的名字与 camera 的名字是一样
的,在上面的例子中是"right",我们可以使用这个名字来转换 camera 的坐标系(use
this to compute the "right" camera position in current space by
transforming the point (0) from the "right" coordinate system to
current space):




    Eright = transform("right", "current", point(0))
   另外我们可以得 camera 的入射法线:
   Iright = P - Eright
   在与"right" camera 相关的计算中我们用 Iright 来替换 I,下面我们来进一步修
正 pliastic shader:

surface
stereoplastic( float Ks = .5,
                        Kd = .5,
                        Ka = 1,
                        roughtness = .1;
                 color specluarcolor = 1;
                 output varying color rightCi = 0;)
{
   normal Nf = normalize(N);
   vector V = -normalize(I);
   Oi = Os;
   //Compute the view independent color
   color Cvi = Cs * (Ka * ambient()+ Kd * diffuse(Nf));

   //Left camera
   Ci = Os * (Cvi + sepcularcolor * Ks * specular( Nf, V,
roughness));
//Right camera
   point Eright = transform("right", "current",point(0));
   vector Iright = P - Eright;
   vector Vright = -nromalize(Iright);
   rightCi = Os    * (Cvi + specularcolor * Ks * specular(Nf,
Vright,roughtness));
}
因为我们要区分左右 camera 的输出,我们需要一个 arbitrary output variable.
我们需要对 rib 文件左相应的调整:

#RenderMan RIB
Projection "perspectiv" "fov" [ 45 ]
Formate 256 256 1.0
PiexlSemples 5 5
ShadingRate 0.25
Translate 0 0 10
TransformBegin
   Roate 45 0 1 0
   Camera "right"
TransformEnd
Rotate -45 0 1 0
Display "left.tif" "tiff" "rgba"
DisplayChannel "float a"
                color rightCi"
DisplayChannel "color rightCi
                               rightCi,
                               rightCi,a" "quantize" [0 255 0 255]
Display "+right.tif" "tiff" "rightCi,
"string camera" ["right"]
FrameBegin 5
   TransformBegin
       LightSource "shadowspot" "mylight" "float intensity" [250]
   "point from" [0 3 -15] "point to"[0 0 0] "shadowname"
   "raytrace"
   TransformEnd
   WorldBegin
       AttributeBegin
          Attribute "visibility" "string transmission" ["opaque"]
          Color [1 0.25 0.25]
          Surface "stereoplastic" "float roughness" [0.05] "color
       specularcolor" [ 0 1 1]
          Translate 0 -1 -
          Rotate -90 1 0 0
          Geometry "teapot"
       AttributeEnd
       AttributeBegin
          Surface "texmap" "string texname" "ratGrid.tex"
Scale 6 6 1
          Patch "bilinear" "P" [ -1 1 4 1 1 4 -1 -1 4 1 -1 4]
       AttributeEnd
   WorldEnd
FrmaeEnd




left.tif: correct                   right.tif: correct




  我们可以看到 teapot 的 diffuse 和 specular 被修正,但是背景的颜色信息丢失
了,因为背景板所使用的 shader "texmap"并没有对"rightCi"做输出

   与相机相关的 shading 可以扩展到其他相关的效果中例如 raytracing.下面是一个
简单的镜面反射材质:
#================================================================
surface
mirror(float Kr = 1)
{
   color Crefl = 0, hitc = 0;
   vector reflDir = reflect(I,N);
   gather ("illuminance", P, reflDir, 0 , 1, "surface:Ci",hitc){
       Crefl +=hitc;
   }
   Ci = 0.2 * Cs * diffuse(normalize(N)) + Kr * Crefl;
   Oi = 1;
}
#===============================================================


如果我们将这个材质赋予一个球体用来反射一个 teapot,我们会得到错误的右相机的输
出:
#===============================================================
##Renderman rib
Projection "perspective" "fov" [45]
Format 256 256 1.0
PixelSamples 5 5
ShadingRate 0.25
Translate 0 0 5
TransfomBegin
   Rotate 45 0 1 0
   Camera "right"
TransformEnd
Rotate -45 0 1 0
Display "left.tif" "tiff" "rgba"
DisplayChannel "float a"
DisplayChannel "color Ci"
Display "+right.tif" "tiff" "Ci,a" "quantize" [0 255 0 255]
"string camera" ["rightcamera"]
FrameBegin 5
   TransformBegin
       LightSource "shadowspot" "mylight" "float intensity" [250]
          "point form" [0 30 -15] "point to" [ 0 0 0]
"shadowname" "ryatrace"
   TransformEnd
   WorldBegin
       AttributeBegin
          Attribute "visibility" "int camera" [0] "int diffuse"
[1] "int specular" [1]
          Color [1 0.25 0.25]
          Surface "defaultsurface"
          Translate 0 -1 -4
          Roatate -90 1 0 0
          Geometry "teapot"
       AttributeEnd
       AttributeBegin
          Surface "texmap" "string texname" "ratGrid.tex"
          Scale 6 6 1
          Patch "bilinear" "P" [ -1 1 4 -1 -1 4 1 1 4 1 -1 4]
       AttributeEnd
       AttributeBegin
          Attribute "visibility" "string transmission" ["opaque"]
          Surface "mirror"
          Color [0.25 0.25 1]
          Sphere 1 -1 1 360
AttributeEnd
   WorldEnd
FrameEnd




left.tif: correct reflection        right.tif: incorrect reflection
我们可以修正 mirror shader 以适应左右相机输出,这里需要两个 gather 语句:
#================================================================
surface
stereomirror ( float Kr = 1 ;
       output varying color rightCi = 0;)
{
   //View independent color calculations
   color Cvi = .2 * Cs * diffuse(normalize(N));

   //View dependent calculation for left camera
   color Crefl = 0, hitc = 0;
   vector reflDir = reflect ( I, N);
   gather ("illuminance", P, reflDir , 0, 1, "surface:Ci", hitc){
      Crefl += hitc;
   }
   Ci = Cvi + Kr * Crefl;
   unifrom float raydepth;
   rayinfo("depth", raydepth);
   if (raydepth ==0)
      //View dependent calculation for right camera - these only
need      // to be performed for primary rays. If we dont
      //perform the reydepth check, we ll be throwing lots of
      //wasted secondary rays.
      point Eright = transform ("right", "current", point(0));
vector Iright = P - Eright;
      Crefl = 0;
      reflDir = reflect(Iright,N);
      gather("illuminance", P, reflDir, 0 ,1, "surface:Ci",hitc){
         Crefl+= hitc;
      }
      rightCi = Cvi + Kr * Crefl;
   }
   Oi = 1;
}
#================================================================


总结:
   在 multi-camera output rendeing 时 , 为 shading 只计算一次并且只和 main
                                     因
camera 进行计算,我们可以遵从下面的规则得到正确的输出图片:
       1.首先运行所有和 view 不相关的计算,         并把结果保存到一个临时的 color 变量
   中(例如:"color Cvi")
       2.运行与 view 相关的计算例     (所有依赖于 I, E 的计算)     ;把计算结果加上 Cvi
   一并储存到 Ci 中,这就是主相机(left camera)的正确结果。
       3.对于所有其他的 camera,将其他 camera 相应的 I,E 转换到 current
   space,Iright, Eright;计算与相机相关的 shading;然后将计算结果加上 Cvi
   一并储存到 color arbitrary output variable 中(这个变量在流程中应该尽
   量 的统 一)并且确 保 RiDisplay 的输出与 color arbitrary output variable
           。
   一直
#================================================================
   注意:
      atmosphere shader 需要特别的注意,因为一般情况下,atmosphere 的所有计算都是与相
   机相关的。(关于 atmosphere shader 的立体渲染以后再研究)




efficiency of multi-camera rendering

综上所述,multi-camera rendering 要比 multiple pass rendering 快 很 多 ,
因为对于所有相机,所有物体的 shading 只计算一次。但是,内存的使用量会随着相机分
离的程度(不同的程度)而又所不同 - 因为 shading 的结果会在 camera 间公用,所以
相应的会在内存中保存时间增加。在 multi camera rending 时,除非指定特定的
dicing camera,不然的话渲染器会每个 camera 渲染时采用物体的最集合机型计算,距
离说如果一个物体只在 left camera 中出现,在计算 right camera 时,他也会被计算
进去,虽然他完全不在 right camera 的输出中出现。在这种情况下 multi-camera
rendering 和 multiple pass rendering 的速度差不多,甚至前者比后者效率会更
低一些(当然这种情况也比较少)         。
email:
zsjasper@gmail.com
欢迎大家交流

Contenu connexe

Similaire à Multi Camera Prmandoc

Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎PingLun Liao
 
How to transfer the paper to the box ?
How to transfer the paper to the box ?How to transfer the paper to the box ?
How to transfer the paper to the box ?Deloitte Consulting
 
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍dennis zhuang
 
人机对弈编程概述
人机对弈编程概述人机对弈编程概述
人机对弈编程概述勇浩 赖
 
基于HTML5的canvas实例分享
基于HTML5的canvas实例分享基于HTML5的canvas实例分享
基于HTML5的canvas实例分享xizhilang6688
 
建造与理解-用Python实现深度学习框架
建造与理解-用Python实现深度学习框架建造与理解-用Python实现深度学习框架
建造与理解-用Python实现深度学习框架ZhenChen57
 
Swift Functional Programming
Swift Functional ProgrammingSwift Functional Programming
Swift Functional Programming林藍 東
 

Similaire à Multi Camera Prmandoc (12)

浅析Flash特效开发 陈勇
浅析Flash特效开发 陈勇浅析Flash特效开发 陈勇
浅析Flash特效开发 陈勇
 
Fp
FpFp
Fp
 
20200323 - AI Intro
20200323 - AI Intro20200323 - AI Intro
20200323 - AI Intro
 
Ch5 範例
Ch5 範例Ch5 範例
Ch5 範例
 
Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎
 
How to transfer the paper to the box ?
How to transfer the paper to the box ?How to transfer the paper to the box ?
How to transfer the paper to the box ?
 
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍
 
人机对弈编程概述
人机对弈编程概述人机对弈编程概述
人机对弈编程概述
 
基于HTML5的canvas实例分享
基于HTML5的canvas实例分享基于HTML5的canvas实例分享
基于HTML5的canvas实例分享
 
建造与理解-用Python实现深度学习框架
建造与理解-用Python实现深度学习框架建造与理解-用Python实现深度学习框架
建造与理解-用Python实现深度学习框架
 
Delta (rostock)
Delta (rostock)Delta (rostock)
Delta (rostock)
 
Swift Functional Programming
Swift Functional ProgrammingSwift Functional Programming
Swift Functional Programming
 

Multi Camera Prmandoc

  • 1. Multi Camera Rendering (prman) 翻译:张邵杰 简述 Prman13.5 开始引入 multiple, arbitrary camera 的概念。主要是为了实现在单独 的 renderpass 中实现多个 viewpoints 的输出结果,这相比用多个 renderpass 输出 要节省大量的时间,现在对这项功能进行一个介绍。 Renderman Interface 一个新的 RI Call 用来定义相机 RiCamera (RtToken name, ..parameterlist...) Rib Binding: Camera name ...parameterlist... 例子: Camera "rightcamera" 这个函数可以将摄像机进行标记,用 name 进行记录。可以在解析来的 RiAttribute 或 者 RiDisplay 中调用 name 调用相应的 Camera 相机的一些其他的属性同样可以被调用: Screen window RiScreenWindow Image dimension RiFromat RiFrameAspectRation Depth of field setting RiDepthOfField Clipping planes RiClipping World to camera transformation Camera projection RiProjection RiCamera 必须要在 RiWorldBegin 前声明才有效,因为对“相机描述”本身其实是一个 option。 RiCamera 同时创建了一个以 name 为标记的坐标系(类似于 RiCoordinateSystem)。 Shader 或者 RiTrasformPoints 可以通过调用 name 来使用这个坐标系。 Prman 有两个默认就定义的摄像机,一个叫“frame”是在 RiFrameBegin 时定义的,另 一个是"world"是在 RiWorldBegin 时定义的,所以用户自定义的摄像机不能是这两个名 字。
  • 2. Dicing Cameras 现在 dicing camera 可以支持 RiCamera 声明的相机了。如果在 Attribute "dice" 中应用 RiCamera 声明的相机,这个相机将在 dicing 的过程中比其他 dicing camera 优先级高。 Muli-Camera Output 一旦创建了 multiple camera ,一个单独的 render pass 就可以在渲染时同时输出多 个 viewpoints.而多相机渲染那需要配合 aov(arbitray output variable)输 出.RiDisplay 增加了一条新的参数 "string camera". 这个参数可以用来接收由 RiCamera 声明的自定义相机。 当多相机渲染时,所有的几何体只被 shade 一次。这也正是 single pass 渲染比 multiple pass 渲染快的原因:即几何体 shade 的结果可以被多个相机同时使用。但是 因为 shading 只发生一次,与 view 相关的 shading 就需要特别注意(比如高光,反射 等。 )这将在下面的章节详细介绍。 下面的代码是一个定义了"right"camera 的 rib 文件,其中 right camera 比 world camera 不同的是 ScreenWindow 参数: ##RenderMan RIB Projection "perspective" "fov" [45] Formate 256 256 1.0 PixelSamples 5 5 ShadingRate 0.25 Translate 0 -1 10 TransformBegin ScreenWindow -0.75 1.25 -1 1 Camera "right" TransformEnd ScreenWindow -1.25 0.75 -1 1 Display "left.tif" "tiff" "rgba" DisplayChannel "float a" DisplayChannel "color Ci" Display "+right.tif" "tiff" "Ci,a" "quantize" [0 255 0 255] string "string camera" ["right"]
  • 3. FrameBegin 5 TransformBegin LightSource "shadowspot" "mylight" "float intensity" [250] "point from" [0 3 -15]"point to " [0 0 0 ] "shadowname" "raytrace" TransformEnd WorldBegin AttributeBegin Attribute "visibility" "string transmission" ["opaque"] Color [1 0.25 0.25] Surface "plastic" "float roughness" [0.05] "color specularcolor" [0 1 1] Translate 0 -1 0 Rotate -90 1 0 0 Geometry "teapot" AttributeEnd AttributeBegin Surface "texmap" "string texname" "ratGrid.tex" Scale 6 6 1 Patch "bilinear" "P" [ -1 1 4 1 1 4 1-1 -1 4 1 -1 4] AttributeEnd WorldEnd FrameEnd left.tif: ScreenWindow -1.25 right.tif: ScreenWindow -0.75 0.75 -1 1 1.25 -1 1 在这个例子中,因为只有 screen window 被修改,而两个渲染相机的位置并没有区别所 以 实 际 观 看 时 并 不 会 出 现 立 体 效 果 。 在 下 面 的 例 子 中 我 们 用 Translate 来 替 换 screenwindow 偏移,两个相机只在 x 轴做偏移
  • 4. ##RenderMan RIB Projection "perspective" "fov" [45] Format 256 256 1.0 Translate 0 -1 10 TransfromBegin Translate -1 0 0 Caemra "right" TransformEnd Translate 1 0 0 Display "left.tif" "tiff" "rgba" DisplayChannel "float a" DisplayChannel "color Ci" Display "+right.tif" "tiff" "Ci,a" "quantize" [0 255 0 255] "string camera" [ "right"] FrameBegin 5 TranformBegin LightSource "shadowspot" "mylight" "float intensity" [250] "point from" [0 3 -15] "point to " [0 0 0] "shadowname" "raytrace" TransformEnd WorldBegin Attribute "visitbility" "string transmission" ["opaque"] Color [1 0.25 0.25] Surface "plastic" "float roughness" [ 0.05] "color sepcularcolor" [0 1 1 ] Rotate -90 1 0 0 Geometry "teapot" WorldEnd FrameEnd
  • 5. left.tif: Translate 1.0 0 0 right.tif: Translate -1.0 0 0 和上个 ScreenWindow 的版本相比,这次的立体效果更加明显:移动镜头产生的立体效果 可以从 teapot 和背景的前后对比中分辨出来。 注意两个图片中 teapot 的 diffuse 效果 也不一样。更明显的是 teapot 的高光位置也不一样了 Shading Considerations 需要再次强调的是,在进行 multiple-camera output 时,shading 过程只执行一次, 并且只与 wolrd camera 进行计算。这就会使图片产生错误。例如在上面的例子中,你会 发现右面图片的高光位置相比左面的图片要离得更远。在大部分情况下,这种 artifacts(不真实)是难以察觉的,但是这也与实际使用的 shader 与相机的相关计算的 程度有关。 为了便于我们介绍怎样修正 multiple-camera rendering 使用的 shader,我们首先 将上面例子中出现的 artifacts 效果放大,以方便我们查看,具体是将右相机与左相机成 90 度夹角: #RenderMan RIB Projection "perspective" "fov" [45] Formate 256 256 1.0 PixelSample 5 5 ShadingRate 0.25 Translate 0 0 10 TransformBegin Rotate 45.0 0 1 0 Camera "right" TransformEnd Rotate -45 0 1 0
  • 6. Display "left.tif" "tiff" "rgba" DisplayChannel "float a" DisplayChannel "color Ci" Display "+right.tif" "tiff" "Ci,a" "quantize" [ 0 255 0 255] string "string camera" ["right"] FrameBegin 5 TransformBegin LightSource "shadowspot" "mylight" "float intensity" [250] "point from " [ 0 30 -15] "point to " [0 0 0 ] "shadowname" "raytrace" TransformEnd WorldBegin AttributeBegin Attribut "visibility" "string transmission" ["opaque"] Color [ 1 0.25 0.25] Surface "plastic" "float roughness" [0.05] "color specularcolor" [0 1 1 ] Translate 0 -1 0 Rotate -90 1 0 0 Geometry "teapot" AttributeEnd AttributeBegin Surface "texmap" "string texname" "ratGrid.tex" Scale 6 6 1 Patch "bilinear" "P" [ -1 1 4 1 1 4 -1 1 4 1 -1 4] AttributeEnd WorldEnd FrameEnd
  • 7. right.tif: incorrect diffuse and left.tif: correct specula 在这个例子中,右相机输出的图片明显是错误的。Diffuse 效果看起来就像是被切掉了, 高光也在错误的位置。下面我们看一下上面例子中使用的 shader plastic,经典的 plastic 如下: surface plastic( float Ks = .5, Kd = .5, Ka = 1, roughtnesss = .1; color sepcularcolor = 1) { normal Nf = faceforward(normalize(N),I); vector V = -normalize(I); Oi = Os; Ci = Os * ( Cs * ( Ka* ambient()+ Kd * diffuse(Nf)) + specularcolor * Ks * specular(Nf, V , roughness)); } ================================================================= diffuse 之 所 以 产 生 问 题 是 因 为 shader 的 计 算 与 view 相 关 , 即 faceforward normal N. 内置的变量 I 是应该随着 camera 变化(主要是指位置方向)而变化的,但 是因为 shading 只跟 world camera(left camera)计算一次, 所以右相机输出的图片 就会有错误。下面的图示中,P 点在左相机中是正确渲染的(被遮挡状态) ,而在右相机中 虽然被渲染出来但是确实黑的,因为实际计算中使用了左相机的信息。因为在函数 faceforward 中使用了左相机的向量 I,在右相机的 diffuse 计算中,P 点的 diffuse 信息丢失。
  • 8. 首先我们可以不使用 faceforward 来避免这中情况。但是这就需要在建模的时候所有的 面的法线都是朝外的。下面是修改以后的 shader: surface stereoplastic ( float Ks = .5, Kd = ,5, Ka = 1, roughtness = .1; color specularcolor = 1) normal Nf = normalize(N) vector V = -nromalize(I) Oi = Os; Ci = Os * (Cs*(Ka * ambient() + Kd * diffuse(Nf)) + specularcolor * Ks * specular(Nf, V, roughness)); } left.tif: correct right.tif: incorrect specular 我们可以看到,虽然经过了这样的修改,右相机中高光的位置仍然是错误的。原因很简 单因为 plastic shader 中的 spelucar 的计算方式仍然是和 view 相关的。在计 算右相机的 specular 函数中使用的参数 I 仍然是左相机的值,所以结果是错误的。 由此我们可以看到解决这个问题的核心是: 所有与参数 I 和 E 相关的计算都应该在 multicamera output 的时候修正。 因为 shading 只计算一次,为了得到"right" 相机的正确的结果,我们需要处理下 面的问题: � 处理与右相机相关的 shading � 与相机无关的计算可以在相机间共享,以避免重复计算和资源的浪费。 � 将右相机的结果使用新的 ouput color 单独输出。
  • 9. 第一个问题: 将 右 相 机 "right" camera 的 位 置 转 换 到 current space. 我 们 可 以 使 用 RiCamera 声明 camera 时储存的坐标系统.这个坐标系统的名字与 camera 的名字是一样 的,在上面的例子中是"right",我们可以使用这个名字来转换 camera 的坐标系(use this to compute the "right" camera position in current space by transforming the point (0) from the "right" coordinate system to current space): Eright = transform("right", "current", point(0)) 另外我们可以得 camera 的入射法线: Iright = P - Eright 在与"right" camera 相关的计算中我们用 Iright 来替换 I,下面我们来进一步修 正 pliastic shader: surface stereoplastic( float Ks = .5, Kd = .5, Ka = 1, roughtness = .1; color specluarcolor = 1; output varying color rightCi = 0;) { normal Nf = normalize(N); vector V = -normalize(I); Oi = Os; //Compute the view independent color color Cvi = Cs * (Ka * ambient()+ Kd * diffuse(Nf)); //Left camera Ci = Os * (Cvi + sepcularcolor * Ks * specular( Nf, V, roughness));
  • 10. //Right camera point Eright = transform("right", "current",point(0)); vector Iright = P - Eright; vector Vright = -nromalize(Iright); rightCi = Os * (Cvi + specularcolor * Ks * specular(Nf, Vright,roughtness)); } 因为我们要区分左右 camera 的输出,我们需要一个 arbitrary output variable. 我们需要对 rib 文件左相应的调整: #RenderMan RIB Projection "perspectiv" "fov" [ 45 ] Formate 256 256 1.0 PiexlSemples 5 5 ShadingRate 0.25 Translate 0 0 10 TransformBegin Roate 45 0 1 0 Camera "right" TransformEnd Rotate -45 0 1 0 Display "left.tif" "tiff" "rgba" DisplayChannel "float a" color rightCi" DisplayChannel "color rightCi rightCi, rightCi,a" "quantize" [0 255 0 255] Display "+right.tif" "tiff" "rightCi, "string camera" ["right"] FrameBegin 5 TransformBegin LightSource "shadowspot" "mylight" "float intensity" [250] "point from" [0 3 -15] "point to"[0 0 0] "shadowname" "raytrace" TransformEnd WorldBegin AttributeBegin Attribute "visibility" "string transmission" ["opaque"] Color [1 0.25 0.25] Surface "stereoplastic" "float roughness" [0.05] "color specularcolor" [ 0 1 1] Translate 0 -1 - Rotate -90 1 0 0 Geometry "teapot" AttributeEnd AttributeBegin Surface "texmap" "string texname" "ratGrid.tex"
  • 11. Scale 6 6 1 Patch "bilinear" "P" [ -1 1 4 1 1 4 -1 -1 4 1 -1 4] AttributeEnd WorldEnd FrmaeEnd left.tif: correct right.tif: correct 我们可以看到 teapot 的 diffuse 和 specular 被修正,但是背景的颜色信息丢失 了,因为背景板所使用的 shader "texmap"并没有对"rightCi"做输出 与相机相关的 shading 可以扩展到其他相关的效果中例如 raytracing.下面是一个 简单的镜面反射材质: #================================================================ surface mirror(float Kr = 1) { color Crefl = 0, hitc = 0; vector reflDir = reflect(I,N); gather ("illuminance", P, reflDir, 0 , 1, "surface:Ci",hitc){ Crefl +=hitc; } Ci = 0.2 * Cs * diffuse(normalize(N)) + Kr * Crefl; Oi = 1; } #=============================================================== 如果我们将这个材质赋予一个球体用来反射一个 teapot,我们会得到错误的右相机的输
  • 12. 出: #=============================================================== ##Renderman rib Projection "perspective" "fov" [45] Format 256 256 1.0 PixelSamples 5 5 ShadingRate 0.25 Translate 0 0 5 TransfomBegin Rotate 45 0 1 0 Camera "right" TransformEnd Rotate -45 0 1 0 Display "left.tif" "tiff" "rgba" DisplayChannel "float a" DisplayChannel "color Ci" Display "+right.tif" "tiff" "Ci,a" "quantize" [0 255 0 255] "string camera" ["rightcamera"] FrameBegin 5 TransformBegin LightSource "shadowspot" "mylight" "float intensity" [250] "point form" [0 30 -15] "point to" [ 0 0 0] "shadowname" "ryatrace" TransformEnd WorldBegin AttributeBegin Attribute "visibility" "int camera" [0] "int diffuse" [1] "int specular" [1] Color [1 0.25 0.25] Surface "defaultsurface" Translate 0 -1 -4 Roatate -90 1 0 0 Geometry "teapot" AttributeEnd AttributeBegin Surface "texmap" "string texname" "ratGrid.tex" Scale 6 6 1 Patch "bilinear" "P" [ -1 1 4 -1 -1 4 1 1 4 1 -1 4] AttributeEnd AttributeBegin Attribute "visibility" "string transmission" ["opaque"] Surface "mirror" Color [0.25 0.25 1] Sphere 1 -1 1 360
  • 13. AttributeEnd WorldEnd FrameEnd left.tif: correct reflection right.tif: incorrect reflection 我们可以修正 mirror shader 以适应左右相机输出,这里需要两个 gather 语句: #================================================================ surface stereomirror ( float Kr = 1 ; output varying color rightCi = 0;) { //View independent color calculations color Cvi = .2 * Cs * diffuse(normalize(N)); //View dependent calculation for left camera color Crefl = 0, hitc = 0; vector reflDir = reflect ( I, N); gather ("illuminance", P, reflDir , 0, 1, "surface:Ci", hitc){ Crefl += hitc; } Ci = Cvi + Kr * Crefl; unifrom float raydepth; rayinfo("depth", raydepth); if (raydepth ==0) //View dependent calculation for right camera - these only need // to be performed for primary rays. If we dont //perform the reydepth check, we ll be throwing lots of //wasted secondary rays. point Eright = transform ("right", "current", point(0));
  • 14. vector Iright = P - Eright; Crefl = 0; reflDir = reflect(Iright,N); gather("illuminance", P, reflDir, 0 ,1, "surface:Ci",hitc){ Crefl+= hitc; } rightCi = Cvi + Kr * Crefl; } Oi = 1; } #================================================================ 总结: 在 multi-camera output rendeing 时 , 为 shading 只计算一次并且只和 main 因 camera 进行计算,我们可以遵从下面的规则得到正确的输出图片: 1.首先运行所有和 view 不相关的计算, 并把结果保存到一个临时的 color 变量 中(例如:"color Cvi") 2.运行与 view 相关的计算例 (所有依赖于 I, E 的计算) ;把计算结果加上 Cvi 一并储存到 Ci 中,这就是主相机(left camera)的正确结果。 3.对于所有其他的 camera,将其他 camera 相应的 I,E 转换到 current space,Iright, Eright;计算与相机相关的 shading;然后将计算结果加上 Cvi 一并储存到 color arbitrary output variable 中(这个变量在流程中应该尽 量 的统 一)并且确 保 RiDisplay 的输出与 color arbitrary output variable 。 一直 #================================================================ 注意: atmosphere shader 需要特别的注意,因为一般情况下,atmosphere 的所有计算都是与相 机相关的。(关于 atmosphere shader 的立体渲染以后再研究) efficiency of multi-camera rendering 综上所述,multi-camera rendering 要比 multiple pass rendering 快 很 多 , 因为对于所有相机,所有物体的 shading 只计算一次。但是,内存的使用量会随着相机分 离的程度(不同的程度)而又所不同 - 因为 shading 的结果会在 camera 间公用,所以 相应的会在内存中保存时间增加。在 multi camera rending 时,除非指定特定的 dicing camera,不然的话渲染器会每个 camera 渲染时采用物体的最集合机型计算,距 离说如果一个物体只在 left camera 中出现,在计算 right camera 时,他也会被计算 进去,虽然他完全不在 right camera 的输出中出现。在这种情况下 multi-camera rendering 和 multiple pass rendering 的速度差不多,甚至前者比后者效率会更 低一些(当然这种情况也比较少) 。