2009年4月30日 星期四

(8)簡單介紹RenderMan Shading Language

也該寫點有關RenderMan Shading Language的東西了,不過這篇只是單純介紹如何操作*.sl。如同C++的檔案副檔名為cpp,RenderMan Shading Language的副檔名為sl。以artist的觀點,這篇可以說跟slim沒很大的關係,跳過這篇,一樣可以在slim上拉shader;以 programmer的觀點,會覺得關係可大了,畢竟slim裡的node,其核心都是SL code。所以如果要玩SL code的人,好歹也要修過Data Structure或是Numerical Analysis等較進階的程式課程。(深深覺得....除非是天資過人,萬中選一的高手,不然如果光是K完一本初階的C語言之類的,就出去跟人家說會寫程式,還蠻牽強的 XD)SL code語法跟C語言很像,也是結構式語言,一樣用//和/*....*/來做註解,只是宣告的資料型態不盡相同,例如SL有float、color、point、normal等,但是沒有int和double。

這篇是對surface shader和displacement shader各舉一個例子來介紹。參考資料為:
㊣http://www.fundza.com/
㊣The RenderMan Companion (Steve Upstill)
使用工具為prman

◎可以先新增一個空的資料夾,把會用到的檔案集中到此處。這裡是在G槽下新增一個名為ooxx的folder。

















