Cesium实现一材质多贴图,一个模型多张贴图,自定义attribute

 思路:

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>

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值