Cesium - custom primitve 的使用

这篇具有很好参考价值的文章主要介绍了Cesium - custom primitve 的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

cesium的官方例子 Custom Primitive 很有用,通过这个例子可以学到 如何在 cesium 中 自定义几何体 和 着色器。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <meta name="description" content="Custom Primitive example." />
    <meta name="cesium-sandcastle-labels" content="Development" />
    <title>Cesium Demo</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script
      type="text/javascript"
      src="../../../Build/CesiumUnminified/Cesium.js"
      nomodule
    ></script>
    <script type="module" src="../load-cesium-es6.js"></script>
  </head>
  <body
    class="sandcastle-loading"
    data-sandcastle-bucket="bucket-requirejs.html"
  >
    <style>
      @import url(../templates/bucket.css);
      #toolbar input[type="range"] {
        width: 70px;
      }
      #toolbar input {
        vertical-align: middle;
        padding-top: 2px;
        padding-bottom: 2px;
      }
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>

    <script id="cesium_sandcastle_script">
      window.startup = async function (Cesium) {
        "use strict";
        //Sandcastle_Begin

        const viewer = new Cesium.Viewer("cesiumContainer");

        /**
         * Simple example of writing a Primitive from scratch. This
         * primitive displays a procedurally-generated surface at a given
         * position on the globe.
         */
        function CustomPrimitive(cartographicPosition) {
          this.show = true;

          // This is initialized in the first call of update()
          // so we don't need a context
          this.drawCommand = undefined;

          // number of faces wide. There are resolution + 1 vertices.
          this.faceResolution = 1;

          // Compute a model matrix that puts the surface at a specific point on
          // the globe.
          this.cartographicPosition = cartographicPosition;
          const cartesianPosition = Cesium.Cartographic.toCartesian(
            cartographicPosition,
            Cesium.Ellipsoid.WGS84,
            new Cesium.Cartesian3()
          );
          this.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
            cartesianPosition,
            Cesium.Ellipsoid.WGS84,
            new Cesium.Matrix4()
          );

          this.halfWidthMeters = 10000;
          this.boundingSphere = new Cesium.BoundingSphere(
            cartesianPosition,
            this.halfWidthMeters * Math.SQRT2
          );

          this.time = undefined;
        }

        /**
         * generate a quad that's subdivided into faceResolution x faceResolution quads.
         * The vertices will be adjusted in the vertex shader.
         */
        function generateVertices(faceResolution, halfWidthMeters) {
          const vertexResolution = faceResolution + 1;
          const vertexCount = vertexResolution * vertexResolution;
          const componentsPerVertex = 3;
          const vertices = new Float32Array(vertexCount * componentsPerVertex);
          for (let i = 0; i < vertexResolution; i++) {
            for (let j = 0; j < vertexResolution; j++) {
              const u = i / (vertexResolution - 1);
              const v = j / (vertexResolution - 1);
              const index = i * vertexResolution + j;
              const x = halfWidthMeters * (2 * u - 1);
              const y = halfWidthMeters * (2 * v - 1);
              const z = 0;

              vertices[index * componentsPerVertex] = x;
              vertices[index * componentsPerVertex + 1] = y;
              vertices[index * componentsPerVertex + 2] = z;
            }
          }
          return vertices;
        }

        /**
         * Tessellate a big square region into faceResolution x faceResolution quads
         */
        function generateIndices(faceResolution) {
          const indicesPerQuad = 6;
          const indexCount = faceResolution * faceResolution * indicesPerQuad;
          const indices = new Uint16Array(indexCount);

          const vertexResolution = faceResolution + 1;

          let quadIndex = 0;
          for (let i = 0; i < faceResolution; i++) {
            for (let j = 0; j < faceResolution; j++) {
              const a = i * vertexResolution + j;
              const b = i * vertexResolution + (j + 1);
              const c = (i + 1) * vertexResolution + (j + 1);
              const d = (i + 1) * vertexResolution + j;

              indices[quadIndex * indicesPerQuad] = a;
              indices[quadIndex * indicesPerQuad + 1] = b;
              indices[quadIndex * indicesPerQuad + 2] = c;
              indices[quadIndex * indicesPerQuad + 3] = c;
              indices[quadIndex * indicesPerQuad + 4] = d;
              indices[quadIndex * indicesPerQuad + 5] = a;
              quadIndex++;
            }
          }

          return indices;
        }

        const scratchColor = new Cesium.Color();
        /**
         * Generate a 1D texture for the color palette
         */
        function generateTexture(context) {
          const width = 256;
          const textureTypedArray = new Uint8Array(width * 4);
          for (let i = 0; i < width; i++) {
            const bucket32 = 32 * Math.floor(i / 32);
            const bucket4 = 4 * Math.floor(i / 4);
            const color = Cesium.Color.fromHsl(
              bucket32 / width,
              bucket32 / width,
              (255 - bucket4) / width,
              1.0,
              scratchColor
            );
            textureTypedArray[4 * i] = 255 * color.red;
            textureTypedArray[4 * i + 1] = 255 * color.green;
            textureTypedArray[4 * i + 2] = 255 * color.blue;
            textureTypedArray[4 * i + 3] = 255 * color.alpha;
          }

          return new Cesium.Texture({
            context: context,
            pixelFormat: Cesium.PixelFormat.RGBA,
            pixelDataType: Cesium.ComponentDatatype.fromTypedArray(
              textureTypedArray
            ),
            source: {
              width: width,
              height: 1,
              arrayBufferView: textureTypedArray,
            },
            flipY: false,
            sampler: new Cesium.Sampler({
              minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
              magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
            }),
          });
        }

        function initialize(primitive, context) {
          // Inteference patterns made by two plane waves crossing each
          // other at an angle. The color is based on the height.
          const vertexShader = `
            in vec3 a_position;
            uniform float u_time;
            void main() {
                gl_Position = czm_modelViewProjection * vec4(a_position, 1.0);
            }
            `;

          const fragmentShader = `
            uniform float u_time;
            uniform vec4 u_color;
            void main() {
                out_FragColor = u_color;
            }
            `;

          const positionLocation = 0;
          const attributeLocations = {
            a_position: positionLocation,
          };

          const renderState = Cesium.RenderState.fromCache({
            depthTest: {
              enabled: true,
            },
          });

          const shaderProgram = Cesium.ShaderProgram.fromCache({
            context: context,
            vertexShaderSource: vertexShader,
            fragmentShaderSource: fragmentShader,
            attributeLocations: attributeLocations,
          });

          const positionTypedArray = generateVertices(
            primitive.faceResolution,
            primitive.halfWidthMeters
          );
          primitive.typedArr = positionTypedArray;
          const positionVertexBuffer = Cesium.Buffer.createVertexBuffer({
            context: context,
            typedArray: positionTypedArray,
            usage: Cesium.BufferUsage.STATIC_DRAW,
          });

          const positionAttribute = {
            index: positionLocation,
            vertexBuffer: positionVertexBuffer,
            componentsPerAttribute: 3,
            componentDatatype: Cesium.ComponentDatatype.fromTypedArray(
              positionTypedArray
            ),
          };

          const indexCount =
            primitive.faceResolution * primitive.faceResolution * 6;
          const indexTypedArray = generateIndices(primitive.faceResolution);
          const indexBuffer = Cesium.Buffer.createIndexBuffer({
            context: context,
            typedArray: indexTypedArray,
            indexDatatype: Cesium.ComponentDatatype.fromTypedArray(
              indexTypedArray
            ),
            usage: Cesium.BufferUsage.STATIC_DRAW,
          });

          const vertexArray = new Cesium.VertexArray({
            context: context,
            attributes: [positionAttribute],
            indexBuffer: indexBuffer,
          });

          const texture = generateTexture(context);

          primitive.time = performance.now();
          const color = Cesium.Color.ORANGE.withAlpha(0.6)
          const uniformMap = {
            u_time: function () {
              const now = performance.now();
              return now - primitive.time;
            },
            u_texture: function () {
              return texture;
            },
            u_color: () => color,
          };

          const drawCommand = new Cesium.DrawCommand({
            boundingVolume: primitive.boundingSphere,
            modelMatrix: primitive.modelMatrix,
            pass: Cesium.Pass.OPAQUE,
            shaderProgram: shaderProgram,
            renderState: renderState,
            vertexArray: vertexArray,
            count: indexCount,
            primitiveType: Cesium.PrimitiveType.LINE_STRIP,
            uniformMap: uniformMap,
          });
          primitive.drawCommand = drawCommand;
        }

        CustomPrimitive.prototype.update = function (frameState) {
          if (!this.show) {
            return;
          }

          // Rendering resources are initialized in the first update() call
          // so we have access to the rendering context
          if (!Cesium.defined(this.drawCommand)) {
            initialize(this, frameState.context);
          }
          this.typedArr[2] = 5000 * Math.sin(performance.now() * 0.001);
          this.typedArr[11] = 5000 * Math.cos(performance.now() * 0.001);
          this.drawCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(this.typedArr);
          frameState.commandList.push(this.drawCommand);
        };

        const position = new Cesium.Cartographic(0, 0, 1000.0);
        const primitive = viewer.scene.primitives.add(
          new CustomPrimitive(position)
        );
        viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(0, 0, 50000),
          duration: 0.1,
        });

        //Sandcastle_End
      };
      if (typeof Cesium !== "undefined") {
        window.startupCalled = true;
        window.startup(Cesium).catch((error) => {
          "use strict";
          console.error(error);
        });
        Sandcastle.finishedLoading();
      }
    </script>
  </body>
