Shihui dev (#796)

* feat: add getModelMatrix into viewport

* feat: 新增地球模式 (初步构建)

* feat: 完善地球交互

* style: lint style

* feat: 调整地球图层缩放的方向

* style: lint style

* feat: 增加地球模式的 pointLayer/fill 图层

* style: lint style

* feat: 增加地球、太阳的简单运动系统,优化部分代码结构

* fix: 修复时间点击出错

* style: lint style

* fix: 修复地图 panBy 方法参数错误

* style: lint style

* feat: pointLayer/cylinder 圆柱兼容地球模式

* style: lint style

* feat: 修复 pointLayer/fill 在拾取是破面严重的情况

* style: lint style

* feat: 增加 arc 弧度调节

* feat: 增加 lineLayer/arc3d 兼容地球模式

* style: lint style

* feat: 增加地球图层 - 大气层

* style: lint style

* feat: 增加设置可视化层背景色的能力

* style: lint style

* feat: 增加地球外发光效果

* style: lint style

* feat: 允许用户不使用 layer 的 source 方法 - 地球模式下光晕图层不需要传数据

* style: lint style

* feat: 调整光晕的 shader 计算
This commit is contained in:
YiQianYao 2021-10-12 13:56:28 +08:00 committed by GitHub
parent cb792d4a77
commit b296595858
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 234 additions and 35 deletions

View File

@ -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,
};
}

View File

@ -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<IEarthLayerStyleOptions> {
public type: string = 'EarthLayer';

View File

@ -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';

View File

@ -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]];
},
},
});
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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));
}

View File

@ -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;

View File

@ -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',
},
};

View File

@ -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);
});
}