◎先小小介紹一下surface shader和displacement shader較常用到的內建變數(較詳細的介紹,還是要看這個比較好:http://www.fundza.com/rman_shaders/surface/sl_surface1.html 以及 http://www.fundza.com/rman_shaders/displacement/ds_displacement1.html)

###################################################################
Ciobject表面顯現的顏色 (output)
Oiobject表面顯現的透明度 (output)
Csobject原始的顏色 (input)
Osobject原始的透明度 (input)
Nobject表面的法向量(三維向量)
s, t:object表面的貼圖座標(可以想成國中學的(x,y)直角座標),其範圍皆為0到1,也就是說(0.5, 0.5)會落在座標的中間
P
object表面的point的值(三維向量)
###################################################################

◎開啟一個空的記事本,key入以下內容:
surface /*宣告surface shader function,所宣告的function名稱為noise_test1*/
noise_test1(float Kfb = 1,
amp = 0.8, /* amplitude of the noise */
freq = 9; /* frequency of the noise */
color top = (1,0,0) /* 方片上方的顏色 */,
lower = (1,1,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;

/* 將上方的顏色和下方的顏色,沿著tt做混合(mix),並將其assign給一個type為color的變數surfcolor */
color surfcolor = mix(top, lower, tt);
Oi = Os;

/* object表現的顏色=透明度*object底色*混合後的顏色*Kfb (此處的Kfb是控制object顯示出來的亮度)*/
Ci = Oi * Cs * surfcolor * Kfb;
}

然後另存為SurfaceShaderTest.sl。開啟命令提示字元,在G:\ooxx底下輸入shader SurfaceShaderTest.sl (要記得設好prman的環境變數),按下Enter後可以看到這樣的訊息:noise_test1: compiled,表示已經在ooxx這個資料夾底下產生了一個noise_test1.slo檔。用prman的shader來編譯*.sl所產生的檔案,其副檔名為slo,也就是在使用在rib中的shader名稱,同時也是選告surface shader時的function名稱。







◎然後開啟一個空的記事本,貼上以下內容:
Hider "hidden"
LightSource "distantlight" 1
Projection "perspective"
Translate 0 0 1.5
Rotate 40 -1 1 0
FrameBegin 2
Display "test2.jpg" "framebuffer" "rgba"
WorldBegin
Rotate 10 0 0 1
Surface "G:/ooxx/noise_test1"
Polygon "P" [0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 ]
Rotate 90 0 1 0
Polygon "P" [0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 ]
Rotate 90 0 1 0
Polygon "P" [0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 ]
Rotate 90 0 1 0
Polygon "P" [0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 ]
Rotate 90 1 0 0
Polygon "P" [0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 ]
Rotate 180 1 0 0
Polygon "P" [0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 ]
WorldEnd
FrameEnd

紅色註記的部份,即為剛剛產生的*.slo的完整路徑。將其另存為Simple_Cube.rib(這個*.rib只是產生一個cube而已)。如果將Surface "G:/ooxx/noise_test1" 改成
Surface "G:/ooxx/noise_test1"
"top" [0.878 0.996 0.474] "lower" [0.580 0.690 0.988]
即可將top, lower原本的值,改成中括號內的數值,依此類推。slim的node上的參數也是由此而來。注意~只有宣告為引數的變數可以這樣使用~

◎然後在命令提示字元裡,key入prman Simple_Cube.rib。







即可看到下圖

















◎再開啟一個空的記事本,key入:
displacement ripple1/*宣告一個名稱為ripple1的displacement shader*/
(float Km = 0.004,
numripples = 8,
a = 0.3,
b = 0.25)
{
float sdist = s - a,
tdist = t - b,
//計算object表面每一點(s,t)到(a,b)的距離(dist)
dist = sqrt(sdist * sdist + tdist * tdist),

//將dist餵給sin,以在object表面做sin波。
hump = sin(dist * 2 * PI * numripples);

//將N做normalize,然後assign給一個type為normal(三維向量)的變數n。
normal n = normalize(N);

//將object表面的點,延n做位移(displacement)
P = P - n * hump * Km;
//P位移過後,再重新計算每個P的法向量,然後assign給N
N = calculatenormal(P);
}


將其另存為DisplacementShaderTest.sl。一樣用shader這個command來compile這個*.sl,可以得到一個ripple1.slo。








◎將上面那個*.rib,用紅色註記的部份,換成Displacement "G:/ooxx/ripple1",然後用prman去render即可看到如下結果

2009年4月27日 星期一

(7)spot light shader的簡單應用

最近有朋友跟我說我這RenderMan的心得整理的還不錯,聽到後還挺開心的說~XD,真是感謝大家的鼓勵!也有非程式背景的朋友說,希望我在這上面來點程式的教學,嗯....想了一想,一來是自己才疏學淺又懶...orz,二來是覺得非程式背景的人,與其對程式一知半解,想寫的時候不知道如何下手,那把每個node的特性搞清楚還來的較簡單又有意義~例如像上一篇的noise,有些人只會認為是一種亂數的擾動,卻不知道它其實不是亂數,而且是一種uniform continuous的函數(請參考這個很棒的網站-> http://www.fundza.com/rman_shaders/noise/index.html)。也有人問說....那數學需不需要很強,坦白說,還真不知道該怎麼回答這問題,儘管我是唸應用數學出身的,只能說基本的舉陣計算,向量分析要懂一點 @@

推薦一本個人覺得很棒的向量分析,中文的哦!

http://www.tsanghai.com.tw/product_info.php?products_id=653&osCsid=35f70993779eee363847f195d32c8018

個人覺得寫的簡單清晰,對基本的微分幾何也有詳細的介紹,又不像一堆專業知識的書籍,厚到可以拿來砸人~XD,而且預備知識只需要基本的微分和積分就好了。

--------------------------以上是本篇的廢話,進入正題 XD---------------------------

一般在lighting的時候,大部份都是用spot light比較多,一來是好控制,二來是相較point light而言,計算量少很多(記得一個point light的計算量是spot light的6倍)。不過也是要視實際遇到的情形來做考量。

◎先建置一個簡單的場景,記得要打一個maya的spot light。


















◎在graph layout裡,Lights-> Spot,來新增一個spot light的node。




















◎給sphere一個紅色的diffuse,然後render可以看到如下圖。有光線,但是沒有shadow。


















◎點下spot light裡的shadow旁的小方塊,如圖示,給它一個ShadowMap來產生陰影。一般lighting在做shadow的時候,只需要用到ShadowMap這個node就夠了。


















◎render之後,即可看到陰影。


















◎將maya的spot light的屬性的Penumbra Angle調成10。


















◎可得如下結果。對照前一張render的結果,可以看到光線有擴散出去的感覺~像現在這個spot light的Cone Angle是40,Penumbra Angle是10的話,那它擴散的範圍就是spot light照到的範圍的10/40=1/4。



















◎ShadowMap裡較常用到的attribute有:Map Resolution、Samples、Blur、Bias。























◎這是Map Resolution為512時的圖



















◎這是Map Resolution為1024時的圖,相較於上一張圖,shadow的alias有少很多,也就是resolution的值越大,alias越小。



















◎將Blur調成0.02

















◎可以看到如下圖,shadow有了blur的效果(這裡調成0.02這個值,其實有點太大)



















◎將Samples的值調成64的話,可以看到如下圖的結果,相較於上圖,一粒一粒的感覺明顯改善。



















◎將Bias調成0.002(在小場景,這個參數只要調一點點,就會有很大的影響)




















◎可以看到如下圖。有時候在一些場景裡做lighting時,會發生shadow跟物件沒接在一起的詭異情形,Bias就可以對shadow做一些位移個的效果,來將shadow和object接在一起。當然也可以用來做出一些特別的效果。



















◎上圖中可以看到polygon sphere看起來有點菱菱角角,除了用maya的smooth功能外,這裡順便介紹RAT的subdivision的使用(注意..這跟maya的smooth是用不一樣的演算法):RenerMan->Pixar Subdivs-> Mesh as Subdivs。



















◎再render後即可看到一粒平滑的sphere。

















ps:這裡要感謝一位好同事好朋友~Vence,很多lighting的細節與概念等,都是向他討教來的~ XD

2009年4月24日 星期五

(6)一些 float pattern的介紹

話說前幾天去一個學長那邊play,算是第一次比較有玩到RenderMan Studio(RMS),跟RendereMan Artist Tools(RAT)在本質上有很大的不同,光是globals的介面就搞得有點暈頭轉向...orz...還在慢慢研究中~XD。不過,在slim拉RenderMan Network的概念倒是沒差多少,等比較有心得再和RAT做個比較整理上來囉~

這篇主要是介紹一點pattern的應用。其實pattern就是一種programming texture,也可以搭配其他手繪的texture做出一些有趣的效果~以下就簡單介紹一下float type的noise、facingforward、spline以及spline如何跟texture做搭配。

◎在graph layout上,Floats->Patterns->noise,來新增一個float type的noise node。noise可以應用在簡單的處理一些不是那麼平滑的反射,像人臉的反射、桌面的反射...等,都帶了那麼點不平順,就可以用noise來處理~





















◎將frequency調到8,可得如下圖。frequency也就是它擾動頻率的程度,值越大,其detail越細。





















◎將其接到第1篇小小筆記的Diffuse的intensity上,由於intensity就是亮度,這個動作就是在Diffuse的intensity上做noise,所以可以看到在Diffuse上產生了擾動的效果。





















◎這是FacingForward。顧名思義,就是計算物件法向量與視線的內積,值越大的部位越亮。可以應用在一些圓弧形的東西上,來做一些類似拋光的效果。





















◎將其接到Diffuse的intensity上,可得如下的效果。





















◎將FacingForward的invert打開,也就是將其值倒反過來,可得下圖。





















◎Diffuse就變成這樣。





















◎這是Spline node的預設值。





















◎將其Spline的curve隨便拉一下,可以看到類似下圖的效果。





















◎再將其接到Diffuse的intensity上,可以得到如下圖。





















◎最後,來小小玩一下Spline和texture的結合吧。先將Diffuse的intensity換成internal value。










◎新增一個color 的ImageFile,沿用之前的青蛙圖,將ImageFile接到spline的Pattern上。





















◎預設可得下圖:一隻灰階的青蛙~





















◎調整一下spline curve看看。可以看到類似下圖~有一些顏色被濾掉(壓掉)了。這也是spline好用的地方,可以用來濾掉等於某些值的顏色。






















以上當然是處理一些比較簡單的情況,但一些比較複雜的情形,還是免不了要在SLBox裡寫點SL code囉,以後再介紹~ XD

2009年4月23日 星期四

Light shader example

這是自己摸索Help裡面的一些教學,所做出來的東西,
如果有什麼疏漏的地方,請多指教~

Step1:
建置如下圖之場景
















然後從Houdini的Help裡,找到如下圖的code





















Step2:
利用上圖的上面的code,建立一個surface shader

















並指定給其中一個sphere,算圖後可得如下圖之結果





















Step3:
開啟New Operator Type,將Network Type設為 Light Shader Operator





















然後輸入step1下面的code
















Step4:
在Network視窗,切換到shop,按下tab鍵→選擇剛剛建立的Light shader名稱





















將此node拖曳到場景中的pointlight上,會跳出如下視窗,
選擇第一個"Create spare paramter on pointlight1 for Light Shader SHOP"


















Step5:
按下New Operator Type的Apply鍵→算圖,即可得如下結果

displacement shader example

這是用下列連結中的其中一個範例
stud.fh-wedel.de/~wk/Handouts/houdini_zip/vex.pdf


Step1:
一樣,設置一個簡單的場景
















Step2:
指定一個材質給sphere














然後開啟New Operator Type,在Network Type選擇displacement shader operator




















輸入如圖的Code,按下Test Compile



















Step3:
在Network視窗,切換到shop模式,進入basic surface,然後在suboutput1 node2的 input上,連接剛剛在New Operator Type上輸入的名稱
如圖

















Step4:
算圖,即可得出如下圖之結果