</html>

以上,是我对这个例子的修改,需要特别留意这处修改

this.drawCommand.vertexArray.getAttribute(0).vertexBuffer.copyFromArrayView(this.typedArr);

通过运行这个修改后的例子,说明了 可以 动态修改 着色器的 attribute 属性,从而可以实现可编辑形状的 primitive;需要特别留意的是,primitive的 modelMatrix 和 boundingSphere 需要初始化文章来源地址https://www.toymoban.com/news/detail-662438.html

import * as Cesium from 'cesium';
import * as THREE from 'three';

const tmpVector = new THREE.Vector3();
const tmpCenter = new THREE.Vector3();

function generateRectVertices() {
  const vertexCount = 4;
  const componentsPerVertex = 3;
  const vertices = new Float32Array(vertexCount * componentsPerVertex);
  const points = [-1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1];
  points.forEach((it, index) => (vertices[index] = it));
  return vertices;
}

export default class EditableRectCesium {
  show = true;
  modelMatrix = Cesium.Matrix4.clone(
    new THREE.Matrix4().elements,
    new Cesium.Matrix4(),
  );
  boundingSphere = new Cesium.BoundingSphere(
    new Cesium.Cartesian3(),
    Math.SQRT2 * 1,
  );
  time = performance.now();
  drawCommand;
  /**
   * @type {Float32Array}
   */
  float32Array;
  vectors = [];

