Cesium全球海洋水纹波浪效果-自定义材质

在这里插入图片描述
在这里插入图片描述源码:

<template>
    <div id="cesiumContainer">
    </div>
</template>

<script setup>
import { onMounted } from "vue";

let viewer, globe;

const reset = () => {
    let baseLayer = viewer.scene.imageryLayers.get(0);
    globe.showGroundAtmosphere = true;
    globe.baseColor = Cesium.Color.BLUE;
    globe.translucency.enabled = false;
    globe.translucency.frontFaceAlpha = 1.0;
    globe.translucency.rectangle = undefined;
    globe.undergroundColor = Cesium.Color.BLACK;
    baseLayer.colorToAlpha = undefined;
}

const loadWaterEntity = () => {
    let baseLayer = viewer.scene.imageryLayers.get(0);
    globe.showGroundAtmosphere = false;
    globe.baseColor = Cesium.Color.TRANSPARENT;
    globe.translucency.enabled = true;
    globe.undergroundColor = undefined;

    baseLayer.colorToAlpha = new Cesium.Color(0.0, 0.016, 0.059);
    baseLayer.colorToAlphaThreshold = 0.2;

    const mantleRadius = 6300000.0;
    const sphere = new Cesium.SphereGeometry({
        radius: mantleRadius,
        vertexFormat: Cesium.VertexFormat.POSITION_NORMAL_AND_ST
    });
    const geometry = Cesium.SphereGeometry.createGeometry(sphere);
    let inst = new Cesium.GeometryInstance({
        geometry: geometry
    });
    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: `
            in vec3 position3DHigh;
            in vec3 position3DLow;
            in float batchId;
            in vec2 st;
            in vec3 normal;
            out vec2 v_st;
            out vec3 v_positionEC;
            out 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: `
            in vec2 v_st;
            in vec3 v_positionEC;
            in 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);
                out_FragColor = color;
            }
        `,
    });
    viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: inst,
        appearance: aper,
        asynchronous: false,
    }));
    const renderLoop = (timestamp) => {
        aper.material.uniforms.iTime = timestamp / 1000;
        requestAnimationFrame(renderLoop);
    }
    renderLoop();
}

onMounted(() => {
    viewer = new Cesium.Viewer("cesiumContainer", {
        orderIndependentTranslucency: false
    });
    globe = viewer.scene.globe;
    loadWaterEntity();
})
</script>

<style scoped></style>

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您想了解有关自定义几何体的内容,我很乐意为您解答。首先,让我们了解一下什么是几何体。 在Cesium中,几何体是由一些点、线和三角形组成的图形。几何体可以在地球上显示各种形状的物体,如建筑、飞机、汽车等。Cesium提供了一些内置的几何体,如BoxGeometry、CylinderGeometry、SphereGeometry等,但是有时候我们需要展示一些特殊形状的物体,这时候就需要自定义几何体了。 下面是一个简单的自定义几何体的例子: ```javascript var geometry = new Cesium.Geometry({ attributes: { position: new Cesium.GeometryAttribute({ componentDatatype: Cesium.ComponentDatatype.DOUBLE, componentsPerAttribute: 3, values: new Float64Array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 ]) }) }, indices: new Uint16Array([ 0, 1, 2, 0, 2, 3 ]), primitiveType: Cesium.PrimitiveType.TRIANGLES }); ``` 这个例子中,我们创建了一个由四个点组成的矩形,并用这些点的索引定义了两个三角形。这个几何体可以用来在地球上显示一个矩形。 接下来,让我们逐步了解这个例子中的代码。首先是Cesium.GeometryAttribute。 Cesium.GeometryAttribute是几何体属性的容器。在这个例子中,我们定义了一个名为position的属性,它有三个分量:x、y和z。这个属性使用的数据类型是Cesium.ComponentDatatype.DOUBLE,表示每个分量有一个双精度浮点数。componentsPerAttribute表示每个属性有几个分量。在这个例子中,每个属性都有三个分量。最后,我们用一个Float64Array数组来定义这个属性的值。 接下来是indices,它定义了几何体使用哪些点来组成三角形。在这个例子中,我们定义了两个三角形,每个三角形使用三个顶点。在indices数组中,我们用顶点在attributes数组中的索引来定义每个三角形。 最后,我们定义了几何体的primitiveType,它表示几何体的类型。在这个例子中,我们使用的是三角形类型,所以primitiveType为Cesium.PrimitiveType.TRIANGLES。 希望这个例子可以帮助您更好地理解自定义几何体的实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值