Cesium自定義材質(zhì)

材質(zhì)是用于描述多邊形、折線、橢球等對象的外觀特征,材質(zhì)可以是幾何對象表面的任一一種著色,可以是貼在其表面的一張圖片、也可以是一個(gè)紋理或圖案。cesium中也提供了一些材質(zhì),比如顏色、圖片,棋盤、虛線,箭頭線等。但這些基本是不會(huì)滿足我們實(shí)際開發(fā)中的需求,需要自定義材質(zhì)。使用FabricGLSL可以寫腳本新建材質(zhì),也可以從現(xiàn)在的材質(zhì)中派生。

1. Material

Material是用于修改幾何對象材質(zhì)的一個(gè)類,在添加幾何圖形的時(shí)候,將設(shè)置material屬于,用于設(shè)置幾何對象的材質(zhì)。如給繪制的線條設(shè)置一個(gè)顏色,可以使用顏色材質(zhì),如下所示:

let line = new Cesium.Entity({
            polyline:new Cesium.PolylineGraphics({
                positions : positions,
                material:Cesium.Color.RED.withAlpha(0.5),
                width:5,
            })
        });

Cesium為我們提供了23種現(xiàn)成的Material類型,可通過Material.fromType方法和Fabric兩種方式去獲取并設(shè)置幾何對象材質(zhì)。如下是通過Material類的兩種方式實(shí)現(xiàn)著色的示例:

polygon.material = Cesium.Material.fromType('Color');
polygon.material.uniforms.color = new Cesium.Color(1.0, 1.0, 0.0, 1.0);
//Fabric
polygon.material = new Cesium.Material({
    fabric : {
        type : 'Color',
        uniforms : {
            color : new Cesium.Color(1.0, 1.0, 0.0, 1.0)
        }
    }
});

2. Fabric

FabricCesium中用于描述材質(zhì)的一種JSON規(guī)定,使用FabricGLSL可以方便的定義材質(zhì)。定義一個(gè)簡單的Fabric對象,需要配置type,uniforms,兩個(gè)屬性,如果需要自定義著色器,需要添加source屬性。如下為創(chuàng)建一個(gè)簡單的Fabric對象:

polygon.appearance.material = new Cesium.Material({
  fabric: {
    type: 'Color',
    uniforms: {
      color: new Cesium.Color(1.0, 0.0, 0.0, 0.5)
    }
  }
})

// 修改顏色
polygon.appearance.material.uniforms.color = Cesium.Color.WHITE

type:用于定義材質(zhì)的類型,使用的時(shí)候可以直接通過Cesium.Material.fromType('type');來指定定義好的材質(zhì)。設(shè)置該參數(shù),可以復(fù)用材質(zhì),傳入一個(gè)不存在的 type類型之后,這個(gè)材質(zhì)將被緩存下來。下次調(diào)用 new Cesium.Material或者 Material.fromType 就會(huì)引用緩存里的材質(zhì),不需要再傳入Fabric對象。
uniforms:用于定義變量,每個(gè) Material 均可以有 0 ~ N 個(gè) uniform,這個(gè)參數(shù)在建立時(shí)指定,也能夠在渲染后修改。其中有一個(gè)repeat屬性,用于控制圖片在水平和垂直方向重復(fù)的次數(shù)。
components: 該屬性包含了 定義了材質(zhì)外觀的子屬性。每個(gè)子屬性是一個(gè)GLSL的代碼段。該屬性值包含了以下幾個(gè)子屬性:

1. diffuse:材質(zhì)的散射光通道,使用vec3定義了光在所有方向的散射值 。
2. specular:材質(zhì)的高光屬性,定個(gè)定義了材質(zhì)的反射強(qiáng)度。
3. shininess:高反射的銳度,值 越大創(chuàng)建一個(gè)更小的高亮光斑。
4. normal:材質(zhì)的法向?qū)傩?,使?code>vec3定義了在視點(diǎn)空間的表面法向量,一般在法向貼圖上使用,默認(rèn)是表面法向量。
5. emission:材質(zhì)的自發(fā)光屬性,使用vec3定義了所有方向上燈光發(fā)出的顏色。
6. alpha:材質(zhì)的透明度,使用一個(gè)float值 定義。

2.1創(chuàng)建新的材質(zhì)

創(chuàng)建一個(gè)新的材質(zhì),只需要設(shè)置Fabric,再加上一點(diǎn)點(diǎn)GLSL或者其他材質(zhì)就可以了。通過source可以指定glsl的代碼,如下是返回每個(gè)分量的默認(rèn)值:

czm_material czm_getMaterial(czm_materialInput materialInput)
{
    return czm_getDefaultMaterial(materialInput);
}

Fabric這么定義:

{
  source : 'czm_material czm_getMaterial(czm_materialInput materialInput) { return czm_getDefaultMaterial(materialInput); }'
}

2.2 材質(zhì)輸入

