思路:
Material.fabric.uniforms添加自定义的两张贴图image_0,image_1。
Geometry.attributes添加imgIdx自定义属性,用于标识该顶点使用哪张贴图。
顶点着色器把imgIdx传入片元着色器。
片元着色器把imgIdx传入source(插值后的结果会有误差,所以用差的绝对值小于0.1来判断标识的值),source中根据imgIdx的值选取采样器(贴图)。
源码仓库:Apps/shaderMaterial_mult_img.html · changjiuxiong/Cesium-1.62Test - Gitee.com
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8">
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Hello World!</title>
<script src="../Build/Cesium/Cesium.js"></script>
<style>
@import url(../Build/Cesium/Widgets/widgets.css);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmNjJjMzY0OS1hZGQxLTRiZmYtYWYwNS03NmIyM2MwMDgwZDAiLCJpZCI6MTIzMTgsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1NjA4NDQ3Mjd9.OLTL_rs2gAi2R9zoztBHcJPDHnVl2Q7OZxRtZhoCeZE';
var viewer = new Cesium.Viewer('cesiumContainer');
let posList = [];
let nList = [];
let indexList = [];
let uvList = [];
let imgList = [];
posList = [
-1000000,-1000000,0,
-1000000,1000000,0,
1000000,-1000000,0,
-1000000,1000000,0,
1000000,1000000,0,
1000000,-1000000,0
];
nList = [
0,0,1,
0,0,1,
0,0,1,
0,0,1,
0,0,1,
0,0,1
];
uvList = [
0,0,
0,1,
1,0,
0,1,
1,1,
1,0
];
imgList = [
1,1,1,
2,2,2
];
indexList = [
0,1,2,
3,4,5
];
let pos = new Float64Array(posList);
let normal = new Float32Array(nList);
let index = new Uint32Array(indexList);
let st = new Float32Array(uvList);
let imgIdx = new Float32Array(imgList);
let boundingSphere = Cesium.BoundingSphere.fromVertices(pos);
//创建geometry
let geometry = new Cesium.Geometry({
attributes: {
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE,
componentsPerAttribute: 3,
values: pos
}),
st: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 2,
values: st
}),
normal: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 3,
values: normal
}),
imgIdx: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 1,
values: imgIdx
}),
},
indices: index,
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere: boundingSphere
});
let inst = new Cesium.GeometryInstance({
geometry: geometry
});
// 自定义材质
let aper = new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
type: 'Image',
uniforms: {
color_2: new Cesium.Color(1,1,1,1),
image_0: "./img/fsb.png",
image_1: "./img/ggj.png",
repeat_1: new Cesium.Cartesian2(1,1),
},
source:`
uniform vec4 color_2;
uniform vec2 repeat_1;
uniform sampler2D image_0;
uniform sampler2D image_1;
czm_material czm_getMaterial(czm_materialInput materialInput, float imgIdx)
{
czm_material material = czm_getDefaultMaterial(materialInput);
if(abs(imgIdx - 1.0)<0.1){
material.diffuse = texture2D(image_0, fract(repeat_1 * materialInput.st)).rgb;
}else if(abs(imgIdx - 2.0)<0.1){
material.diffuse = texture2D(image_1, fract(repeat_1 * materialInput.st)).rgb;
}else{
material.diffuse = vec3(1,0,0);
}
material.alpha = 1.0;
return material;
}
`,
}
}),
vertexShaderSource: `
attribute vec3 position3DHigh;
attribute vec3 position3DLow;
attribute vec3 normal;
attribute vec2 st;
attribute float imgIdx;
attribute float batchId;
varying vec3 v_positionEC;
varying vec3 v_normalEC;
varying vec2 v_st;
varying float v_imgIdx;
void main()
{
vec4 p = czm_computePosition();
v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates
v_normalEC = czm_normal * normal; // normal in eye coordinates
v_st = st;
v_imgIdx = imgIdx;
gl_Position = czm_modelViewProjectionRelativeToEye * p;
}
`,
fragmentShaderSource: `
varying vec3 v_positionEC;
varying vec3 v_normalEC;
varying vec2 v_st;
varying float v_imgIdx;
void main()
{
vec3 positionToEyeEC = -v_positionEC;
vec3 normalEC = normalize(v_normalEC);
#ifdef FACE_FORWARD
normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
#endif
czm_materialInput materialInput;
materialInput.normalEC = normalEC;
materialInput.positionToEyeEC = positionToEyeEC;
materialInput.st = v_st;
czm_material material = czm_getMaterial(materialInput,v_imgIdx);
#ifdef FLAT
gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);
#else
gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
#endif
}
`,
});
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(110, 40, 10)
);
viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: inst,
appearance: aper,
modelMatrix: modelMatrix,
}));
viewer.camera.flyToBoundingSphere(new Cesium.BoundingSphere(
Cesium.Cartesian3.fromDegrees(110, 40, 10), 950000,
),{
duration: 0.1,
});
function renderLoop(timestamp){
// aper.material.uniforms.iTime = timestamp/1000;
requestAnimationFrame(renderLoop);
}
renderLoop();
</script>
</body>
</html>