cesium移植shadertoy代码

版本:1.105之前,1.105使用了GLSL3.0语法,输出从gl_FragColor变为out_FragColor

GLSL2.0和3.0语法区别

  • attributevarying。 取而代之的是inout
  • 头文件多了个#version 300 es
  • 还有纹理 texture2Dtexture3D统统改为texture
  • 内置函数gl_FragColorgl_FragData删除,如果片段着色器要输出用out声明字段输出。不过保留了gl_Position
  • 还有的是layout的作用:可以直接指定位置

可以在primitive.appearance中的source写入shader代码

main函数也写在source

移植代码注意事项

  • main()函数替换为vec4 czm_getMaterial(vec2 vUv),且函数中声明uv:vec2 uv = vUv;
  • 原来的fragColor不再需要赋值,czm_getMaterial函数只需return值即可
  • iResolutionfragColor都替换为uv或者czm_viewport.zw
  • iTime直接传入uniform即可,也可直接使用cesium内置变量czm_frameNumber

vertexShaderSource和fragmentShaderSource

固定写法

ini 复制代码
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;
}
ini 复制代码
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;
}

示例代码

vue 复制代码
<template>
  <div id="cesium-container"></div>
</template>

<script setup>
  import { onMounted } from "vue";
  import * as Cesium from "cesium";

  const initEarth = () => {
    var viewer = new Cesium.Viewer("cesium-container");

    let inst = new Cesium.GeometryInstance({
      geometry: Cesium.BoxGeometry.createGeometry(
        new Cesium.BoxGeometry({
          vertexFormat: Cesium.VertexFormat.POSITION_NORMAL_AND_ST,
          maximum: new Cesium.Cartesian3(250000.0, 250000.0, 250000.0),
          minimum: new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0),
        })
      ),
    });

    // 自定义材质
    let aper = new Cesium.MaterialAppearance({
      material: new Cesium.Material({
        fabric: {
          uniforms: {
            iTime: 0,
          },
          source: `
        const int NUM_STEPS = 8;
      const float PI     = 3.141592;
      const float EPSILON  = 1e-3;
      //#define EPSILON_NRM (0.1 / iResolution.x)
      #define EPSILON_NRM (0.1 / 200.0)
      // sea
      const int ITER_GEOMETRY = 3;
      const int ITER_FRAGMENT = 5;
      const float SEA_HEIGHT = 0.6;
      const float SEA_CHOPPY = 4.0;
      const float SEA_SPEED = 1.8;
      const float SEA_FREQ = 0.16;
      const vec3 SEA_BASE = vec3(0.1,0.19,0.22);
      const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
      //#define SEA_TIME (1.0 + iTime * SEA_SPEED)
      const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
      // math
      mat3 fromEuler(vec3 ang) {
        vec2 a1 = vec2(sin(ang.x),cos(ang.x));
        vec2 a2 = vec2(sin(ang.y),cos(ang.y));
        vec2 a3 = vec2(sin(ang.z),cos(ang.z));
        mat3 m;
        m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
        m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
        m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
        return m;
        }
      float hash( vec2 p ) {
        float h = dot(p,vec2(127.1,311.7));
        return fract(sin(h)*43758.5453123);
        }
      float noise( in vec2 p ) {
        vec2 i = floor( p );
        vec2 f = fract( p );
        vec2 u = f*f*(3.0-2.0*f);
        return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
                 hash( i + vec2(1.0,0.0) ), u.x),
              mix( hash( i + vec2(0.0,1.0) ),
                 hash( i + vec2(1.0,1.0) ), u.x), u.y);
          }
      // lighting
      float diffuse(vec3 n,vec3 l,float p) {
        return pow(dot(n,l) * 0.4 + 0.6,p);
        }
      float specular(vec3 n,vec3 l,vec3 e,float s) {
        float nrm = (s + 8.0) / (PI * 8.0);
        return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
                }
      // sky
      vec3 getSkyColor(vec3 e) {
        e.y = max(e.y,0.0);
        return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4);
                }
      // sea
      float sea_octave(vec2 uv, float choppy) {
        uv += noise(uv);
        vec2 wv = 1.0-abs(sin(uv));
        vec2 swv = abs(cos(uv));
        wv = mix(wv,swv,wv);
        return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
            }
      float map(vec3 p) {
        float freq = SEA_FREQ;
        float amp = SEA_HEIGHT;
        float choppy = SEA_CHOPPY;
        vec2 uv = p.xz; uv.x *= 0.75;
        float d, h = 0.0;
        float SEA_TIME = 1.0 + iTime * SEA_SPEED;
        for(int i = 0; i < ITER_GEOMETRY; i++) {
          d = sea_octave((uv+SEA_TIME)*freq,choppy);
          d += sea_octave((uv-SEA_TIME)*freq,choppy);
          h += d * amp;
          uv *= octave_m; freq *= 1.9; amp *= 0.22;
          choppy = mix(choppy,1.0,0.2);
        }
        return p.y - h;
      }
      float map_detailed(vec3 p) {
        float freq = SEA_FREQ;
        float amp = SEA_HEIGHT;
        float choppy = SEA_CHOPPY;
        vec2 uv = p.xz; uv.x *= 0.75;
        float SEA_TIME = 1.0 + iTime * SEA_SPEED;
        float d, h = 0.0;
        for(int i = 0; i < ITER_FRAGMENT; i++) {
          d = sea_octave((uv+SEA_TIME)*freq,choppy);
          d += sea_octave((uv-SEA_TIME)*freq,choppy);
          h += d * amp;
          uv *= octave_m; freq *= 1.9; amp *= 0.22;
          choppy = mix(choppy,1.0,0.2);
        }
        return p.y - h;
      }
      vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
        float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0);
        fresnel = pow(fresnel,3.0) * 0.65;
        vec3 reflected = getSkyColor(reflect(eye,n));
        vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
        vec3 color = mix(refracted,reflected,fresnel);
        float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
        color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
        color += vec3(specular(n,l,eye,60.0));
        return color;
      }
      // tracing
      vec3 getNormal(vec3 p, float eps) {
        vec3 n;
        n.y = map_detailed(p);
        n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
        n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
        n.y = eps;
        return normalize(n);
      }
      float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
        float tm = 0.0;
        float tx = 1000.0;
        float hx = map(ori + dir * tx);
        if(hx > 0.0) return tx;
        float hm = map(ori + dir * tm);
        float tmid = 0.0;
        for(int i = 0; i < NUM_STEPS; i++) {
          tmid = mix(tm,tx, hm/(hm-hx));
          p = ori + dir * tmid;
          float hmid = map(p);
          if(hmid < 0.0) {
            tx = tmid;
            hx = hmid;
          } else {
            tm = tmid;
            hm = hmid;
          }
        }
        return tmid;
      }
           vec4 czm_getMaterial(vec2 vUv)
           {
            vec2 uv = vUv;
            uv = vUv * 2.0 - 1.0;
            float time = iTime * 0.3 + 0.0*0.01;
            // ray
            vec3 ang = vec3(0, 1.2, 0.0);
              vec3 ori = vec3(0.0,3.5,0);
            vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.15;
            dir = normalize(dir) * fromEuler(ang);
            // tracing
            vec3 p;
            heightMapTracing(ori,dir,p);
            vec3 dist = p - ori;
            vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
            vec3 light = normalize(vec3(0.0,1.0,0.8));
            // color
            vec3 color = mix(
              getSkyColor(dir),
              getSeaColor(p,n,light,dir,dist),
              pow(smoothstep(0.0,-0.05,dir.y),0.3));
               return vec4( pow(color,vec3(0.75)), 1.0 );
           }
        `,
      },
    }),
    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;
      }
    `,
  });

  let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
    Cesium.Cartesian3.fromDegrees(110, 40, 10)
  );

  viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: new Cesium.RectangleGeometry({
          rectangle: Cesium.Rectangle.fromDegrees(116, 39, 117, 39.7),
        }),
      }),
      appearance: aper,
      // vertexFormat: Cesium.VertexFormat.POSITION_NORMAL_AND_ST,
    })
  );

  viewer.camera.flyToBoundingSphere(
    new Cesium.BoundingSphere(
      Cesium.Cartesian3.fromDegrees(116, 39, 10),
      950000
    ),
    {
      duration: 0.1,
    }
  );

  function renderLoop(timestamp) {
    aper.material.uniforms.iTime = timestamp / 1000;
    requestAnimationFrame(renderLoop);
  }

  renderLoop();
};

onMounted(() => {
  initEarth();
});
</script>

<style scoped>
#cesium-container {
  width: 100%;
  height: 900px;
  margin: 0;
  position: relative;
}
</style>
相关推荐
用你的胜利博我一笑吧2 天前
vue3+ts+supermap iclient3d for cesium功能集合
前端·javascript·vue.js·3d·cesium·supermap
涛涛英语学不进去16 天前
3D Tiles的4x4的仿射变换矩阵
线性代数·3d·矩阵·cesium·3d tiles
GIS瞧葩菜16 天前
Cesium.ScreenSpaceEventHandler是 CesiumJS 中用于处理屏幕空间事件(如鼠标点击、移动、滚轮等)的工具
前端·javascript·cesium
BJ-Giser21 天前
cesium 水波纹扩散圆材质
前端·javascript·cesium
激动的兔子23 天前
使用Vue创建cesium项目模版该如何选择?
vue.js·cesium
BJ-Giser25 天前
Cesium 视频纹理
前端·javascript·cesium
BJ-Giser1 个月前
Cesium 视频投射
前端·javascript·cesium
柳晓黑胡椒1 个月前
cesium 实现批量divpoint气泡,及气泡碰撞测试与自动避让
cesium·divpoint·碰撞测试
undefined&&懒洋洋1 个月前
【Cesium】Cesium图层请求完成的回调
开发语言·前端·javascript·cesium
undefined&&懒洋洋1 个月前
Cesium倾斜相机视角观察物体
前端·gis·相机·cesium