czm_getMaterial函數(shù)中有一個(gè)czm_materialInput類型的屬性,用于設(shè)置材質(zhì)的輸入,materialInput 變量在sourcecomponents屬性中都可以配置,主要包括以下幾個(gè)屬性:
1.s:一維紋理坐標(biāo)。
2.st:二維紋理坐標(biāo)。
3.str:三維紋理坐標(biāo)。
4. tangentToEyeMatrix:從片元的切線空間轉(zhuǎn)到視點(diǎn)空間的轉(zhuǎn)換矩陣,在法向貼圖和凹凸貼圖時(shí)使用。
5. positionToEyeEC:從片元到視點(diǎn)之間的向量,為了反射和折射計(jì)算。向量的模表示了從片元到視點(diǎn)的距離。
6. normalEC:片元在視點(diǎn)空間的單位化后的法向量,在凹凸貼圖、反射、折射的時(shí)候使用。

2.3 合并材質(zhì)

Fabric 有個(gè)materials屬性,它的每個(gè)子屬性也是Fabric材質(zhì)。他們的材質(zhì)可以可以在components或者source中引用。比如一個(gè)塑料材質(zhì)可以通過 DiffuseMapSpecularMap兩個(gè)材質(zhì)的合并來模擬。

{
  type : 'OurMappedPlastic',
  materials : {
    diffuseMaterial : {
      type : 'DiffuseMap'
    },
    specularMaterial : {
      type : 'SpecularMap'
    }
  },
  components : {
      diffuse : 'diffuseMaterial.diffuse',
      specular : 'specularMaterial.specular'
  }
};

3自定義Material類

在實(shí)際開發(fā)中,為了使用方便,往往將一些常用的材質(zhì)一個(gè)一個(gè)的封裝,需要將其定義成Material類,以方便代碼的復(fù)用。如下為封裝的一個(gè)擴(kuò)散回的代碼:

import  * as Cesium from '@/Cesium/Source/Cesium';
import createPropertyDescriptor from "@/Cesium/Source/DataSources/createPropertyDescriptor.js";
import Property from "@/Cesium/Source/DataSources/Property.js";
const source =  "czm_material czm_getMaterial(czm_materialInput materialInput)\n" +
                "{\n" +
                "czm_material material = czm_getDefaultMaterial(materialInput);\n" +
                "material.diffuse = 1.5 * color.rgb;\n" +
                "vec2 st = materialInput.st;\n" +
                "float dis = distance(st, vec2(0.5, 0.5));\n" +
                "float per = fract(time);\n" +
                "if(dis > per * 0.5){\n" +
                "material.alpha = 0.0;\n"+
                "discard;\n" +
                "}else {\n" +
                "material.alpha = color.a  * dis / per / 1.0;\n" +
                "}\n" +
                "return material;\n" +
                "}";
function AnimationPointMaterialProperty(color,duration) {
    Cesium.PolylineTrailLinkMaterialProperty = AnimationPointMaterialProperty;
    Cesium.Material.AnimationPointMaterialType = 'AnimationPoint';
    Cesium.Material.AnimationPointMaterialSource = source;
    Cesium.Material._materialCache.addMaterial(Cesium.Material.AnimationPointMaterialType, {
        fabric: {
            type: Cesium.Material.AnimationPointMaterialType,
            uniforms: {
                color: new Cesium.Color(1.0, 0.0, 0.0, 1),
                time: 0
            },
            source: Cesium.Material.AnimationPointMaterialSource
        },
        translucent: function (material) {
            return true;
        }
    })
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._colorSubscription = undefined;
    this.color = color;
    this.duration = duration;
    this._time = (new Date()).getTime();
}

Object.defineProperties(AnimationPointMaterialProperty.prototype, {
    isConstant: {
        get: function () {
            return Property.isConstant(this._color);
        },
    },

    definitionChanged: {
        get: function () {
            return this._definitionChanged;
        },
    },

    color: createPropertyDescriptor("color"),
});

AnimationPointMaterialProperty.prototype.getType = function () {
    return "AnimationPoint";
};

AnimationPointMaterialProperty.prototype.getValue = function (time, result) {
    if (!Cesium.defined(result)) {
        result = {};
    }
    result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
    result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
};

AnimationPointMaterialProperty.prototype.equals = function (other) {
    return (
        this === other ||
        (other instanceof AnimationPointMaterialProperty &&
            Property.equals(this._color, other._color))
    );
};
export default AnimationPointMaterialProperty;

3.1 公共方法

在定義自己的AnimationPointMaterialProperty時(shí),需要設(shè)置幾個(gè)公共的方法,分別是:getValue,isConstant,definitionChanged,equals。
1.getValue:用來獲取某個(gè)時(shí)間點(diǎn)的特定屬性值,包括兩個(gè)參數(shù):typeresult,分別是用于傳遞時(shí)間點(diǎn)和存儲(chǔ)屬性值。
2.isConstant:用來判斷該屬性是否會(huì)隨時(shí)間變化,是一個(gè)bool類型。Cesium會(huì)通過這個(gè)變量來決定是否需要在場景更新的每一幀中都獲取該屬性的數(shù)值,從而來更新三維場景中的物體。如果isConstanttrue,則只會(huì)獲取一次數(shù)值,除非definitionChanged事件被觸發(fā)。
3.definitionChanged:是一個(gè)事件,可以通過該事件,來監(jiān)聽該P(yáng)roperty自身所發(fā)生的變化,比如數(shù)值發(fā)生修改。
4.equals:用來檢測屬性值是否相等。
具體的實(shí)例可以在。cgis中預(yù)覽,后期將添加更多的自定義材質(zhì)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容