03-Cesium自定义着色器完整代码以及注释

1. 效果展示

2. 完整代码

<!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.0" />
    <title>自定义着色器完整代码</title>
    <!-- 线上 -->
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.107.1/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.107.1/Build/Cesium/Widgets/widgets.css" rel="stylesheet" />

    <style>
      #map {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <script>
      Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhZjZkZDAwZC1mNTFhLTRhOTEtOGExNi00MzRhNGIzMDdlNDQiLCJpZCI6MTA1MTUzLCJpYXQiOjE2NjA4MDg0Njd9.qajeJtc4-kppqfR1--Y2FqCu5r3TE1xYYGnEQhy-JF0'
      const viewer = new Cesium.Viewer('map', {
        infoBox: false,
        shadows: true,
        terrainShadows: Cesium.ShadowMode.RECEIVE_ONLY,
        terrain: Cesium.Terrain.fromWorldTerrain(),
      })

      //平面的顶点数据
      let points = [110.2, 20.0, 112.2, 20.0, 110.2, 22.0, 112.2, 22.0]
      let positions = Cesium.Cartesian3.fromDegreesArray(points)
      //顶点对应的纹理坐标数据
      let sts = [0, 0, 0, 1, 1, 0, 1, 1]

      //顶点卷绕的方式
      let positionIndex = [0, 1, 2, 1, 2, 3]

      function primitivePlaneShader(options) {
        console.log(options, 'options')
        let viewer = options.viewer
        let vertexShader = v_shader()
        let fragShader = f_shader()
        let sts = new Uint8Array(options.sts) //纹理数据
        let positionIndex = new Uint16Array(options.positionIndex) //顶点索引数据
        let tempPosition = []
        for (var i = 0; i < options.positions.length; i++) {
          tempPosition.push(options.positions[i].x)
          tempPosition.push(options.positions[i].y)
          tempPosition.push(options.positions[i].z)
        }
        positions = new Float64Array(tempPosition) //顶点数据
        let geometry = createGeometry(positions, sts, positionIndex) //几何体
        let appearance = createAppearance(vertexShader, fragShader) //外观
        //primitive方式加载
        viewer.scene.primitives.add(
          new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
              //渲染的几何体
              geometry: geometry,
            }),
            appearance: appearance, //外观
            asynchronous: false,
          })
        )
      }
      function createAppearance(vertexShader, fragShader) {
        return new Cesium.Appearance({
          material: new Cesium.Material({
            /* 在Cesium中,fabric 是用于创建着色器材质(Shader Material)的对象。
            它允许您定义一种着色器材质类型,并通过uniforms(统一变量)传递外部数据给着色器。 */
            fabric: {
              /* 
              uniforms是一个包含统一变量(Uniform)的对象。
              统一变量是一种在着色器程序中定义的全局变量,
              它们的值可以在渲染过程中从CPU(JavaScript代码)传递给GPU(着色器代码)。 */
              uniforms: {
                speed: 0.1,
              },
              source: getMS(),
            },
          }),
          translucent: false, //显示不为半透明
          renderState: {
            blending: Cesium.BlendingState.PRE_MULTIPLIED_ALPHA_BLEND, //使用Alpha混合功能启用混合
            depthTest: { enabled: true }, //深度检测
            depthMask: true, //将深度值写入深度缓冲区
          },
          fragmentShaderSource: fragShader, //片段着色器
          vertexShaderSource: vertexShader, //顶点着色器
        })
      }
      //构建几何体
      function createGeometry(positions, sts, positionIndex) {
        return new Cesium.Geometry({
          attributes: {
            //几何顶点属性
            position: new Cesium.GeometryAttribute({
              componentDatatype: Cesium.ComponentDatatype.DOUBLE, //数据类型
              componentsPerAttribute: 3, //定义几个为一组
              values: positions, //坐标值
            }),
            st: new Cesium.GeometryAttribute({
              componentDatatype: Cesium.ComponentDatatype.FLOAT, //数据类型
              componentsPerAttribute: 2, //定义几个为一组
              values: sts, //坐标值
            }),
          },
          indices: positionIndex, //顶点索引
          primitiveType: Cesium.PrimitiveType.TRIANGLES, //图元类型
          boundingSphere: Cesium.BoundingSphere.fromVertices(positions), //包围球
        })
      }
      function v_shader() {
        // 这段着色器代码的作用是将顶点变换到裁剪空间,并传递纹理坐标给片段着色器,为后续的光栅化和渲染阶段做准备。
        return `
                in vec3 position3DHigh;//这是一个输入变量,表示高精度的3D位置。通常情况下,这个变量的值是由CesiumJS引擎在渲染过程中提供的,它表示当前处理的顶点或片段的高精度3D位置。
            		in vec3 position3DLow;//这也是一个输入变量,表示低精度的3D位置。在CesiumJS中,当高精度3D位置无法完全表示时,这个变量提供额外的信息,以便更准确地确定位置。
            		in float batchId;//这是一个输入变量,表示批次ID。在CesiumJS中,通常用于将相同类型的几何体分组在一起,以优化渲染性能。
            		in vec2 st;//这是一个输入变量,表示纹理坐标。
            		out vec2 v_st; //这是一个输出变量,表示处理后的纹理坐标。
            		void main() {
                  // czm_computePosition() //计算模型视图相对眼睛坐标空间中的顶点位置。
                  //czm_modelViewProjectionRelativeToEye//变换顶点位置到裁剪空间,并将结果保存在position中。
            		  vec4 position = czm_modelViewProjectionRelativeToEye *czm_computePosition();
                  //将输入变量st赋值给输出变量v_st,这样纹理坐标将在顶点着色器中传递给片段着色器。
            		   v_st = st;
                   //将经过变换后的顶点位置position赋值给内置变量gl_Position,这样OpenGL将使用这个值来确定顶点在屏幕上的位置。
            		   gl_Position = position;
            		}
              `
      }

      function f_shader() {
        return `
              in vec2 v_st;//这是一个输入变量,表示纹理坐标。在片段着色器中,v_st变量将包含插值后的纹理坐标值,这些值在顶点着色器中计算并传递给片段着色器。
              //uniform float speed;
              void main() {
                //这一行将纹理坐标(v_st)转换为范围在[-1, 1]的坐标(position)。在OpenGL中,纹理坐标的范围通常是[0, 1],而转换后的坐标在顶点着色器的插值过程中进行了变换,使其范围变为[-1, 1]。
            		   vec2 position = -1.0 + 2.0 *v_st;
                   //这行代码调用一个函数getSpeed(),该函数返回一个浮点数,表示速度。
            		   float speed = getSpeed();
                   //这一行根据帧号(czm_frameNumber)和速度(speed)计算时间(time)。czm_frameNumber是CesiumJS引擎提供的一个内置变量,表示当前渲染帧的序号。
            		   float time= czm_frameNumber *speed;
                   //计算颜色
            		   float r = abs( cos( position.x * position.y + time / 5.0 ));
            		   float g = abs( sin( position.x * position.y + time / 4.0 ) );
            		   float b = abs( cos( position.x * position.y + time / 3.0 ) );
                   //并将其赋值给特殊的输出变量out_FragColor,这个变量是CesiumJS中用于存储片段着色器输出颜色的内置变量。
            		   out_FragColor = vec4( r, g, b, 1.0 );
            		}

              `
      }

      function getMS() {
        return `#version 300 es
              uniform float speed;
              float getSpeed(){
            		  return speed;
            		}
              `
      }

      var plane = new primitivePlaneShader({
        viewer: viewer,
        positions: positions,
        sts: sts,
        positionIndex: positionIndex,
      })
      viewer.scene.camera.setView({
        destination: new Cesium.Cartesian3.fromDegrees(110.2, 20.0, 500000),
      })
    </script>
  </body>
