2009年8月20日 星期四

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

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

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

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


這次是試著實作水面下的效果。上一次做跟水底有關的效果,大概是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)實作一個結冰的動態



最近在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接出去做出來的囉~