2009年7月10日 星期五

(14)在RMS中使用RIBArchive

最近突然有一種體悟....就是當有一個....我認為xxoo的人,說我很ooxx時,在有那種

"你明明也xxoo,憑什麼批評我的ooxx?!"

的想法前,應該事先要對自己坦承:我就是一個ooxx的人~
還是坦然點會過的比較舒服

-------------嘰哩呱啦吱吱咂咂--------------

這篇只是小小介紹如何在RMS中使用RibArchive的功能。跟RMS的Ensemble跟RAT不同,沒有RIBBox這種東西可以接,因為RMS將其整合進Maya裡(RMS就是為了跟Maya有更好的結合才誕生的)。而且不只RibArchive,很多RenderMan的功能都要透過在Maya裡,新增以及設定一些attribute來達成。


首先...建置一個簡單的場景如下:(cube給它一個紅色的材質球)
















然後在Attribute視窗,切換到pCubeShape1的tab,按Attributes->RenderMan->Manage Attributes,會跳出下面這個視窗





















在Optional Attributes裡選"Pre Shape MEL",然後按下Add,即可發現在pCubeShape1最下面出現一個新的attribute:Pre Shape MEL。這個欄位就等同於RAT的RIBBox欄位。





















對旁邊那個locator也是相同的作法。然後在這個欄位輸入RiReadArchive "/oox/ooxx/Archive_test.rib";
也就是在RiReadArchive後面接RibArchive的路徑,render後可以看到類似下圖:紅色的teapot是由於有給他一顆材質球,所以它會去讀材質球上的資訊。另一個是只單純讀*.rib裡的geometry資訊。(註:在RMS1.0中,並不能對locator做這樣的動作,而在RMS2.0中,有將這個bug修掉)
















可以在文字編輯器裡,先打好所要輸入的code,再複製貼上,不然那欄位那麼小,直接在裏面輸入會搞到眼睛脫窗@@




這裡有順手寫了一個小小的script,先選取object,然後在maya裡執行(環境要為linux),可選取要被讀取的文字檔,並將此文字檔的內容輸入到Pre Shape MEL裡:

from pymel import *
import pymel as pm

from commands import *

import maya.mel as mel

def getFile():
 zenFile = getoutput('zenity --title="search file" --file-selection --filename=""')
 tmpPath = zenFile.split('failed')
 filePath = tmpPath[1].split('\n')

 fileCont = open(filePath[1], 'r')
 return fileCont.read()

def addArch():
 objShap = pm.ls(sl=1, dag=True, g=True)
 testName = objShap[0]
 mel.eval(' rmanAddAttr '+objShap[0]+' rman__torattr___preShapeScript "" ')

 archCont = getFile()
 print archCont
 setAttr(objShap[0]+".rman__torattr___preShapeScript" , archCont)

addArch()

2009年7月8日 星期三

(13)在RMS中使用Environment Light來做Point-Based Global Illumination

 
"為什麼我們要花這麼多時間做準備,以便在未來能做我們想做的事,卻不肯現在就去實現我們的理想?"

節錄自「生命咖啡館」

----------------------------

這篇是介紹如何使用RMS的Environment Light中的Point-Based Global Illumination功能,來做approximate occlusion(不負責翻譯:"近似occlusion".....好瞎@@)

首先....就是要先有場景,以及要用來render的camera囉!

















然後再新增一個camera,用來bake *.ptc用的,所以要保證render用的camera所看到的範圍,這個新增的camera也都要看的到。這裡是將這個camera重新命名為reference。

















打開Render Setting,將Render using切換成RenderMan(也可以直接開啟RenderMan Global)。然後切換到Features這個tab,在其底下的Global Illumination→Environment Light欄位裡,按滑鼠右鍵,選Create RenderManEnvLightShape,可以看到如下視窗。把Shadowing這個欄位切換成是occlusion。





















接著在RenderManEnvLightShape的Bake(或是Bake Shadowing)這個欄位裡,按滑鼠右鍵,選Create RenderRadiosity,即可出現如下視窗。
(註:這裡會出現三個選項:Create RenderRadiosity、Create MakeApproxGlobalDiffuse、Create MakeGlobalDiffuse3d,簡述如下:

MakeApproxGlobalDiffuse:會bake出global illumination的*.ptc,並會從這個*.ptc再產生*.bkm(brick map檔,可以想成是經過空間分割的*.ptc)

MakeGlobalDiffuse3d:會bake出有ray-traced的global illumination的*.ptc,並會從這個*.ptc再產生*.bkm

RenderRadiosity:同MakeApproxGlobalDiffuse,但不會產生*.bkm)