  constructor(cartesian, vectors) {
    this.vectors = vectors;
    this.cartesian = cartesian;
    Cesium.Cartesian3.clone(cartesian, this.boundingSphere.center);
    this.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
      cartesian,
      Cesium.Ellipsoid.WGS84,
      new Cesium.Matrix4(),
    );
    const enuMatInv = Cesium.Matrix4.inverse(
      this.modelMatrix,
      new Cesium.Matrix4(),
    );
    const enuMatInv3 = new THREE.Matrix4();
    Cesium.Matrix4.clone(enuMatInv, enuMatInv3.elements);
    this.enuMatInv3 = enuMatInv3;
  }

  _init(context) {
    const vertexShader = `
            in vec3 a_position;
            uniform float u_time;
            void main() {
                gl_Position = czm_modelViewProjection * vec4(a_position, 1.0);
            }
            `;

    const fragmentShader = `
            uniform float u_time;
            uniform vec4 u_color;
            void main() {
                out_FragColor = u_color;
            }
            `;
    const positionLocation = 0;
    const attributeLocations = {
      a_position: positionLocation,
    };
    const renderState = Cesium.RenderState.fromCache({
      depthTest: {
        enabled: true,
      },
    });
    const shaderProgram = Cesium.ShaderProgram.fromCache({
      context: context,
      vertexShaderSource: vertexShader,
      fragmentShaderSource: fragmentShader,
      attributeLocations: attributeLocations,
    });

    const positionTypedArray = generateRectVertices();
    this.float32Array = positionTypedArray;
    const positionVertexBuffer = Cesium.Buffer.createVertexBuffer({
      context: context,
      typedArray: positionTypedArray,
      usage: Cesium.BufferUsage.STATIC_DRAW,
    });

    const positionAttribute = {
      index: positionLocation,
      vertexBuffer: positionVertexBuffer,
      componentsPerAttribute: 3,
      componentDatatype:
        Cesium.ComponentDatatype.fromTypedArray(positionTypedArray),
    };

    const indexTypedArray = new Uint16Array([0, 1, 2, 0, 2, 3]);
    const indexBuffer = Cesium.Buffer.createIndexBuffer({
      context: context,
      typedArray: indexTypedArray,
      indexDatatype: Cesium.ComponentDatatype.fromTypedArray(indexTypedArray),
      usage: Cesium.BufferUsage.STATIC_DRAW,
    });

    const vertexArray = new Cesium.VertexArray({
      context: context,
      attributes: [positionAttribute],
      indexBuffer: indexBuffer,
    });

    const uniformMap = {
      u_time: performance.now(),
      u_color: () => Cesium.Color.ORANGE.withAlpha(0.8),
    };
    const drawCommand = new Cesium.DrawCommand({
      boundingVolume: this.boundingSphere,
      modelMatrix: this.modelMatrix,
      pass: Cesium.Pass.TRANSLUCENT,
      shaderProgram: shaderProgram,
      renderState: renderState,
      vertexArray: vertexArray,
      count: indexTypedArray.length,
      primitiveType: Cesium.PrimitiveType.TRIANGLES,
      uniformMap: uniformMap,
    });
    this.drawCommand = drawCommand;
  }

  update(frameState) {
    if (!this.show) {
      return;
    }

    // Rendering resources are initialized in the first update() call
    // so we have access to the rendering context
    if (!Cesium.defined(this.drawCommand)) {
      this._init(frameState.context);
    }
    // this.updatePositionAttr(this.vectors);
    frameState.commandList.push(this.drawCommand);
  }

  updatePositionAttr(vectors) {
    if (!this.drawCommand) {
      return;
    }
    const buffer = this.drawCommand.vertexArray.getAttribute(0).vertexBuffer;
    const arr = this.float32Array;
    // tmpCenter.set(0, 0, 0);
    vectors.forEach((vector, index) => {
      // tmpCenter.add(vector);
      tmpVector.copy(vector).applyMatrix4(this.enuMatInv3);
      arr[index * 3] = tmpVector.x;
      arr[index * 3 + 1] = tmpVector.y;
      arr[index * 3 + 2] = tmpVector.z;
    });
    buffer.copyFromArrayView(arr);
    // tmpCenter.divideScalar(4);
    // const radius = vectors[0].distanceTo(vectors[2]) * 0.5;
    // Cesium.Cartesian3.clone(tmpCenter, this.boundingSphere.center);
    // this.boundingSphere.radius = radius;
  }
}

