2009年8月20日 星期四

(16)用volume簡單實作水面下的效果

video

先扯點題外話....
看到那些八八水災的報導,對災民的處境雖不能感同身受,但也會有想要下去幫點忙的衝動。最近也在想....如果這些水量是降落在台北,想必也會是一場浩劫

◢▆▅▄▃天佑╰(〒皿〒)╯台灣▃▄▅▇◣

----------------------題外話分隔線----------------------


這次是試著實作水面下的效果。上一次做跟水底有關的效果,大概是5,6年前的事了,那時是用3ds max照著書上的範例來做,連RenderMan這個詞都沒聽過。這次要用RenderMan來做,一開始有點傷腦筋,不過把Finding Nemo開來看個幾次之後,也有了點fu,就測試出如上面影片的樣子的東西囉。這篇就是大致上介紹一下上面的影片是如何做出來的,也是我第一次用到RenderMan的volume來做東西。

首先是建置一個這樣的場景:一顆sphere中包著兩片平行的plane,然後camera從這兩片平行的plane裡看過去。如下圖

















這裡會用到3個ensemble,分別是水面的、水中的、水底的。這裡先介紹水中的(下圖左:Ensemble_volume),和水面的(下圖右:Ensemble_ocean_surf)。要注意的地方是,在Ensemble的Atmosphere上,接上smoke這個volume shader。將Ensemble_volume和Ensemble_ocean_surf分別attach在場景中的sphere和上方的plane上。Ensemble_volume的Surface接一個constant當作底色;將這兩個Ensemble接上smoke這個node的功用是~smoke這個volume shader會對這兩個Ensemble發生作用。





















上面那個smoke 如下圖。這裡小小介紹幾個欄位:
Color : 就是color ,沒辦法更白話了
Density:volume的濃度
Sampling Increment:volume的顆粒大小
至於這裡Pattern接的SLBox,本來是想要給它一點動態的變化,但是發現好像不明顯 @@,所以也就不特別介紹了~後面會在介紹Color接的SLBox是做什麼用的。





















接著是水面波紋的介紹。可以看到Ensemble_ocean_surf上分別在Surface和Displacement上接了Delux和Simple。其中displacement是接一個SLBox,如下圖





















SL code內容如下:簡單來說,就是用一層波紋較大片(f)的再疊上一層波紋叫細密(f2)的pattern,然後餵進時間變數(v1),來做出動態效果。
/******************************************************/
/* float */
float hump = 0, hump2 = 0;
float j, f = 12, f2=200, amplitude = 1;

point p= transform("object", P);

for(j = 0; j <3 ; j+=1)
 hump += abs(noise(p * f+2*v1) - 0.75) * amplitude;
 f *= 2;
 amplitude *= 0.5;
 }


for(j = 0; j <3; j+=1)
 hump2 += abs(noise(p * f+2*v1) - 0.75) * amplitude;
 f *= 2;
 amplitude *= 0.5;
 }


result = 1.75*(hump)+0.4*hump2;
/******************************************************/



接下來先介紹一個result會隨景深(Z軸)越深而漸漸變小的SLBox(type為float)。這裡將其命名為Z_d

SL code 如下:zmax和zmin分別為最大值的景深和最小值(camera前)的景深,視場景大小而定
/******************************************************/
/* float */
point pp = transform("camera",P);
point py = transform("world",P);
float zr = (zcomp(pp)-zmin) / (zmax-zmin); zr = clamp(zr,0,1);
result = zr*zr;//乘兩次的用意是...加重落差

/******************************************************/












然後來看看用在做水波全反射用的SL code。乘上v4的用意是,讓水面的眼色會隨著景深越深而越來越黑。除此之外,也將Ensemble_ocean_surf上的Delux的opacity接上前述的Z_d,好讓其透明度隨著景深降低。

/******************************************************/
normal n = normalize(N);
normal i = normalize(I);


result = (v1+v5)*v3*v4;

//視角與法向量內積的值小於某個值後,即將其改成較亮的顏色,
//來摹擬全反射。
if(abs(n.i)<0.3)
 result = v4*(v2*v3);
/******************************************************/








同理,在smoke的color上,接上的SLBox,其SL code就只是簡單的color*Z_d(顏色*景深)。

至於水底........就找張還ok的貼圖,乘上Z_d,再加點顏色的動態擾動以及一點displacement即可~


2009年8月15日 星期六

(15)實作一個結冰的動態

video

最近在ptt上面發現一個很溫暖的地方→內湖版!
不只家在內湖,從幼稚園到高中,我都是在內湖度過的,覺得這是個生活機能好,有美麗環境,居民又熱心的地方~

所以就想在這篇的影片上,表示一下我對這可愛的地方的喜愛~

內湖Good!!

--------------------------------拉哩拉咂分隔線-----------------------------------

在RenderMan上是可以讓一張texture動態的出現,以下就小小的實作一下囉!(其實基本上,使用RenderMan可以做出很多動態的效果)

這裡要做出的效果是....一個金屬要結冰,但不是整顆同時結,而是從邊邊角角的部位開始漸層的往內擴散~

◎先準備一張像雪的texture~
下面那張是來自這個材質的好站:
http://www.davegh.com/blade/davegh.htm
站長是一個國外專業的繪製材質藝術家(但好像很久沒更新了)























◎在ImageFile裡使用那張texture,並將其接到一個type為float的Spline上,調整一下curve,使其白色的部份變的較為突出。





















◎在Delux裡,接上一個type為color的SLBox(這裡是接在v4上)。在這裡的作用是....在這個SLBox裡寫的code所產生的效果(結冰),可以動態的將Diffuse、Specular、Reflection...等,慢慢蓋掉。






