然後在rmanRenderRadiosityPass的camera欄位裡,按滑鼠右鍵,選擇要bake *.ptc的camera的名稱(這裡是referenceShape);在Caching Behavior選Compute,即要計算出*.ptc。





















執行render後,可以看到先render出object的color的圖,且是從reference這個camera角度看出去的樣子,也就是說,先透過bake *.ptc用的camera,來bake出object的顏色的資訊到*.ptc裡。

















接著會看到真正render出來的approximate occlusion的結果,如下:


















而且在project的renderman->untitled->data->0001底下,看到有一個*.ptc檔。














用ptviewer開啟這個*.ptc,再右鍵->Color->_radiosity,可以看到如下結果~將object的color資訊寫進去的*.ptc,且視角是reference看出去的視角。















再在rmanRenderRadiosityPass裡,將Caching Behavior切成Reuse,即可重複使用剛剛生出來的*.ptc的color資訊。再次render,就會直接render出結果,而不會先render出用來bake物件的color pass。

2009年7月6日 星期一

(12)利用python產生rib並使用*.ptc



~你為什麼在這裡?~


最近在想....該怎麼釐清"依賴"跟"無賴"的感覺。昨天看完了 "生命咖啡館(The WHY ARE YOU HERE CAFE')" 的前面三章,已經很久沒有放慢速度,一字一句的好好看本書了,特別是這種勵志類的書。"我為什麼會在這裡?", 這問題我還沒有個較明確的頭緒~想的到的是"因為我喜歡computer graphic阿"、"因為我喜歡看動畫阿"、"因為我很幸運可以把興趣當職業阿"、"因為我有想要珍惜的人阿"、"因為我宅阿"...etc,但仍是如 書上所敘述,我有一份喜歡的職業,也有一些好朋友,生活還算如意~但是內心深處,總還是有種難以言喻的感覺。昨天看完前三章後,感受到這本書有種讓我想一 口氣看完的吸引力。但還是闔上了書本,覺得這種書就是要看一部份,然後從生活中累積一些感觸後,再看一部份....慢慢的看完,儘管我真的很想一口氣看完 它 XD.


有幾句話真的有被觸動到~

有的時候,換個角度來看事情,確實會挺有幫助的

如果誠實面對自己,我會承認這些年來,我一直在質疑自己的人生,是否還有比我目前所知更深刻的一面

有時候你就是不知道自己早已準備好,可以盡情享受生命中的完美時刻

------------囉哩八嗦分隔線------------
RMS2.0新加了PRman for python,顧名思義,就是它有提供module(prman)讓使用者可以在python使用PRman的API。整個手癢想小小測一下,所以就以上一篇網誌當範例來玩一下,然後整理上來囉。以下是玩出來的python code:

import prman

ri=prman.Ri()

def ptc_RIB(ri):
 rendertarget = "ptc_RIB.rib"
 ri.Begin("ptc_RIB.rib") # set rendertarget to ri.RENDER to render pixels
 ri.Display("helloworld.exr", "it", "rgba")
 ri.DisplayChannel("color _ooxx")
 ri.Format(512,512,1)
 ri.Projection(ri.PERSPECTIVE, {ri.FOV: 60}) # standard Ri tokens are available

 ri.Rotate(180, 1,0, 0)
 ri.Rotate(0, 0,1, 0)
 ri.Translate(0, 0.1, -8)
 ri.WorldBegin()

 ri.Attribute( "cull", {"hidden": 0}) # don't cull hidden surfaces
 ri.Attribute( "cull", {"backfacing": 0}) # don't cull backfacing surfaces
 ri.Attribute( "dice", {"rasterorient": 0}) # view-independent dicing !
 ri.Attribute( "visibility", {"int diffuse": 1}) # make objects visible to rays
 ri.Attribute( "visibility", {"int specular": 1}) # make objects visible to rays

#RenderMan Interface會在RIB中的Lights(ex:spot light), Objects(ex:sphere) 和 Archives 上綁
#一個ID,但我們可以自己給他我們想要的ID名稱,來將RI給它的蓋掉。如下紅色部份的寫法
 ri.LightSource("spherelight", {ri.HANDLEID:"sl1", "point from": (-2.8, 2.0, 2.5),
 "float radius": 0.5, "float intensity": 2, "float samples": 64.0, "float falloff": 0.5})

 a="area_illum_tpt.ptc"
 b="_ooxx"

