Cesium官方教程12--材質(Fabric)

原文地址:https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric
介紹
Fabric 是Cesium中基於JSON格式來描述materials的機制。材質描述多邊形、折線、橢球等對象的外觀特徵。
材質可以簡單的是覆蓋一張圖片,或者是條紋或者棋盤圖案。使用Fabric 和GLSL,可以從零開始寫腳本新建材質,也可以從現有的材質中派生。比如潮溼碎裂的磚塊可以使用程序生成的紋理、凹凸貼圖和反射貼圖來組合。
對象通過material 屬性來支持材質效果。當前這些對象是多邊形、折線、橢球等(這篇文章寫的較早,其實現在已經很多幾何體都支持材質了)。
Cesium官方教程12--材質(Fabric)
上面,Color是一個內置材質,它表示了包含透明度在內的一個顏色值。Material.fromType是簡略寫法,完整的Fabric的JSON應該是這樣的:
Cesium官方教程12--材質(Fabric)
每一個材質包含0或者更多個uniforms,uniform是一種輸入參數變量,在創建材質時或者創建材質後修改。比如 , Color有一個 color uniform ,它包含red, green, blue, 和alpha四個部件。
Cesium官方教程12--材質(Fabric)
內置材質
Cesium有一些內置材質,應用最廣泛的是這兩個:
Cesium官方教程12--材質(Fabric)
如同上面的 Color 一樣,所有的內置材質都可以這麼創建。比如:
Cesium官方教程12--材質(Fabric)
或者
Cesium官方教程12--材質(Fabric)
程序生成的紋理 (Procedural Textures)
程序生成的紋理,他們不依賴於外部圖片文件,是通過GPU編程計算的圖案,他們可以表示顏色和透明。
Cesium官方教程12--材質(Fabric)
基本材質
Base materials represent fine-grain fundamental material characteristics, such as how much incoming light is reflected in a single direction, i.e., the specular intensity, or how much light is emitted, i.e., the emission. These materials can be used as is, but are more commonly combinedusing Fabric to create a more complex material.
Cesium官方教程12--材質(Fabric)
折線材質
這隻一種只能添加到折線幾何體上的材質。
Cesium官方教程12--材質(Fabric)
其他材質
還有一些不適合歸到其他類的材質
Cesium官方教程12--材質(Fabric)
瞭解更多材質,可以去看下這個 Cesium Materials Plugin.

通用的Uniforms
很多材質都有一個image uniform,它是一個圖片訪問地址,或者數據URI。
polygon.material.uniforms.image = 'image.png';
polygon.material.uniforms.image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAC/SURBVDhPrZPRDYQgEEQpjVKuFEvhw0IoxU6QgQwMK+vdx5FsooT3GHdjCM4qZnnnHvvkYoxFi/uvIhwiRCClXFC6v5UQ1uQAsbrkHCLsbaPjFgIzQQc1yUOwu33ePGE3BQUaee2BpjhbP5YUmkAlbNzsAURfBDqJnMIyyv4JjsCCgCnIR32uZUfcJuGBOwEk6bOKhoAADh31EIq3MgFg1mgkE1BA2AoUZoo2iZ3gyqGgmMDC/xWwkfb3/eUd7A1v3kxjNW9taQAAAABJRU5ErkJggg=='

