diff --git a/packages/layers/src/core/triangulation.ts b/packages/layers/src/core/triangulation.ts index 5ad994618f..fe6875bbb1 100644 --- a/packages/layers/src/core/triangulation.ts +++ b/packages/layers/src/core/triangulation.ts @@ -5,6 +5,7 @@ import earcut from 'earcut'; import { mat4, vec3 } from 'gl-matrix'; import { EARTH_RADIUS, + EARTH_RADIUS_OUTER, EARTH_SEGMENTS, lglt2xyz, primitiveSphere, @@ -415,3 +416,16 @@ export function earthTriangulation() { normals: normalArr, }; } + +export function earthOuterTriangulation() { + const earthmesh = primitiveSphere(EARTH_RADIUS + EARTH_RADIUS_OUTER, { + segments: EARTH_SEGMENTS, + }); + const { positionsArr, indicesArr, normalArr } = earthmesh; + return { + vertices: positionsArr, + indices: indicesArr, + size: 5, + normals: normalArr, + }; +} diff --git a/packages/layers/src/earth/index.ts b/packages/layers/src/earth/index.ts index 6a442a9ff8..0824b1f8a2 100644 --- a/packages/layers/src/earth/index.ts +++ b/packages/layers/src/earth/index.ts @@ -1,19 +1,22 @@ import BaseLayer from '../core/BaseLayer'; import EarthAtomSphereModel from './models/atmosphere'; import BaseEarthModel from './models/base'; +import EarthBloomSphereModel from './models/bloomsphere'; interface IEarthLayerStyleOptions { + opacity: number; setEarthTime(time: number): void; } -export type EarthModelType = 'base' | 'atomSphere'; +export type EarthModelType = 'base' | 'atomSphere' | 'bloomSphere'; const EarthModels: { [key in EarthModelType]: any } = { base: BaseEarthModel, atomSphere: EarthAtomSphereModel, + bloomSphere: EarthBloomSphereModel, }; -const earthLayerTypes = ['base', 'atomSphere']; +const earthLayerTypes = ['base', 'atomSphere', 'bloomSphere']; export default class EarthLayer extends BaseLayer { public type: string = 'EarthLayer'; diff --git a/packages/layers/src/earth/models/atmosphere.ts b/packages/layers/src/earth/models/atmosphere.ts index d4caab29d0..e8a8e1e350 100644 --- a/packages/layers/src/earth/models/atmosphere.ts +++ b/packages/layers/src/earth/models/atmosphere.ts @@ -1,17 +1,13 @@ import { AttributeType, - BlendType, gl, IEncodeFeature, - ILayerConfig, IModel, IModelUniform, - ITexture2D, } from '@antv/l7-core'; -import { rgb2arr } from '@antv/l7-utils'; import { isNumber } from 'lodash'; -import BaseModel, { styleOffset, styleSingle } from '../../core/BaseModel'; +import BaseModel from '../../core/BaseModel'; import { earthTriangulation } from '../../core/triangulation'; import atmoSphereFrag from '../shaders/atmosphere_frag.glsl'; import atmoSphereVert from '../shaders/atmosphere_vert.glsl'; diff --git a/packages/layers/src/earth/models/bloomsphere.ts b/packages/layers/src/earth/models/bloomsphere.ts new file mode 100644 index 0000000000..0d20bd8f4f --- /dev/null +++ b/packages/layers/src/earth/models/bloomsphere.ts @@ -0,0 +1,126 @@ +import { + AttributeType, + gl, + IEncodeFeature, + IModel, + IModelUniform, +} from '@antv/l7-core'; +import { isNumber } from 'lodash'; + +import BaseModel from '../../core/BaseModel'; +import { earthOuterTriangulation } from '../../core/triangulation'; +import bloomSphereFrag from '../shaders/bloomsphere_frag.glsl'; +import bloomSphereVert from '../shaders/bloomsphere_vert.glsl'; +interface IBloomLayerStyleOptions { + opacity: number; +} + +export default class EarthBloomSphereModel extends BaseModel { + public getUninforms(): IModelUniform { + const { + opacity = 1, + } = this.layer.getLayerConfig() as IBloomLayerStyleOptions; + return { + u_opacity: isNumber(opacity) ? opacity : 1.0, + }; + } + + public initModels(): IModel[] { + return this.buildModels(); + } + + public clearModels() { + return ''; + } + + public buildModels(): IModel[] { + // TODO: 调整图层的绘制顺序,让它保持在地球后面(减少锯齿现象) + this.layer.zIndex = -999; + return [ + this.layer.buildLayerModel({ + moduleName: 'earthBloomSphere', + vertexShader: bloomSphereVert, + fragmentShader: bloomSphereFrag, + triangulation: earthOuterTriangulation, + depth: { + enable: false, + }, + blend: this.getBlend(), + }), + ]; + } + + protected registerBuiltinAttributes() { + // point layer size; + this.styleAttributeService.registerStyleAttribute({ + name: 'size', + type: AttributeType.Attribute, + descriptor: { + name: 'a_Size', + buffer: { + // give the WebGL driver a hint that this buffer may change + usage: gl.DYNAMIC_DRAW, + data: [], + type: gl.FLOAT, + }, + size: 1, + update: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + const { size = 1 } = feature; + return Array.isArray(size) ? [size[0]] : [size as number]; + }, + }, + }); + + this.styleAttributeService.registerStyleAttribute({ + name: 'normal', + type: AttributeType.Attribute, + descriptor: { + name: 'a_Normal', + buffer: { + // give the WebGL driver a hint that this buffer may change + usage: gl.STATIC_DRAW, + data: [], + type: gl.FLOAT, + }, + size: 3, + update: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + normal: number[], + ) => { + return normal; + }, + }, + }); + + this.styleAttributeService.registerStyleAttribute({ + name: 'uv', + type: AttributeType.Attribute, + descriptor: { + name: 'a_Uv', + buffer: { + // give the WebGL driver a hint that this buffer may change + usage: gl.DYNAMIC_DRAW, + data: [], + type: gl.FLOAT, + }, + size: 2, + update: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + return [vertex[3], vertex[4]]; + }, + }, + }); + } +} diff --git a/packages/layers/src/earth/shaders/atmosphere_frag.glsl b/packages/layers/src/earth/shaders/atmosphere_frag.glsl index 8ec223a3d7..1d288be36f 100644 --- a/packages/layers/src/earth/shaders/atmosphere_frag.glsl +++ b/packages/layers/src/earth/shaders/atmosphere_frag.glsl @@ -1,13 +1,15 @@ uniform float u_opacity; uniform vec3 u_CameraPosition; -varying vec3 vVertexNormal; +varying vec3 vVertexNormal; +varying float v_offset; varying vec4 v_Color; void main() { - - - float intensity = pow(0.5 + dot(normalize(vVertexNormal), normalize(u_CameraPosition)), 3.0); + + + // float intensity = pow(0.5 + dot(normalize(vVertexNormal), normalize(u_CameraPosition)), 3.0); + float intensity = pow(v_offset + dot(normalize(vVertexNormal), normalize(u_CameraPosition)), 3.0); // TODO: 去除背面 if(intensity > 1.0) intensity = 0.0; diff --git a/packages/layers/src/earth/shaders/atmosphere_vert.glsl b/packages/layers/src/earth/shaders/atmosphere_vert.glsl index 934a98ce01..e42667ceb6 100644 --- a/packages/layers/src/earth/shaders/atmosphere_vert.glsl +++ b/packages/layers/src/earth/shaders/atmosphere_vert.glsl @@ -4,16 +4,22 @@ attribute vec3 a_Normal; attribute vec2 a_Uv; attribute vec4 a_Color; uniform vec3 u_CameraPosition; +varying float v_CamreaDistance; + uniform mat4 u_ViewProjectionMatrix; uniform mat4 u_ModelMatrix; uniform mat4 u_ViewMatrix; varying vec3 vVertexNormal; varying vec4 v_Color; +varying float v_offset; void main() { + float EARTH_RADIUS = 100.0; + v_Color = a_Color; + v_offset = min(((length(u_CameraPosition) - EARTH_RADIUS)/600.0) * 0.5 + 0.4, 1.0); vVertexNormal = a_Normal; gl_Position = u_ViewProjectionMatrix * u_ModelMatrix * vec4(a_Position, 1.0); diff --git a/packages/layers/src/earth/shaders/bloomsphere_frag.glsl b/packages/layers/src/earth/shaders/bloomsphere_frag.glsl new file mode 100644 index 0000000000..ee8ad4e5d1 --- /dev/null +++ b/packages/layers/src/earth/shaders/bloomsphere_frag.glsl @@ -0,0 +1,15 @@ + +uniform float u_opacity; +uniform vec3 u_CameraPosition; +varying vec3 vVertexNormal; + +varying vec4 v_Color; +void main() { + + + float intensity = - dot(normalize(vVertexNormal), normalize(u_CameraPosition)); + // TODO: 去除背面 + if(intensity > 1.0) intensity = 0.0; + + gl_FragColor = vec4(v_Color.rgb, v_Color.a * intensity * u_opacity); +} diff --git a/packages/layers/src/earth/shaders/bloomsphere_vert.glsl b/packages/layers/src/earth/shaders/bloomsphere_vert.glsl new file mode 100644 index 0000000000..934a98ce01 --- /dev/null +++ b/packages/layers/src/earth/shaders/bloomsphere_vert.glsl @@ -0,0 +1,20 @@ + +attribute vec3 a_Position; +attribute vec3 a_Normal; +attribute vec2 a_Uv; +attribute vec4 a_Color; +uniform vec3 u_CameraPosition; +uniform mat4 u_ViewProjectionMatrix; +uniform mat4 u_ModelMatrix; +uniform mat4 u_ViewMatrix; + +varying vec3 vVertexNormal; +varying vec4 v_Color; + +void main() { + v_Color = a_Color; + + vVertexNormal = a_Normal; + + gl_Position = u_ViewProjectionMatrix * u_ModelMatrix * vec4(a_Position, 1.0); +} diff --git a/packages/layers/src/earth/utils.ts b/packages/layers/src/earth/utils.ts index 8de4a2f775..32ab8b2ad1 100644 --- a/packages/layers/src/earth/utils.ts +++ b/packages/layers/src/earth/utils.ts @@ -5,6 +5,8 @@ import { mat4, vec3 } from 'gl-matrix'; export const EARTH_RADIUS = 100; export const EARTH_SEGMENTS = 36; +export const EARTH_RADIUS_OUTER = 40; + /** * 角度转弧度 * @param deg diff --git a/packages/layers/src/plugins/DataSourcePlugin.ts b/packages/layers/src/plugins/DataSourcePlugin.ts index 8f8fed81bd..77d97be588 100644 --- a/packages/layers/src/plugins/DataSourcePlugin.ts +++ b/packages/layers/src/plugins/DataSourcePlugin.ts @@ -5,9 +5,8 @@ import { IMapService, TYPES, } from '@antv/l7-core'; -import Source from '@antv/l7-source'; +import Source, { DEFAULT_DATA, DEFAULT_PARSER } from '@antv/l7-source'; import { injectable } from 'inversify'; -import { cloneDeep } from 'lodash'; import 'reflect-metadata'; @injectable() @@ -18,7 +17,11 @@ export default class DataSourcePlugin implements ILayerPlugin { layer.hooks.init.tap('DataSourcePlugin', () => { const source = layer.getSource(); if (!source) { - const { data, options } = layer.sourceOption; + // TODO: 允许用户不使用 layer 的 source 方法,在这里传入一个默认的替换的默认数据 + const { data, options } = layer.sourceOption || { + data: DEFAULT_DATA, + options: DEFAULT_PARSER, + }; layer.setSource(new Source(data, options)); } diff --git a/packages/source/src/index.ts b/packages/source/src/index.ts index 4d8e363280..0d6b717615 100644 --- a/packages/source/src/index.ts +++ b/packages/source/src/index.ts @@ -2,7 +2,7 @@ import { registerParser, registerTransform } from './factory'; import csv from './parser/csv'; import geojson from './parser/geojson'; import image from './parser/image'; -import json from './parser/json'; +import json, { defaultData, defaultParser } from './parser/json'; import raster from './parser/raster'; import Source from './source'; import { cluster } from './transform/cluster'; @@ -31,3 +31,6 @@ export { } from './factory'; export * from './interface'; + +export const DEFAULT_DATA = defaultData; +export const DEFAULT_PARSER = defaultParser; diff --git a/packages/source/src/parser/json.ts b/packages/source/src/parser/json.ts index 3883d82a3c..97cb2d0894 100644 --- a/packages/source/src/parser/json.ts +++ b/packages/source/src/parser/json.ts @@ -47,3 +47,23 @@ export default function json(data: IJsonData, cfg: IParserCfg): IParserData { dataArray: resultData, }; } + +// TODO: 提供默认数据和解析器 +export const defaultData = [ + { + lng1: 100, + lat1: 30.0, + lng2: 130, + lat2: 30, + }, +]; + +export const defaultParser = { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, +}; diff --git a/stories/customMap/components/earth2.tsx b/stories/customMap/components/earth2.tsx index ab08969c2b..9b063e2b2a 100644 --- a/stories/customMap/components/earth2.tsx +++ b/stories/customMap/components/earth2.tsx @@ -122,29 +122,17 @@ export default class ScaleComponent extends React.Component { // earthlayer.setEarthTime(4.0) const atomLayer = new EarthLayer() - .source( - [ - { - lng1: 100, - lat1: 30.0, - lng2: 130, - lat2: 30, - }, - ], - { - parser: { - type: 'json', - x: 'lng1', - y: 'lat1', - x1: 'lng2', - y1: 'lat2', - }, - }, - ) .color('#2E8AE6') .shape('atomSphere') .style({ - opacity: 1.5, + opacity: 1, + }); + + const bloomLayer = new EarthLayer() + .color('#fff') + .shape('bloomSphere') + .style({ + opacity: 0.5, }); scene.on('loaded', () => { @@ -154,6 +142,7 @@ export default class ScaleComponent extends React.Component { // earthlayer.setEarthTime(4.0); scene.addLayer(atomLayer); + scene.addLayer(bloomLayer); scene.addLayer(lineLayer); }); }