#在給shader的引數設定數值時,跟C/C++不同的是,PRman for python是要寫成如下面的型
#式(綠色部份)
 ri.Surface("bake_direct_irrad", {"string filename": a,"string displaychannels": b})
 ri.Geometry("teapot")
 ri.WorldEnd()
 ri.End()

ptc_RIB(ri)


下面是上面那段code,經由 RenderMan client library產生出來的code(RenderMan client library是把含有RenderMan Interface的code,output成rib語法的東西):

##RenderMan RIB
version 3.04
Display "helloworld.exr" "it" "rgba"
DisplayChannel "color _ooxx"
Format 512 512 1
Projection "perspective" "uniform float fov" [60]
Rotate 180 1 0 0
Rotate 0 0 1 0
Translate 0 0.1 -8
WorldBegin
Attribute "cull" "hidden" [0]
Attribute "cull" "backfacing" [0]
Attribute "dice" "rasterorient" [0]
Attribute "visibility" "int diffuse" [1]
Attribute "visibility" "int specular" [1]
LightSource "spherelight" "sl1" "float falloff" [0.5] "point from" [-2.8 2 2.5] "float samples" [64] "float radius" [0.5] "float intensity" [2]
Surface "bake_direct_irrad" "string filename" ["area_illum_tpt.ptc"] "string displaychannels" ["_ooxx"]
Geometry "teapot"
WorldEnd

render出來的圖(左)以及*.ptc(右)分別如下:

















2009年7月5日 星期日

(11)淺談point cloud

先扯點提外話吧~XD

最近朋友大推我一本書,書名是"生命咖啡館",裡面問讀者三個神祕的問題:

1.你為什麼在這裡? 2.你害怕死亡嗎? 3.你實現自我了嗎?

我想....不少人一看到這三個問題,會跟我有一樣的想法--->"就醬阿!科科"

但也就是會想知道除了"就醬阿"之外,這本書能帶給讀者怎樣的省思~
這本書我也才正要開始看~有心得再寫上來囉!

-----------正題分隔線----------









1 point = 1 micropolygon











什麼是point cloud(*.ptc)檔勒?顧名思義~裏面存的是point(可用ptviewer開來看看),每個 point 可以有任意的資料,雖然 point 會讓人覺得是一個, 但其實在 *.ptc 裏頭,每一個 point 其實是由 (position, normal, area) 三個組成,亦即它是一個有面積的圓盤(disk),所以一個最基本的 .ptc 檔,裏頭的每一個 point 至少會有這三個資料,其餘的就看使用的人怎麼去運用(ex, occlusion, irradiance, …)。
(以上是節錄Drake對point cloud檔的介紹~)

接下來開始介紹如何在RenderMan中使用這種檔案,用的範例也是RMS的document所提供的。
在RenderMan中,要產生*.ptc是透過使用一個叫作bake3d()的function,在document中的敘述簡述如下:
bake3d(filename, displaychannels, P, N, "radius", r, "coordsystem", cs,
"interpolate", 0,
"direct", d, "onebounce", ob, "occlusion", occ, ... );
綠色標記的部份,是要另外寫入*.ptc的channel,也就是除了(position, normal, area)以外,要寫入*.ptc的資訊。而在RIB檔中,也要有一個跟其名稱對應的DisplayChannel。例如:在bake3d中,有一個"_ooxx", ooxx,其中ooxx為一個type為color的變數,則在RIB中,也要這樣宣告
DisplayChannel "color _ooxx"

才可在*.ptc中寫入一個名為 '_ooxx' 的channel,並將變數color ooxx所存的資訊寫入 '_ooxx'。

至於interpolate這個flag的作用是....先想像有一個四方形的盒子放在桌面上,盒子會有一面跟桌面平貼接觸。當interpolate為0時,除了盒子跟桌子接觸的面的資訊會被寫入*.ptc裡,而桌子跟盒子接觸的面的資訊也會被寫入*.ptc裡;而其值為1時,只會將桌子跟盒子接觸的面的資訊寫入*.ptc裡。所以其值為1是比較省時省空間的。

接下來,來play一下document中的例子吧!