</html>

 

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Cesium中,您可以使用`CustomDataSource`和`CustomRenderPrimitive`来自定义渲染代码。 `CustomDataSource`是一种特殊类型的`DataSource`,它允许您在场景中添加自定义的实体和几何图形。您可以使用`CustomRenderPrimitive`在场景中添加自定义的渲染图元,每个渲染图元都可以实现自己的渲染逻辑。 以下是一个简单的示例,演示如何使用`CustomDataSource`和`CustomRenderPrimitive`来自定义渲染代码: ```javascript // 创建Cesium Viewer var viewer = new Cesium.Viewer('cesiumContainer'); // 创建自定义数据源 var customDataSource = new Cesium.CustomDataSource('custom'); // 添加自定义实体 var entity = customDataSource.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), billboard: { image: 'path/to/image.png', scale: 2.0 } }); viewer.dataSources.add(customDataSource); // 创建自定义渲染图元 var customPrimitive = new Cesium.CustomRenderPrimitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.RectangleGeometry({ rectangle: Cesium.Rectangle.fromDegrees(-75.0, 35.0, -125.0, 45.0) }), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED) } }), fragmentShaderSource: 'void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }', vertexShaderSource: 'attribute vec3 position3DHigh;\ attribute vec3 position3DLow;\ attribute vec4 color;\ varying vec4 v_color;\ void main() {\ vec4 position = czm_computePosition();\ gl_Position = czm_viewProjection * position;\ v_color = color;\ }', renderState: { blending: Cesium.BlendingState.DISABLED, depthTest: { enabled: true, func: Cesium.DepthFunction.LESS }, depthMask: true, polygonOffset: { enabled: false, factor: 0.0, units: 0.0 } } }); viewer.scene.primitives.add(customPrimitive); ``` 在上面的代码中,我们首先创建了一个Cesium Viewer,并创建了一个自定义数据源。然后,我们向自定义数据源中添加了一个自定义实体,并将其添加到场景中。接下来,我们创建了一个自定义渲染图元,并将其添加到场景中。在自定义渲染图元中,我们使用了自定义的顶点着色器和片段着色器,并设置了渲染状态。 请注意,上面的示例仅用于演示目的。实际应用中,您可能需要更复杂的渲染逻辑和着色器代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值