《拜見羅賓遜一家》又叫做《未來小子》,原名叫做《ADayWithWilburRobinson》。它取材于WilliamJoyce頗富奇想的繪本故事童書,情節十分簡單,講述一個男孩Lewis跟著他來自未來的朋友Wilbur拜訪他各具特色的家人,讓Lewis度過奇妙的一天。在《拜見羅賓遜一家》中,Lewis的眼球渲染是一個技術難點,而迪斯尼很好地處理了這個問題。
面臨挑戰《四眼天雞》(Chicken Little)的初始眼球懸掛在動畫師懸掛中完成了所有的工作,包括處理所有的縮放、旋轉,甚至可以做出虹膜和瞳孔區域的縮放,還有眼球范圍的保持,這些都應用到了由一組復雜的變形器提供的單表面上。我們繪制了最終表面,一切的效果都剛剛好。動畫師的所見即所得。 問題:這個懸掛的復雜程度要乘以兩倍,因為有兩個眼球。 懸掛部門可以制作一個更加輕量的懸掛,其中眼球的表面是一個簡單的構造幾何實體(constructive solid geometry, CSG),它由一個球體和兩個從球心向外指向的圓柱之間的布爾運算生成。不過我們不能輕易的繪制或者渲染那些表面。解決方法:著色器會將動畫師看到的內容重新生成。用于生成虹膜和瞳孔布爾形的兩個圓柱能夠非常好地幫助著色器中的投影橢圓。
我們認為我們需要以下的控制:?一個定義眼球中心以及所有旋轉信息的坐標系。 ?虹膜大小、高度和寬度 ?瞳孔大小、高度和寬度我們隨后在眼球周圍添加了旋轉。眼球的懸掛控制了坐標系(每個眼球一個)的生成,并將它們連接到動畫師的控制,以及追蹤上面提到的其他設置。它們會作為補充屬性來處理,然后直接輸出到鏡頭完成的RIB中,它們會在這個階段覆蓋著色器。使用標準的RAT格式來指定基本變量(請在你的Renderman文檔中查看Application Note #22),Maya的屬性如下:
我們在視覺發展部門有這些默認數值,也有它們在坐標系上的默認位置,不過當場景制作到了鏡頭完成的階段時,這些都會被動畫師的最終設置替換掉。著色器實際上,我們的虹膜和瞳孔都被定義成單位圓上的投影橢圓。著色器知道每個區域的大小,并將這些信息投射會單材質貼圖上,這些貼圖已經對眼球、瞳孔和鞏膜范圍硬編碼成s和t材質貼圖調用。首先我們會定義表面上的一個點與眼球中心的相對位置,這剛好就是我們坐標軸上的z軸。 // transform sample point into the center pivot coord system varying point Pt = transform("current", coordSysName, Pbase); // unit vector from origin pointing toward current sample varying vector vecP = normalize(vector(Pt)); // angle between current sample and z axisvarying float angleP = acos(comp(vecP,2));
現在我們知道該點與眼球中心的相對位置,這樣我們只需將它代入到我們的材質貼圖中。一般來說,我們只需對角度進行測量,并利用測量結果,但是由于我們需要有能力對眼球的某些區域(瞳孔和虹膜)以任意數值進行縮放,所以我們的過程變得非常復雜??紤]到兩個區域的的大小,并假設瞳孔的大小總是比虹膜要小,我們現在就可以預測該點會出現在哪個區域,并將該信息映射回材質貼圖。首先,我們要定義這些區域: // get regions edge angles in the direction of the current sample varying float pupilAngle = ellipseAngle( Pt, pupilX, pupilY, rotation); varying float irisAngle = ellipseAngle( Pt, irisX, irisY, rotation); 上面的函數(在附錄中有提供)將表示瞳孔、虹膜和鞏膜之間界限的角度返回?,F在我們簡單地將該點映射到瞳孔、虹膜或者鞏膜上的表面。然后該取值會經過標準化,并重新映射到單材質貼圖中。材質貼圖區域會被硬編碼到著色器中,而且所有繪制的貼圖必須符合這些設置。
瞳孔、虹膜和鞏膜區域利用Z軸(眼球中心)與該點之間的角度,我們現在可以定義該點會在哪里映射到我們的眼球材質貼圖中,該距離為t: // get v texture coord (same for all regions) varying float angleV = atan(comp(Pt,0),comp(Pt,1)); map_tt = (angleV + PI)/(2*PI); // normalize angle 現在我們已經有了s和t的值,材質貼圖參考能夠正常處理。
簡單材質貼圖值得一提的是,這種投影技術不會限制于完美球形的眼球。雖然初始投影是在一個單位球體上完成的,但是我們可以將眼球區域的結果投影到任意的最終形狀上。球體會有最好的效果,而且形狀越接近球體的話,投影就會出現越少的變形。
不同的眼球形狀執行細節每只眼球都由兩個球體來表示,眼球的主體含有上文提到的瞳孔、虹膜以及鞏膜區域。另外一個稍微大一點的球體是用來表示角膜。它渲染出來的效果是完全透明的,只有一些反射以及高光部分。我們在兩個球體上都使用了位移。對于眼球本身,我們將虹膜和瞳孔向下移動,做出更加接近真實眼睛的反射效果。我們發現如果跳過這一步的話,眼睛看起來會很奇怪,而且沒有對焦的感覺。奇怪的是,動畫師們使用的眼球懸掛卻沒有這種位移。不過它的旋轉是由一個定位器確定的,能夠確定角色確實在看的方向。他們沒有精細地微調眼球的焦點,只需要定義它的朝向就行了。
兩個加上最終外觀的球體,有位移與無位移
Lewis的凝視表情,加入位移之前與之后另外,我們在角膜上有一個突出貼圖,用來定義角膜突出,以及少量的突出噪點。我們選擇比真實位移更大的突出,這是為了避免眼瞼向內陷進去的問題。突出貼圖為我們很好地將眼球上的直接高光分開,跟真正的角膜很相似。
角膜突出 將來的工作這里會介紹我們的眼球投影技術背后的核心功能。從眼球的中心投影這一基礎概念讓我們可以在簡單地材質投影之外添加很多其他的特性。我們添加了一些可以柔化和混合瞳孔、虹膜和鞏膜之間的邊緣的特性。另外,將來的制作會將著色器模塊擴展,具體如下: 虹膜和鞏膜的連續位移,用于避免我們現有貼圖中的異常頂點產生的位移假象。 為鏡面高光添加矢量補償,這樣燈光師可以將它向左或向右移動,而不需要調整燈光。 為鏡面高光添加形狀控制,這樣它就能夠變成燈光師想要的形狀,比如標準的球體或者橢圓或者其他的形狀。 在虹膜的反面添加鏡面高光,做出豐富的焦散效果。這點也可以使用矢量補償來實現。在陰影計算中添加一個比例系數,這樣做實際上是一種取巧,沿著眼瞼的內部生成陰影。相似地,由于我們的坐標系有向上的概念,我們可以旋轉陰影貼圖,在上眼瞼上生成更深的陰影。最后,當我們將動畫師的懸掛更好的適配到我們渲染的內容之后,外觀發展過程就完整了。我們沒有使用CSG幾何圖形,而是生成了一個Maya的硬件著色器插件,它能夠準確復制RenderMan著色器投影技術。這個插件實際上將Nvidia的Cg著色器語言加入到了Maya當中,并讓我們能夠使用各種屬性調整著色器設置。在這種情況下,同樣的rmanFirisX會控制RenderMan的著色器。我們甚至會參考同樣的默認材質文件。事實證明這樣會比之前的解決方案更準確,而且更快。
Maya的硬件著色器的截圖
ellipseAngle()計算的可視化表示