◎這裡就是上述那個SLBox的內容:
v2: [expr $time/5]->此為一個tcl語法,即v2的值為所經過的時間的五倍慢
v3: 連接一個float noise node
v4: 連接上面那個Spline node





















◎此為寫在SL code裡的code,小小的解說一下:
/*********************************************************************************/
//宣告兩個type為color的變數,其中finalColor為最後呈現的顏色
color C = 1;
color finalColor=0;

//pp來物件座標的點的值
point pp = transform("object", P);

/*hump為控制結冰的範圍的值,3.2和1.4為測試出來的值,3.2為pp到物件中心點的距離的上界。當v2(時間)為0時,也就是還沒開始結冰。當時間過越久,也就是v2的值越大,hump的值就越小,3.2-hump的值就越大;也就是說...結冰的範圍就越大*/
float hump = 3.20-1.4*(noise(10*s,10*t))*v2;
float rp;

/*當物件表面的點,到物件中心的距離(length(pp)),大於hump的話,就將其做結冰的效果,否則就不作用,維持原本物件表面的樣子*/
if(length(pp)>hump)
{
//用smootstep這個function做出漸層的效果
rp = 1.4*smoothstep(hump, 3.2, length(pp));
finalColor = v4*C*v3*rp;
}
else
{
finalColor = 0;
}


result = finalColor;

/******************************************************************************/

上面的影片中,還有加displacement,也是從這個SLBox node接出去做出來的囉~

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篇邁進吧!(遠目~~~)





2009年5月9日 星期六

(10)利用SLBox出AOV(Arbitrary Output Variables)

一直很喜歡一首歌---華仔的"下次不敢",也是電影童夢奇緣的主題曲
每隔一段時間聽,都會有不同感受,在進入本篇主題前,先分享一下歌詞囉~

劉德華--下次不敢

歌手:劉德華 | 作曲:Peter Kam
填詞:劉德華 | 編曲:馮翰銘

繞了一圈 又過了一環
犯錯以後才後悔會不會太晚
就算認錯 就算你說下一次 我不敢

*失去容易 啊 回頭真難
 日子再壞也必需要走完
 啊 在生活中 每一個人
 應該有對自己最誠實的那份勇敢

 朋友啊 雖然哭泣常常讓人太難堪
 其實眼淚也有溫暖
 流過淚的你才能慢慢成長
 有傷心才會懂得有心歡*

#啊 抓緊時間 把你感情的帳單
 好好去認認真真 一一的清還
 為身邊每個人 請不要再怠慢
 讓愛火一再點燃 從今我不想
 再聽你說 下一次我不敢#

REPEAT*##


------------本篇開始 XD------------

承接上一篇....這篇是透過介紹如何利用SLBox來出matte為例,來介紹如何出AOV。

◎接續上一篇....另外再新增一個Ensemble,接一個Delux,然後在Delux裡新增一個Diffuse及SLBox,並將Duffuse的顏色調成黃色。preview可以看到如下圖~~~全白 XD。是因為SLBox的 result=(1,1,1); 將Diffuse蓋掉了。






















◎將SLBox改成 result=0;即可看到黃色color的Diffuse效果。






















◎接著....來出matte吧。matte的pass在合成時可是非常非常非常重要的!!!
在SLBox裡先新增一個type為color的變數,將其顏色調成紅色。
接著在Primvars輸入
output varying color matte_test;
接著在SL code欄位裡加入
extern color matte_test;
matte_test=v1;






















◎在上一篇的SLBox裡,一樣新增一個type為color的變數(v6),然後跟上一段一樣,
Primvars輸入
output varying color matte_test;
SL code欄位裡加入
extern color matte_test;
matte_test=v6;






















◎在maya的scene裡,為了方便觀察,建置兩顆交疊的sphere。然後將slim裡的兩個ensemble分別assign給這兩個sphere。

















◎接著在RAT的RenderMan Globals裡->Display->Channel,按下New來新增一個pass,並在channel欄位裡打上color matte_test(跟SLBox宣告的pass變數名稱一樣)。





















◎然後在Secondary裡,按New,然後在Name欄位裡將名稱改成matteTest(所render出的pass檔按名稱)





















◎按下在下方的Channels旁的Add,在選單中選擇剛剛在Display->Channel輸入的color matte_test。(這裡也再加選float a的話,matte_test這個pass裡會有alpha channel)





















◎在Primary的Display Server,將it改成tiff,也就是將檔案render成*.tiff。





















◎按下render後,即可在project下的rmanpix裡看到render的圖以及拆出來的pass。












◎用shake開啟(或其他合成軟體),即可看到拆出的pass的物件顏色,為剛剛在SLBox裡assign給matte_test的顏色。













◎如果是用RMS的話,只用在RenderMan Globals的Passes tab裡,output -> Create Output -> Custom,然後輸入color matte_test,即可出pass。






















如果想在*.sl裡,寫RSL來出aov的話,是用如下寫法:
surface ooxx(output varying color matte_test = 0;
)
{
matte_test = color(1,0,0);
}
(呃....有程式基礎的,應該看的出這段想表答什麼吧)


呼~不知不覺也累積到10篇了,但也自以為有系統的將RenderMan以及slim的network做了點初步的介紹。覺得達成一個整數後,就會失去動力....XD 疏漏之處....還希望有人指正囉~也謝謝賞識這些小小筆記的人! ^_____^
接下來....會想寫點實際的應用吧~不過還沒想好也還沒去想要怎麼有系統的寫....(劣根性阿....orz)