首先,先分別新增一個*.sl和*.rib,這裡檔名分別是ptc_gen.sl與ptc_RIB.rib。先做個小小的實驗~用文字編輯器打開ptc_gen.sl,輸入以下RSL code:
surface
bake_direct_irrad(string filename = "", displaychannels = "";
float interpolate = 1)
{
color irrad;
normal Nn = normalize(N);

/* Compute direct illumination (ambient and diffuse) */
//irrad = ambient() + diffuse(Nn);
irrad = 1;
/* Store in point cloud file */
bake3d(filename, displaychannels, P, Nn, "interpolate", interpolate,
"_ooxx", irrad);

Ci = irrad * Cs * Os;
Oi = Os;
}
注意一下紅色部份:先將 " irrad = ambient() + diffuse() ; " mark起來,另外將irrad的值設為1。

然後打開 ptc_RIB.rib ,輸入:
FrameBegin 0

Format 400 300 1
ShadingInterpolation "smooth"
PixelSamples 4 4

Display "bake_arealight" "it" "rgba"
Quantize "rgba" 255 0 255 0.5
   #宣告對應bake3d中的 '_ooxx' channel
DisplayChannel "color _ooxx"

Projection "perspective" "fov" 25
Translate 0 -0.5 8
Rotate -40 1 0 0
Rotate 20 0 1 0

Attribute "trace" "bias" 0.0001

WorldBegin

Attribute "cull" "hidden" 0 # don't cull hidden surfaces
Attribute "cull" "backfacing" 0 # don't cull backfacing surfaces
Attribute "dice" "rasterorient" 0 # view-independent dicing !
Attribute "visibility" "int diffuse" 1 # make objects visible to rays
Attribute "visibility" "int specular" 1 # make objects visible to rays

LightSource "spherelight" 1 "from" [-2.8 2 0.5] "radius" 0.2
"intensity" 2 "samples" 64 "falloff" 1

Sides 1 # to avoid flipping normals in "spherelight"

# Ground plane
AttributeBegin
#產生名稱為area_illum_plane.ptc的point cloud檔
Surface "bake_direct_irrad" "filename" "area_illum_plane.ptc"
      #將shader中,變數irrad的資訊寫入此*.ptc中
"displaychannels" "_ooxx"
Scale 3 3 3
Polygon "P" [ -1 0 1 1 0 1 1 0 -1 -1 0 -1 ]
AttributeEnd

Attribute "visibility" "int transmission" 1 # the cyl. casts shadow
Attribute "shade" "transmissionhitmode" "primitive"

# Cylinder with cap
AttributeBegin
Surface "bake_direct_irrad" "filename" "area_illum_cyl.ptc"
"displaychannels" "_ooxx"
Translate -1 0 0.5
Rotate -90 1 0 0
Cylinder 0.5 0 1 360
Disk 1 0.5 360
AttributeEnd

WorldEnd
FrameEnd
分別用shaderprman去編譯ptc_gen.sl和ptc_RIB.rib後,除了可以看到render出來的obj是一片白,還可以在目錄下發現多了兩個ptc檔:
area_illum_plane.ptc
area_illum_cyl.ptc
用Pixar RenderMan提供的ptviewer開啟area_illum_cyl.ptc,可以看到如下圖~每個point都是全白的cylinder(因為irrad=1),也就是說~有把irrad是白色的資訊寫入此ptc中:


















按右鍵->color可以看到 '_ooxx' 這個channel。選擇Point Radii,可以看到其point的分佈狀況:


















將ptc_gen.sl中的 irrad改回 ' irrad = ambient() + diffuse() ;' 再render則可得到下圖:




















其area_illum_cyl.ptc如下圖。用滑鼠左鍵反轉一下,可以看到此cylinder底部是空的,是因為interpolate為1的緣故。




















而area_illum_plane.ptc如下圖。右鍵->color->white,可以看到中間沒有空洞,整片白的plane。由上一個和此*.ptc可以看到,shadow的資訊被寫入*.ptc裡。



















將ptc_gen.sl內容改成:
surface
bake_illumsurfcolor(string filename = "", displaychannels = "", texturename = "";
float interpolate = 1)
{
color irrad, tex = 1, illumsurfcolor;
normal Nn = normalize(N);

/* Compute direct illumination (ambient and diffuse) */
irrad = ambient() + diffuse(Nn);

/* Multiply by surface color */
if (texturename != "")
tex = texture(texturename);
illumsurfcolor = irrad * tex * Cs;

/* Store in point cloud file */
bake3d(filename, displaychannels, P, Nn, "interpolate", interpolate,
"_illumsurfcolor", illumsurfcolor);

Ci = illumsurfcolor * Os;
Oi = Os;
}
再將ptc_RIB.rib內容改成:
FrameBegin 0