到了这里,关于Cesium - custom primitve 的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Cesium 1.02.0 及以上版本下自定义材质报错:[Cesium WebGL] Fragment shader compile log: ERROR: 0:8: ‘texture2D‘

    2023年4月19日更新— 搞了一个 Cesium 镜像,欢迎使用:沙盒示例 和 API 在看到 Cesium 官方更新的日志, 最新版(1.103.0) 支持平滑缩放,于是升级尝试一下。 结果偶然发现,之前写的 墙体动态效果报错 ,经过调试,找到原因, Cesium 新版对 WebGL2 支持有变化 ,这里记录一下。

    2024年02月11日
    浏览(48)
  • uniapp中使用微信小程序custom-tab-bar

    今天把小程序项目中的 tabBar 改为使用自定义的tabbar 其实很简单,只要按照小程序开发文档中的步骤来做 在 app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。 示例: 在代码根目

    2023年04月08日
    浏览(34)
  • UE4/5的Custom节点:在VScode使用HLSL(新手入门用)

    目录 custom节点 VSCode环境安装 将VSCode里面的代码放入Custom中 可以看到这是一个简单的Custom节点:  而里面是可以填写代码的:  但是在这里面去写代码会发现十分的繁琐【按下enter后,不会换行,也不会自动缩进】 所以这里我们就可以去vscode里面写: 首先是去vscode里面安装

    2024年02月11日
    浏览(53)
  • WebGL简介以及使用

    WebGL(Web图形库) 是一种在没有使用插件的情况下在网页浏览器中渲染2D图形和3D图形的技术。它基于OpenGL ES,一个在嵌入式系统中广泛使用的图形API。WebGL通过HTML5的 canvas 元素直接在网页上实现图形渲染,使得开发者能够创建复杂的视觉效果和动态图形,而不会牺牲网页的性

    2024年02月01日
    浏览(28)
  • 使用Element UI图片容器报错 Unknown custom element: <el-image>

    记一次项目中使用el-image组件报错问题,报错如下: 查阅资料后发现项目中使用的element版本不支持该组件,查看项目的package.json文件,发现使用的element ui版本为:2.4.6。而el-image组件是在2.8.0引入的 Elemtnt UI更新日志这里可以看到在2.8.0的时候加入了Image组件 解决办法:升级

    2024年02月04日
    浏览(47)
  • 快速上手WebGL,代码+图解手把手教你使用WebGL一步步实现热力图

    大家好,我是南木元元,热衷分享有趣实用的文章。 项目中需要绘制热力图,热力图其实就是数值大小用颜色来进行区分,每个点的数值需根据颜色映射表(调色板)映射为指定颜色。需要3个数值字段,可绘制在平行坐标系中(2个数值字段分别确定x、y轴,1个数值字段确定

    2024年01月18日
    浏览(52)
  • WebGL 同时使用多幅纹理

    目录 前言 ​编辑 示例代码 颜色矢量的分量乘法来计算两个纹素最终的片元颜色

    2024年02月09日
    浏览(35)
  • uniapp 开发微信小程序 中使用 custom-tab-bar创建自定义tabbar

    1.   目录结构必须按照如图所示,在src 目录下   2. index.js 3.  index.html 4.  wxss 5. index.json  按照微信官方文档,以及代码片段,需要在tabbar 页面中onshow生命周期内设置 tabbar 的选中状态,但是在 uniapp 创建的 页面中是 this 是不包含 getTabBar 方法的, 只有通过 this.$mp.page或者

    2024年02月10日
    浏览(34)
  • 解决:使用hexo deploy部署之后,github page的custom domian自定义域名失效

    使用hexo搭建个人博客网站,将个人博客托管导github上,并设置在github page设置custom damain自定义域名 然后每次部署完,自定域名都会消失 在hexo项目的source文件夹下新建CNAME文件,里面填入你的域名,并保存,这样每次hexo deploy后,github page就不会出现域名重置了

    2024年03月14日
    浏览(51)
  • Openlayers使用WebGL加载多种自定义图标矢量点

    使用OpenLayers的 WebGLPointsLayer 加载海量矢量点(100W),并使用 多种自定义图标样式 。 你需要满足以下环境要求: 支持WebGL 的浏览器(Chrome、Firefox、Safari和Edge等)。 计算机具有一定的图形处理能力( 显卡 )。 一定的计算机 内存和网络带宽 。 一点耐心 1.创建一个 包含所有

    2024年04月11日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包