一些材質,比如Diffuse 和 NormalMap 都要求圖片至少有RGB三個通道。另一個材質,比如Specular和Alpha要求圖片有一個通道。我們可以指定渲染的時候從哪些通道(或者什麼順序)從原始圖片中讀取數據,通過 channel這個字符串uniform來設置。比如,默認Specular材質是從 r讀取高光反射參數。不過我們可以如下修改它:
Cesium官方教程12--材質(Fabric)
這就是說可以把多個材質的信息放到一個圖片裏,比如在同一個圖片內,用rgb通道存儲diffuse值,用a通道存儲specular值。也就是說,我們的圖片只需要載入一次。
通常材質裏有一個repeat uniform,它控制了圖片在水平和垂直方向重複了多少次。這個在表面重複貼圖的時候很方便:
Cesium官方教程12--材質(Fabric)
創建新的材質
使用Fabric,只需要一點點GLSL或者其他材質就可以了。
如果不打算複用材質,那麼不要設置type參數。
Cesium官方教程12--材質(Fabric)
當在new Cesium.Material時,傳入一個不存在的 type類型之後,這個材質將被緩存下來。下次調用 new Cesium.Material 或者 Material.fromType 就會引用緩存裏的,就如同我們內置的材質一樣,那時候就不需要提供整個Fabric的定義,而僅僅傳遞 type以及想更改的 uniforms值。
Cesium官方教程12--材質(Fabric)
Components
或許最簡單有趣的材質就是純白色散射光:
Cesium官方教程12--材質(Fabric)
稍微複雜一點,增加一個高光元素,當視角正對反射光的時候更亮一些,當視角在邊上的時候稍微亮一些。
Cesium官方教程12--材質(Fabric)
components屬性包含了 定義了材質外觀的子屬性。每個子屬性是一個GLSL的代碼段,比如上面的vec3(0.5) ,它實際創建了一個三維向量,每個分量都設置爲 0.5。這裏可以訪問所有的GLSL函數,包括 mix,cos,texture2D`等等。現在有5種子屬性:
Cesium官方教程12--材質(Fabric)
綜上所述,子屬性或者components 定義了材質的特點。他們是材質的輸出值,是光照系統的輸入值。

代碼
提供完整的GLSL代碼是一種比前面 components 更靈活的方式。通過自定義czm_getMaterial函數,返回材質的各個分量。代碼如下:
Cesium官方教程12--材質(Fabric)
最簡單的實現就是返回每個分量的默認值。
Cesium官方教程12--材質(Fabric)
Fabric 這麼定義:
{
source : 'czm_material czm_getMaterial(czm_materialInput materialInput) { return czm_getDefaultMaterial(materialInput); }'
}
下面的示例代碼,只設置了diffuse和 specular分量的值:
Cesium官方教程12--材質(Fabric)
source相對 components更加繁瑣,但是更靈活,比如定義一些公用的函數,共享每個分量的計算過程等等。有個原則就是優先使用components屬性,除非明確需要實現 czm_getMaterial函數。也就是說 components的子屬性實際也是實現czm_getMaterial函數。而兩種方式下,我們都可以訪問GLSL 的內置函數和Cesium提供的GLSL函數(functions), 變量(uniforms), and 常量(constants)(鏈接已失效)。
材質輸入
materialInput 變量在source和 components屬性中都可以配置。它具有下面的字段,用來計算材質分量:

Cesium官方教程12--材質(Fabric)
把紋理座標的st值顯示出來的簡單方法:
Cesium官方教程12--材質(Fabric)
類似的,查看視點座標下的法向量,只需要 把materialInput.normalEC 設置到 diffuse 分量上。
除此之外,在materialInput裏,可以訪問uniforms變量,包括Cesium 提供的內置變量 uniforms 和 材質設置的uniforms變量。比如,我們可以設置自定義的Color材質,依據一個color 變量來設置diffuse和alpha 。
Cesium官方教程12--材質(Fabric)
Fabric中,uniform屬性的子屬性是GLSL中的uniform變量名 ,也是 new Material和 Material.fromType返回中JavaScript的對象屬性名。子屬性的值也是GLSL中uniform變量的值。(這塊意思就是說uniform下的屬性和值在GLSL的GPU環境和js的內存環境中一致的)。
可以通過一個自定義的 image變量來實現材質的DiffuseMap :

Cesium官方教程12--材質(Fabric)
上面代碼裏,'czm_defaultImage'是一個1x1的圖片。前面說過,這個值可以是一個圖片URL地址或者 數據URI。比如用戶可以使用我們自定義的OurDiffuseMap 材質,這麼來設置紋理:
Cesium官方教程12--材質(Fabric)
也有一個內置的立體貼圖:czm_defaultCubeMap。GLSL 標準的uniform變量類型float, vec3, mat4都是支持的。Uniform數組還不支持,但是已經在計劃內 roadmap。
材質的合併
至此,我們可以使用內置的材質,可以通過設置材質的components來自定義 ,或者實現完整的GLSL代碼source來自定義。我們還可以通過繼承已有的材質來新建材質。
Fabric 有個materials屬性,它的每個子屬性也是Fabric材質。他們的材質可以可以在 components 或者source 中引用。比如一個塑料材質可以通過 DiffuseMap和SpecularMap兩個材質的合併來模擬。
Cesium官方教程12--材質(Fabric)
這個材質的diffuse和specular 都是從其他材質中提取的。子屬性的名字叫diffuseMaterial 和specularMaterial(根據類型 DiffuseMap和SpecularMap創建的材質。不要搞混 類型 和 實例對象的名稱,在 components 和source 屬性中,子材質通過名稱訪問,因爲他們都是一個czm_material 結構,所以可以訪問.diffuse和 .specular分量。
基於這個Fabric材質,可以這麼用我們的材質:
Cesium官方教程12--材質(Fabric)
Fabric 格式
Fabric 是基於JSON 格式的格式定義。這格式定義裏詳細描述了Fabric的屬性和子屬性,包括 type, materials, uniforms, components, 和 source等。那裏面有一些JSON的格式示例,但是沒有必要去看。
對於一些嚴格要求的Fabric文件,可以使用一些類似 JSV的工具去驗證Fabric格式。
渲染流水線中的材質
Polygon, PolylineCollection, Ellipsoid, CustomSensorVolume等幾何體 已經 和材質系統集成。大部分用戶只需要簡單的設置material就可以了。可是,用戶還是想實現自己的材質渲染代碼。直接了當的去做就行了。
在渲染階段,材質就是一段GLSL函數czm_getMaterial 和 一些uniform變量。片段着色器需要構造一個 czm_MaterialInput結構,然後調用czm_getMaterial方法,把獲得的 czm_material 結果傳遞給光照處理函數去計算圖元顏色。
在JavaScript代碼裏,這些對象應該有一個 material屬性。當這個屬性變換的時候,update 函數應該把材質的GLSL代碼轉爲對象的片段着色器代碼,並且把對象和材質的uniform變量合併起來。
Cesium官方教程12--材質(Fabric)
Cesium官方教程12--材質(Fabric)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章