Format 400 300 1
ShadingInterpolation "smooth"
PixelSamples 4 4

Display "bake_illumsurf" "it" "rgba"
Quantize "rgba" 255 0 255 0.5
DisplayChannel "color _illumsurfcolor"

Projection "perspective" "fov" 25
Translate 0 -0.5 8
Rotate -40 1 0 0
Rotate 20 0 1 0

Attribute "trace" "bias" 0.0001

WorldBegin

Attribute "cull" "hidden" 0 # don't cull hidden surfaces
Attribute "cull" "backfacing" 0 # don't cull backfacing surfaces
Attribute "dice" "rasterorient" 0 # view-independent dicing !
Attribute "visibility" "int diffuse" 1 # make objects visible to rays
Attribute "visibility" "int specular" 1 # make objects visible to rays

LightSource "spherelight" 1 "from" [-2.8 2 0.5] "radius" 0.2
"intensity" 2 "samples" 64 "falloff" 1

Sides 1 # to avoid flipping normals in "spherelight"

# Ground plane
AttributeBegin
Surface "bake_illumsurfcolor" "filename" "illumsurf_plane.ptc"
"displaychannels" "_illumsurfcolor" "texturename" "ooxx.tex"
Scale 3 3 3
Polygon "P" [ -1 0 1 1 0 1 1 0 -1 -1 0 -1 ]
"s" [1 1 0 0]
"t" [0 1 1 0]
AttributeEnd

Attribute "visibility" "int transmission" 1 # the cyl. casts shadow
Attribute "shade" "transmissionhitmode" "primitive"

# Cylinder with cap
AttributeBegin
Surface "bake_illumsurfcolor" "filename" "illumsurf_cyl.ptc"
"displaychannels" "_illumsurfcolor" "texturename" "ooxx.tex"
Translate -1 0 0.5
Rotate -90 1 0 0
Cylinder 0.5 1 0 -360 # reversed to get texture right side up
Disk 1 0.5 360
AttributeEnd

WorldEnd
FrameEnd
其中 'ooxx.tex' 是利用txmake 這個command(txmake ooxx.tif ooxx.tex),將一個ooxx.tif轉成ooxx.tex,也就是RenderMan的材質格式。

render後可得到下圖:




















產生的*.ptc,分別為下面兩張圖(右鍵->Focus View可將視角focus在object上)。可以看到texture資訊也被寫入point裡。

































最後介紹如何讀取已經bake好的ptc。
可以將已經bake好的ptc,當作是一種3-d的texture,可以用 texture3d() 來讀取。由上一個例子,將ptc_gen改成:

surface
read_illumsurfcolor(uniform string filename = "")
{
color illumsurfcolor = 0;
normal Nn = normalize(N);
float ok;
     
     //利用texture3d(),將 _illumsurfcolor 的資訊寫入illumsurfcolor
ok = texture3d(filename, P, Nn, "_illumsurfcolor", illumsurfcolor);

Ci = illumsurfcolor * Os;
Oi = Os;
}
再將ptc_RIB.rib改成:(注意~這rib跟之前不同,沒有light shader,也不用指定*.tex,因為已經通通被寫入*.ptc裡,直接讀取*.ptc裡的資訊即可)
FrameBegin 0

Format 400 300 1
ShadingInterpolation "smooth"
PixelSamples 4 4

Display "read_illumsurf" "it" "rgba"
Quantize "rgba" 255 0 255 0.5

Projection "perspective" "fov" 25
Translate 0 -0.5 8
Rotate -40 1 0 0
Rotate 20 0 1 0

WorldBegin

# Ground plane
AttributeBegin
Surface "read_illumsurfcolor" "filename" "illumsurf_plane.ptc"
Scale 3 3 3
Polygon "P" [ -1 0 1 1 0 1 1 0 -1 -1 0 -1 ]
AttributeEnd

# Cylinder with cap
AttributeBegin
Surface "read_illumsurfcolor" "filename" "illumsurf_cyl.ptc"
Translate -1 0 0.5
Rotate -90 1 0 0
Cylinder 0.5 0 1 360
Disk 1 0.5 360
AttributeEnd

WorldEnd
FrameEnd

render後即可得到如前一例子的結果。

話說....這網誌已經閒置一個多月了,一來是不知道該寫些什麼,因為之前都在用RAT,而Pixar現在是推RMS;二來是前陣子事情也頗多的說~想想....還是寫些比較技術性的東西會覺得比較有趣~XD

朝下一個10篇邁進吧!(遠目~~~)