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即可~


2 則留言: