自定义材质的两种方式
new Cesium.Material
- 独立实例:使用
new Cesium.Material每次都会创建一个新的材质实例,即使材质的定义和参数与之前创建的一样。这会导致更多的内存占用,特别是当场景中有许多材质实例且它们可以复用时。
- 灵活性:直接实例化提供了更高的灵活性,因为你可以直接控制材质实例的生命周期,而不受缓存管理的影响。这在你需要对材质实例进行特定操作或管理其生命周期时很有用。
- 直接控制:创建独立的实例允许你直接修改实例的属性,而不会影响到可能存在的其他相同配置的材质实例。
let aper = new Cesium.MaterialAppearance({
faceForward: true,
material: new Cesium.Material({
fabric: {
uniforms: {
uTime: 0,
uWaterColor: new Cesium.Color(0.0, 0.0, 1.0, 0.5),
uLineColor: new Cesium.Color(0.0, 1.0, 1.0, 0.5),
uImage: "",
},
source: `
float random(float x) {
return fract(sin(x) * 10000.);
}
float noise(vec2 p) {
return random(p.x + p.y * 10000.);
}
vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }
float smoothNoise(vec2 p) {
vec2 interp = smoothstep(0., 1., fract(p));
float s = mix(noise(sw(p)), noise(se(p)), interp.x);
float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
return mix(s, n, interp.y);
}
float fractalNoise(vec2 p) {
float x = 0.;
x += smoothNoise(p );
x += smoothNoise(p * 2. ) / 2.;
x += smoothNoise(p * 4. ) / 4.;
x += smoothNoise(p * 8. ) / 8.;
x += smoothNoise(p * 16.) / 16.;
return x / (3. + 1./2. + 1./4. + 1./8. + 1./16.);
}
float movingNoise(vec2 p) {
float x = fractalNoise(p +0.5* uTime);
float y = fractalNoise(p -0.5* uTime);
return fractalNoise(p + vec2(x, y));
}
float nestedNoise(vec2 p) {
float x = movingNoise(p);
float y = movingNoise(p + 100.);
return movingNoise(p + vec2(x, y));
}
vec4 czm_getMaterial(vec2 vUv)
{
vec2 uv = vUv;
uv = vUv * 2.0 - 1.0;
float n = nestedNoise(uv * 6.);
vec4 newColor = vec4(mix(uWaterColor.rgb, uLineColor.rgb, n), 0.5);
return newColor;
}
`,
},
}),
translucent: true,
vertexShaderSource: `
attribute vec3 position3DHigh;
attribute vec3 position3DLow;
attribute float batchId;
attribute vec2 st;
attribute vec3 normal;
varying vec2 v_st;
varying vec3 v_positionEC;
varying vec3 v_normalEC;
void main() {
v_st = st;
vec4 p = czm_computePosition();
v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates
v_normalEC = czm_normal * normal; // normal in eye coordinates
gl_Position = czm_modelViewProjectionRelativeToEye * p;
}
`,
fragmentShaderSource: `
varying vec2 v_st;
varying vec3 v_positionEC;
varying vec3 v_normalEC;
void main() {
vec3 positionToEyeEC = -v_positionEC;
vec3 normalEC = normalize(v_normalEC);
czm_materialInput materialInput;
materialInput.normalEC = normalEC;
materialInput.positionToEyeEC = positionToEyeEC;
materialInput.st = v_st;
vec4 color = czm_getMaterial(v_st);
gl_FragColor = color;
}
`,
});
Cesium.Material._materialCache.addMaterial
- 资源管理:此方法会将新材质添加到Cesium内部维护的材质缓存中。这意味着如果你尝试添加一个已经存在于缓存中的材质(基于相同的定义和参数),它不会创建新的实例,而是返回缓存中已有的材质实例。这种方式有助于减少内存消耗,避免相同材质的重复创建。
- 重复利用:通过缓存,可以确保多个具有相同属性的材质实例共享相同的底层资源,这对于性能优化尤其重要,尤其是在大量使用相同材质的场景中。
- 访问方式:通常情况下,直接通过
Cesium.Material._materialCache.getMaterial(materialId)来获取缓存中的材质,其中materialId是材质定义的唯一标识符。
class waterMaterial {
constructor() {
Cesium.Material._materialCache.addMaterial('waterMaterial', {
fabric: {
type:'waterMaterial',
uniforms: {
uTime: 0,
uWaterColor: new Cesium.Color(0.0, 0.0, 1.0, 0.5),
uLineColor: new Cesium.Color(0.0, 1.0, 1.0, 0.5),
uImage: "",
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
// czm_frameNumber得到当前屏幕的刷新率
float animation = czm_frameNumber/60.0;
// vec4 colorImage = texture2D(image, vec2(fract(st.s - animation), st.t));
// material.alpha = colorImage.a * color.a;
// material.diffuse = (colorImage.rgb+color.rgb)/2.0;
material.diffuse =vec3(1.0,0.0,0.0);
return material;
}
`,
},
translucent: function (material) {
return true;
},
})
}
getType() {
return 'waterMaterial'
}
getValue(time, result) {
return result
}
}