mirror of https://gitee.com/antv-l7/antv-l7
feat: 去除 style 更新时 options 的更新、earth 图层解耦 (#1232)
* feat: 在点图层中去除 global 的耦合 * style: lint style * fix: 修复更新 style 的同时更新了 option 带来的问题 * style: lint style * feat: 拆除 arc3d 地球模式和普通模式的耦合 * style: lint style
This commit is contained in:
parent
0a9ad6c6f7
commit
c2812205c5
|
@ -246,9 +246,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
|||
public updateLayerConfig(
|
||||
configToUpdate: Partial<ILayerConfig | ChildLayerStyleOptions>,
|
||||
) {
|
||||
// 同步 options 记录
|
||||
this.updateRawConfig(configToUpdate);
|
||||
|
||||
if (!this.inited) {
|
||||
this.needUpdateConfig = {
|
||||
...this.needUpdateConfig,
|
||||
|
@ -638,12 +635,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
|||
);
|
||||
}
|
||||
|
||||
this.rawConfig = {
|
||||
...this.rawConfig,
|
||||
...rest,
|
||||
};
|
||||
// this.rawConfig = {
|
||||
// ...this.rawConfig,
|
||||
// ...rest,
|
||||
// };
|
||||
if (this.container) {
|
||||
this.updateLayerConfig(this.rawConfig);
|
||||
// this.updateLayerConfig(this.rawConfig);
|
||||
this.updateLayerConfig(rest);
|
||||
this.styleNeedUpdate = true;
|
||||
}
|
||||
|
||||
|
@ -1315,18 +1313,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
|||
return {};
|
||||
}
|
||||
|
||||
private updateRawConfig(
|
||||
configToUpdate: Partial<ILayerConfig | ChildLayerStyleOptions>,
|
||||
) {
|
||||
Object.keys(configToUpdate).map((key) => {
|
||||
// @ts-ignore
|
||||
if (this.rawConfig[key] && this.rawConfig[key] !== configToUpdate[key]) {
|
||||
// @ts-ignore
|
||||
this.rawConfig[key] = configToUpdate[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private sourceEvent = () => {
|
||||
this.dataState.dataSourceNeedUpdate = true;
|
||||
const { autoFit, fitBoundsOptions } = this.getLayerConfig();
|
||||
|
|
|
@ -39,10 +39,14 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
|
|||
vectorline: {},
|
||||
tileLine: {},
|
||||
halfLine: {},
|
||||
earthArc3d: {},
|
||||
};
|
||||
return defaultConfig[type];
|
||||
}
|
||||
protected getModelType(): LineModelType {
|
||||
if (this.layerType) {
|
||||
return this.layerType as LineModelType;
|
||||
}
|
||||
if (this.layerSource.parser.type === 'mvt') {
|
||||
return 'vectorline';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IAnimateOption,
|
||||
IEncodeFeature,
|
||||
ILayerConfig,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
ITexture2D,
|
||||
} from '@antv/l7-core';
|
||||
import { getMask, rgb2arr } from '@antv/l7-utils';
|
||||
import { isNumber } from 'lodash';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { ILineLayerStyleOptions } from '../../core/interface';
|
||||
import { LineArcTriangulation } from '../../core/triangulation';
|
||||
import { EARTH_RADIUS } from '../../earth/utils';
|
||||
// arc3d line layer
|
||||
import arc3d_line_frag from '../shaders/line_arc_3d_frag.glsl';
|
||||
import arc3d_line_vert from '../shaders/line_arc_3d_vert.glsl';
|
||||
// arc3d linear layer
|
||||
import arc3d_linear_frag from '../shaders/linear/arc3d_linear_frag.glsl';
|
||||
import arc3d_linear_vert from '../shaders/linear/arc3d_linear_vert.glsl';
|
||||
|
||||
const lineStyleObj: { [key: string]: number } = {
|
||||
solid: 0.0,
|
||||
dash: 1.0,
|
||||
};
|
||||
export default class Arc3DModel extends BaseModel {
|
||||
protected texture: ITexture2D;
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity = 1,
|
||||
sourceColor,
|
||||
targetColor,
|
||||
textureBlend = 'normal',
|
||||
lineType = 'solid',
|
||||
dashArray = [10, 5],
|
||||
lineTexture = false,
|
||||
iconStep = 100,
|
||||
segmentNumber = 30,
|
||||
globalArcHeight = 10,
|
||||
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
|
||||
|
||||
if (dashArray.length === 2) {
|
||||
dashArray.push(0, 0);
|
||||
}
|
||||
|
||||
// 转化渐变色
|
||||
let useLinearColor = 0; // 默认不生效
|
||||
let sourceColorArr = [0, 0, 0, 0];
|
||||
let targetColorArr = [0, 0, 0, 0];
|
||||
if (sourceColor && targetColor) {
|
||||
sourceColorArr = rgb2arr(sourceColor);
|
||||
targetColorArr = rgb2arr(targetColor);
|
||||
useLinearColor = 1;
|
||||
}
|
||||
|
||||
if (this.rendererService.getDirty()) {
|
||||
this.texture.bind();
|
||||
}
|
||||
|
||||
if (this.dataTextureTest && this.dataTextureNeedUpdate({ opacity })) {
|
||||
this.judgeStyleAttributes({ opacity });
|
||||
const encodeData = this.layer.getEncodedData();
|
||||
const { data, width, height } = this.calDataFrame(
|
||||
this.cellLength,
|
||||
encodeData,
|
||||
this.cellProperties,
|
||||
);
|
||||
this.rowCount = height; // 当前数据纹理有多少行
|
||||
|
||||
this.dataTexture =
|
||||
this.cellLength > 0 && data.length > 0
|
||||
? this.createTexture2D({
|
||||
flipY: true,
|
||||
data,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
: this.createTexture2D({
|
||||
flipY: true,
|
||||
data: [1],
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
u_globel: this.mapService.version === 'GLOBEL' ? 1 : 0,
|
||||
u_globel_radius: EARTH_RADIUS, // 地球半径
|
||||
u_global_height: globalArcHeight,
|
||||
|
||||
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
|
||||
u_cellTypeLayout: this.getCellTypeLayout(),
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
u_textureBlend: textureBlend === 'normal' ? 0.0 : 1.0,
|
||||
segmentNumber,
|
||||
u_line_type: lineStyleObj[lineType as string] || 0.0,
|
||||
u_dash_array: dashArray,
|
||||
|
||||
// 纹理支持参数
|
||||
u_texture: this.texture, // 贴图
|
||||
u_line_texture: lineTexture ? 1.0 : 0.0, // 传入线的标识
|
||||
u_icon_step: iconStep,
|
||||
u_textSize: [1024, this.iconService.canvasHeight || 128],
|
||||
|
||||
// 渐变色支持参数
|
||||
u_linearColor: useLinearColor,
|
||||
u_sourceColor: sourceColorArr,
|
||||
u_targetColor: targetColorArr,
|
||||
};
|
||||
}
|
||||
|
||||
public getAnimateUniforms(): IModelUniform {
|
||||
const { animateOption } = this.layer.getLayerConfig() as ILayerConfig;
|
||||
return {
|
||||
u_aimate: this.animateOption2Array(animateOption as IAnimateOption),
|
||||
u_time: this.layer.getLayerAnimateTime(),
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
this.updateTexture();
|
||||
this.iconService.on('imageUpdate', this.updateTexture);
|
||||
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
this.texture?.destroy();
|
||||
this.dataTexture?.destroy();
|
||||
this.iconService.off('imageUpdate', this.updateTexture);
|
||||
}
|
||||
|
||||
public getShaders(): { frag: string; vert: string; type: string } {
|
||||
const {
|
||||
sourceColor,
|
||||
targetColor,
|
||||
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
|
||||
|
||||
if (sourceColor && targetColor) {
|
||||
// 分离 linear 功能
|
||||
return {
|
||||
frag: arc3d_linear_frag,
|
||||
vert: arc3d_linear_vert,
|
||||
type: 'linear',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
frag: arc3d_line_frag,
|
||||
vert: arc3d_line_vert,
|
||||
type: 'normal',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
const {
|
||||
segmentNumber = 30,
|
||||
mask = false,
|
||||
maskInside = true,
|
||||
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
|
||||
const { frag, vert, type } = this.getShaders();
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'arc3Dline' + type,
|
||||
vertexShader: vert,
|
||||
fragmentShader: frag,
|
||||
triangulation: LineArcTriangulation,
|
||||
blend: this.getBlend(),
|
||||
segmentNumber,
|
||||
// primitive: gl.POINTS,
|
||||
stencil: getMask(mask, maskInside),
|
||||
}),
|
||||
];
|
||||
}
|
||||
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: 'instance', // 弧线起始点信息
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Instance',
|
||||
buffer: {
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 4,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
return [vertex[3], vertex[4], vertex[5], vertex[6]];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'uv',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_iconMapUV',
|
||||
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,
|
||||
) => {
|
||||
const iconMap = this.iconService.getIconMap();
|
||||
const { texture } = feature;
|
||||
const { x, y } = iconMap[texture as string] || { x: 0, y: 0 };
|
||||
return [x, y];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private updateTexture = () => {
|
||||
const { createTexture2D } = this.rendererService;
|
||||
if (this.texture) {
|
||||
this.texture.update({
|
||||
data: this.iconService.getCanvas(),
|
||||
});
|
||||
this.layer.render();
|
||||
return;
|
||||
}
|
||||
this.texture = createTexture2D({
|
||||
data: this.iconService.getCanvas(),
|
||||
mag: gl.NEAREST,
|
||||
min: gl.NEAREST,
|
||||
premultiplyAlpha: false,
|
||||
width: 1024,
|
||||
height: this.iconService.canvasHeight || 128,
|
||||
});
|
||||
};
|
||||
}
|
|
@ -2,6 +2,7 @@ import LineTileModel from '../../tile/models/tileModel';
|
|||
import ArcModel from './arc';
|
||||
import Arc3DModel from './arc_3d';
|
||||
import ArcMiniModel from './arcmini';
|
||||
import EarthArc3DModel from './earthArc_3d';
|
||||
import GreatCircleModel from './great_circle';
|
||||
import LineHalfModel from './half';
|
||||
import LineModel from './line';
|
||||
|
@ -21,7 +22,8 @@ export type LineModelType =
|
|||
| 'halfLine'
|
||||
| 'linearline'
|
||||
| 'vectorline'
|
||||
| 'tileLine';
|
||||
| 'tileLine'
|
||||
| 'earthArc3d';
|
||||
|
||||
const LineModels: { [key in LineModelType]: any } = {
|
||||
arc: ArcModel,
|
||||
|
@ -35,6 +37,7 @@ const LineModels: { [key in LineModelType]: any } = {
|
|||
linearline: LinearLine,
|
||||
vectorline: LineTileModel,
|
||||
tileLine: TileLineModel,
|
||||
earthArc3d: EarthArc3DModel,
|
||||
};
|
||||
|
||||
export default LineModels;
|
||||
|
|
|
@ -68,6 +68,8 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
},
|
||||
vectorpoint: {},
|
||||
tile: {},
|
||||
earthFill: {},
|
||||
earthExtrude: {},
|
||||
};
|
||||
return defaultConfig[type];
|
||||
}
|
||||
|
@ -85,6 +87,8 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
'icon',
|
||||
'vectorpoint',
|
||||
'tile',
|
||||
'earthFill',
|
||||
'earthExtrude',
|
||||
];
|
||||
if (this.layerSource.parser.type === 'mvt') {
|
||||
return 'vectorpoint';
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
ILayerConfig,
|
||||
IModel,
|
||||
} from '@antv/l7-core';
|
||||
import { getCullFace, rgb2arr } from '@antv/l7-utils';
|
||||
import { isNumber } from 'lodash';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { IPointLayerStyleOptions } from '../../core/interface';
|
||||
import { PointExtrudeTriangulation } from '../../core/triangulation';
|
||||
import { lglt2xyz } from '../../earth/utils';
|
||||
import { calculateCentroid } from '../../utils/geo';
|
||||
import pointExtrudeFrag from '../shaders/earth/extrude/extrude_frag.glsl';
|
||||
import pointExtrudeVert from '../shaders/earth/extrude/extrude_vert.glsl';
|
||||
|
||||
export default class ExtrudeModel extends BaseModel {
|
||||
private raiseCount: number = 0;
|
||||
private raiserepeat: number = 0;
|
||||
public getUninforms() {
|
||||
const {
|
||||
animateOption = {
|
||||
enable: false,
|
||||
speed: 0.01,
|
||||
repeat: false,
|
||||
},
|
||||
opacity = 1,
|
||||
|
||||
sourceColor,
|
||||
targetColor,
|
||||
|
||||
pickLight = false,
|
||||
heightfixed = false,
|
||||
|
||||
opacityLinear = {
|
||||
enable: false,
|
||||
dir: 'up',
|
||||
},
|
||||
|
||||
lightEnable = true,
|
||||
} = this.layer.getLayerConfig() as Partial<
|
||||
ILayerConfig & IPointLayerStyleOptions
|
||||
>;
|
||||
if (
|
||||
this.dataTextureTest &&
|
||||
this.dataTextureNeedUpdate({
|
||||
opacity,
|
||||
})
|
||||
) {
|
||||
this.judgeStyleAttributes({
|
||||
opacity,
|
||||
});
|
||||
const encodeData = this.layer.getEncodedData();
|
||||
const { data, width, height } = this.calDataFrame(
|
||||
this.cellLength,
|
||||
encodeData,
|
||||
this.cellProperties,
|
||||
);
|
||||
this.rowCount = height; // 当前数据纹理有多少行
|
||||
|
||||
this.dataTexture =
|
||||
this.cellLength > 0 && data.length > 0
|
||||
? this.createTexture2D({
|
||||
flipY: true,
|
||||
data,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
: this.createTexture2D({
|
||||
flipY: true,
|
||||
data: [1],
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
}
|
||||
|
||||
// 转化渐变色
|
||||
let useLinearColor = 0; // 默认不生效
|
||||
let sourceColorArr = [0, 0, 0, 0];
|
||||
let targetColorArr = [0, 0, 0, 0];
|
||||
if (sourceColor && targetColor) {
|
||||
sourceColorArr = rgb2arr(sourceColor);
|
||||
targetColorArr = rgb2arr(targetColor);
|
||||
useLinearColor = 1;
|
||||
}
|
||||
|
||||
if (this.raiseCount < 1 && this.raiserepeat > 0) {
|
||||
if (animateOption.enable) {
|
||||
const { speed = 0.01, repeat = false } = animateOption;
|
||||
this.raiseCount += speed;
|
||||
if (this.raiseCount >= 1) {
|
||||
if (this.raiserepeat > 1) {
|
||||
this.raiseCount = 0;
|
||||
this.raiserepeat--;
|
||||
} else {
|
||||
this.raiseCount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// 圆柱体的拾取高亮是否要计算光照
|
||||
u_pickLight: Number(pickLight),
|
||||
// 圆柱体是否固定高度
|
||||
u_heightfixed: Number(heightfixed),
|
||||
|
||||
u_r: animateOption.enable && this.raiserepeat > 0 ? this.raiseCount : 1.0,
|
||||
|
||||
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
|
||||
u_cellTypeLayout: this.getCellTypeLayout(),
|
||||
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
|
||||
// 渐变色支持参数
|
||||
u_linearColor: useLinearColor,
|
||||
u_sourceColor: sourceColorArr,
|
||||
u_targetColor: targetColorArr,
|
||||
|
||||
// 透明度渐变
|
||||
u_opacitylinear: Number(opacityLinear.enable),
|
||||
u_opacitylinear_dir: opacityLinear.dir === 'up' ? 1.0 : 0.0,
|
||||
|
||||
// 光照计算开关
|
||||
u_lightEnable: Number(lightEnable),
|
||||
};
|
||||
}
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
// GAODE1.x GAODE2.x MAPBOX
|
||||
const {
|
||||
depth = true,
|
||||
animateOption: { repeat = 1 },
|
||||
} = this.layer.getLayerConfig() as ILayerConfig;
|
||||
this.raiserepeat = repeat;
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'pointExtrude2',
|
||||
vertexShader: pointExtrudeVert,
|
||||
fragmentShader: pointExtrudeFrag,
|
||||
triangulation: PointExtrudeTriangulation,
|
||||
blend: this.getBlend(),
|
||||
cull: {
|
||||
enable: true,
|
||||
face: getCullFace(this.mapService.version),
|
||||
},
|
||||
depth: {
|
||||
enable: depth,
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
public clearModels() {
|
||||
this.dataTexture?.destroy();
|
||||
}
|
||||
protected registerBuiltinAttributes() {
|
||||
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
|
||||
const isGlobel = this.mapService.version === 'GLOBEL';
|
||||
// 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: 3,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const { size } = feature;
|
||||
if (size) {
|
||||
let buffersize: number[] = [];
|
||||
if (Array.isArray(size)) {
|
||||
buffersize =
|
||||
size.length === 2 ? [size[0], size[0], size[1]] : size;
|
||||
}
|
||||
if (!Array.isArray(size)) {
|
||||
buffersize = [size, size, size];
|
||||
}
|
||||
return buffersize;
|
||||
} else {
|
||||
return [2, 2, 2];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// point layer size;
|
||||
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: 'pos',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Pos',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
update: (feature: IEncodeFeature, featureIdx: number) => {
|
||||
const coordinates = calculateCentroid(feature.coordinates);
|
||||
if (isGlobel) {
|
||||
// TODO: 在地球模式下需要将传入 shader 的经纬度转化成对应的 xyz 坐标
|
||||
return lglt2xyz([coordinates[0], coordinates[1]]) as [
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
];
|
||||
} else {
|
||||
return [coordinates[0], coordinates[1], 0];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IAnimateOption,
|
||||
IEncodeFeature,
|
||||
ILayerConfig,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
import { isNumber } from 'lodash';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { IPointLayerStyleOptions } from '../../core/interface';
|
||||
import { GlobelPointFillTriangulation } from '../../core/triangulation';
|
||||
|
||||
import pointFillFrag from '../shaders/earth/fill_frag.glsl';
|
||||
import pointFillVert from '../shaders/earth/fill_vert.glsl';
|
||||
|
||||
import { mat4, vec3 } from 'gl-matrix';
|
||||
export default class FillModel extends BaseModel {
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity = 1,
|
||||
strokeOpacity = 1,
|
||||
strokeWidth = 0,
|
||||
stroke = 'rgba(0,0,0,0)',
|
||||
offsets = [0, 0],
|
||||
blend,
|
||||
blur = 0,
|
||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||
if (
|
||||
this.dataTextureTest &&
|
||||
this.dataTextureNeedUpdate({
|
||||
opacity,
|
||||
strokeOpacity,
|
||||
strokeWidth,
|
||||
stroke,
|
||||
offsets,
|
||||
})
|
||||
) {
|
||||
// 判断当前的样式中哪些是需要进行数据映射的,哪些是常量,同时计算用于构建数据纹理的一些中间变量
|
||||
this.judgeStyleAttributes({
|
||||
opacity,
|
||||
strokeOpacity,
|
||||
strokeWidth,
|
||||
stroke,
|
||||
offsets,
|
||||
});
|
||||
|
||||
const encodeData = this.layer.getEncodedData();
|
||||
const { data, width, height } = this.calDataFrame(
|
||||
this.cellLength,
|
||||
encodeData,
|
||||
this.cellProperties,
|
||||
);
|
||||
this.rowCount = height; // 当前数据纹理有多少行
|
||||
|
||||
this.dataTexture =
|
||||
this.cellLength > 0 && data.length > 0
|
||||
? this.createTexture2D({
|
||||
flipY: true,
|
||||
data,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
: this.createTexture2D({
|
||||
flipY: true,
|
||||
data: [1],
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
}
|
||||
return {
|
||||
u_blur: blur,
|
||||
|
||||
u_additive: blend === 'additive' ? 1.0 : 0.0,
|
||||
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
|
||||
u_cellTypeLayout: this.getCellTypeLayout(),
|
||||
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
u_stroke_opacity: isNumber(strokeOpacity) ? strokeOpacity : 1.0,
|
||||
u_stroke_width: isNumber(strokeWidth) ? strokeWidth : 1.0,
|
||||
u_stroke_color: this.getStrokeColor(stroke),
|
||||
u_offsets: this.isOffsetStatic(offsets)
|
||||
? (offsets as [number, number])
|
||||
: [0, 0],
|
||||
};
|
||||
}
|
||||
public getAnimateUniforms(): IModelUniform {
|
||||
const {
|
||||
animateOption = { enable: false },
|
||||
} = this.layer.getLayerConfig() as ILayerConfig;
|
||||
return {
|
||||
u_aimate: this.animateOption2Array(animateOption),
|
||||
u_time: this.layer.getLayerAnimateTime(),
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
const { frag, vert, type } = this.getShaders();
|
||||
this.layer.triangulation = GlobelPointFillTriangulation;
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'pointfill_' + type,
|
||||
vertexShader: vert,
|
||||
fragmentShader: frag,
|
||||
triangulation: GlobelPointFillTriangulation,
|
||||
depth: { enable: true },
|
||||
blend: this.getBlend(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 animateOption 的值返回对应的 shader 代码
|
||||
* @returns
|
||||
*/
|
||||
public getShaders(): { frag: string; vert: string; type: string } {
|
||||
return {
|
||||
frag: pointFillFrag,
|
||||
vert: pointFillVert,
|
||||
type: 'point_earth_fill',
|
||||
};
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
this.dataTexture?.destroy();
|
||||
}
|
||||
|
||||
// overwrite baseModel func
|
||||
protected animateOption2Array(option: Partial<IAnimateOption>): number[] {
|
||||
return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0];
|
||||
}
|
||||
protected registerBuiltinAttributes() {
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'extrude',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Extrude',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const [x, y, z] = vertex;
|
||||
const n1 = vec3.fromValues(0, 0, 1);
|
||||
const n2 = vec3.fromValues(x, 0, z);
|
||||
|
||||
const xzReg =
|
||||
x >= 0 ? vec3.angle(n1, n2) : Math.PI * 2 - vec3.angle(n1, n2);
|
||||
|
||||
const yReg = Math.PI * 2 - Math.asin(y / 100);
|
||||
|
||||
const m = mat4.create();
|
||||
mat4.rotateY(m, m, xzReg);
|
||||
mat4.rotateX(m, m, yReg);
|
||||
|
||||
const v1 = vec3.fromValues(1, 1, 0);
|
||||
vec3.transformMat4(v1, v1, m);
|
||||
vec3.normalize(v1, v1);
|
||||
|
||||
const v2 = vec3.fromValues(-1, 1, 0);
|
||||
vec3.transformMat4(v2, v2, m);
|
||||
vec3.normalize(v2, v2);
|
||||
|
||||
const v3 = vec3.fromValues(-1, -1, 0);
|
||||
vec3.transformMat4(v3, v3, m);
|
||||
vec3.normalize(v3, v3);
|
||||
|
||||
const v4 = vec3.fromValues(1, -1, 0);
|
||||
vec3.transformMat4(v4, v4, m);
|
||||
vec3.normalize(v4, v4);
|
||||
|
||||
const extrude = [...v1, ...v2, ...v3, ...v4];
|
||||
const extrudeIndex = (attributeIdx % 4) * 3;
|
||||
return [
|
||||
extrude[extrudeIndex],
|
||||
extrude[extrudeIndex + 1],
|
||||
extrude[extrudeIndex + 2],
|
||||
];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 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 = 5 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'shape',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Shape',
|
||||
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 { shape = 2 } = feature;
|
||||
const shape2d = this.layer.getLayerConfig().shape2d as string[];
|
||||
const shapeIndex = shape2d.indexOf(shape as string);
|
||||
return [shapeIndex];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -111,8 +111,6 @@ export default class ExtrudeModel extends BaseModel {
|
|||
u_heightfixed: Number(heightfixed),
|
||||
|
||||
u_r: animateOption.enable && this.raiserepeat > 0 ? this.raiseCount : 1.0,
|
||||
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
|
||||
u_globel: this.mapService.version === 'GLOBEL' ? 1 : 0,
|
||||
|
||||
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
|
||||
u_cellTypeLayout: this.getCellTypeLayout(),
|
||||
|
|
|
@ -9,14 +9,11 @@ import {
|
|||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
import { $window, getCullFace, getMask } from '@antv/l7-utils';
|
||||
import { $window, getMask } from '@antv/l7-utils';
|
||||
import { isNumber } from 'lodash';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { IPointLayerStyleOptions } from '../../core/interface';
|
||||
import {
|
||||
GlobelPointFillTriangulation,
|
||||
PointFillTriangulation,
|
||||
} from '../../core/triangulation';
|
||||
import { PointFillTriangulation } from '../../core/triangulation';
|
||||
// animate pointLayer shader - support animate
|
||||
import waveFillFrag from '../shaders/animate/wave_frag.glsl';
|
||||
// static pointLayer shader - not support animate
|
||||
|
@ -24,7 +21,6 @@ import pointFillFrag from '../shaders/fill_frag.glsl';
|
|||
import pointFillVert from '../shaders/fill_vert.glsl';
|
||||
|
||||
import { Version } from '@antv/l7-maps';
|
||||
import { mat4, vec3 } from 'gl-matrix';
|
||||
export default class FillModel extends BaseModel {
|
||||
private meter2coord: number = 1;
|
||||
private meteryScale: number = 1; // 兼容 mapbox
|
||||
|
@ -100,7 +96,6 @@ export default class FillModel extends BaseModel {
|
|||
u_blur: blur,
|
||||
|
||||
u_additive: blend === 'additive' ? 1.0 : 0.0,
|
||||
u_globel: this.mapService.version === Version.GLOBEL ? 1 : 0,
|
||||
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
|
||||
u_cellTypeLayout: this.getCellTypeLayout(),
|
||||
|
||||
|
@ -201,20 +196,14 @@ export default class FillModel extends BaseModel {
|
|||
>;
|
||||
const { frag, vert, type } = this.getShaders(animateOption);
|
||||
|
||||
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
|
||||
const isGlobel = this.mapService.version === 'GLOBEL';
|
||||
this.layer.triangulation = isGlobel
|
||||
? GlobelPointFillTriangulation
|
||||
: PointFillTriangulation;
|
||||
this.layer.triangulation = PointFillTriangulation;
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'pointfill_' + type,
|
||||
vertexShader: vert,
|
||||
fragmentShader: frag,
|
||||
triangulation: isGlobel
|
||||
? GlobelPointFillTriangulation
|
||||
: PointFillTriangulation,
|
||||
depth: { enable: isGlobel },
|
||||
triangulation: PointFillTriangulation,
|
||||
depth: { enable: false },
|
||||
blend: this.getBlend(),
|
||||
stencil: getMask(mask, maskInside),
|
||||
}),
|
||||
|
@ -261,9 +250,6 @@ export default class FillModel extends BaseModel {
|
|||
return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0];
|
||||
}
|
||||
protected registerBuiltinAttributes() {
|
||||
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
|
||||
const isGlobel = this.mapService.version === 'GLOBEL';
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'extrude',
|
||||
type: AttributeType.Attribute,
|
||||
|
@ -282,44 +268,7 @@ export default class FillModel extends BaseModel {
|
|||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
let extrude;
|
||||
// 地球模式
|
||||
if (isGlobel) {
|
||||
const [x, y, z] = vertex;
|
||||
const n1 = vec3.fromValues(0, 0, 1);
|
||||
const n2 = vec3.fromValues(x, 0, z);
|
||||
|
||||
const xzReg =
|
||||
x >= 0 ? vec3.angle(n1, n2) : Math.PI * 2 - vec3.angle(n1, n2);
|
||||
|
||||
const yReg = Math.PI * 2 - Math.asin(y / 100);
|
||||
|
||||
const m = mat4.create();
|
||||
mat4.rotateY(m, m, xzReg);
|
||||
mat4.rotateX(m, m, yReg);
|
||||
|
||||
const v1 = vec3.fromValues(1, 1, 0);
|
||||
vec3.transformMat4(v1, v1, m);
|
||||
vec3.normalize(v1, v1);
|
||||
|
||||
const v2 = vec3.fromValues(-1, 1, 0);
|
||||
vec3.transformMat4(v2, v2, m);
|
||||
vec3.normalize(v2, v2);
|
||||
|
||||
const v3 = vec3.fromValues(-1, -1, 0);
|
||||
vec3.transformMat4(v3, v3, m);
|
||||
vec3.normalize(v3, v3);
|
||||
|
||||
const v4 = vec3.fromValues(1, -1, 0);
|
||||
vec3.transformMat4(v4, v4, m);
|
||||
vec3.normalize(v4, v4);
|
||||
|
||||
extrude = [...v1, ...v2, ...v3, ...v4];
|
||||
} else {
|
||||
// 平面模式
|
||||
extrude = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0];
|
||||
}
|
||||
|
||||
const extrude = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0];
|
||||
const extrudeIndex = (attributeIdx % 4) * 3;
|
||||
return [
|
||||
extrude[extrudeIndex],
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import PointTileModel from '../../tile/models/tileModel';
|
||||
import EarthExtrudeModel from './earthExtrude';
|
||||
// earth
|
||||
import EarthFillModel from './earthFill';
|
||||
import ExtrudeModel from './extrude';
|
||||
import FillModel from './fill';
|
||||
import FillImageModel from './fillmage';
|
||||
|
@ -21,7 +24,9 @@ export type PointType =
|
|||
| 'text'
|
||||
| 'icon'
|
||||
| 'vectorpoint'
|
||||
| 'tile';
|
||||
| 'tile'
|
||||
| 'earthFill'
|
||||
| 'earthExtrude';
|
||||
|
||||
const PointModels: { [key in PointType]: any } = {
|
||||
fillImage: FillImageModel,
|
||||
|
@ -35,6 +40,8 @@ const PointModels: { [key in PointType]: any } = {
|
|||
icon: IconModel,
|
||||
vectorpoint: PointTileModel,
|
||||
tile: TileFillModel,
|
||||
earthFill: EarthFillModel,
|
||||
earthExtrude: EarthExtrudeModel,
|
||||
};
|
||||
|
||||
export default PointModels;
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
varying vec4 v_color;
|
||||
uniform float u_opacity: 1.0;
|
||||
|
||||
uniform float u_pickLight: 0.0;
|
||||
|
||||
#pragma include "picking"
|
||||
|
||||
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
|
||||
|
||||
uniform float u_linearColor: 0;
|
||||
uniform vec4 u_sourceColor;
|
||||
uniform vec4 u_targetColor;
|
||||
|
||||
uniform float u_opacitylinear: 0.0;
|
||||
uniform float u_opacitylinear_dir: 1.0;
|
||||
|
||||
void main() {
|
||||
float opacity = styleMappingMat[0][0];
|
||||
float lightWeight = styleMappingMat[1][3];
|
||||
float barLinearZ = styleMappingMat[2][3];
|
||||
|
||||
// 设置圆柱的底色
|
||||
if(u_linearColor == 1.0) { // 使用渐变颜色
|
||||
gl_FragColor = mix(u_sourceColor, u_targetColor, barLinearZ);
|
||||
gl_FragColor.rgb *= lightWeight;
|
||||
} else { // 使用 color 方法传入的颜色
|
||||
gl_FragColor = v_color;
|
||||
}
|
||||
|
||||
// 应用透明度
|
||||
gl_FragColor.a *= opacity;
|
||||
|
||||
// 开启透明度渐变
|
||||
if(u_opacitylinear > 0.0) {
|
||||
gl_FragColor.a *= u_opacitylinear_dir > 0.0 ? (1.0 - barLinearZ): barLinearZ;
|
||||
}
|
||||
|
||||
// picking
|
||||
if(u_pickLight > 0.0) {
|
||||
gl_FragColor = filterColorAlpha(gl_FragColor, lightWeight);
|
||||
} else {
|
||||
gl_FragColor = filterColor(gl_FragColor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
precision highp float;
|
||||
|
||||
#define pi 3.1415926535
|
||||
#define ambientRatio 0.5
|
||||
#define diffuseRatio 0.3
|
||||
#define specularRatio 0.2
|
||||
|
||||
attribute vec3 a_Position;
|
||||
attribute vec3 a_Pos;
|
||||
attribute vec4 a_Color;
|
||||
attribute vec3 a_Size;
|
||||
attribute vec3 a_Normal;
|
||||
|
||||
uniform float u_heightfixed: 0.0; // 默认不固定
|
||||
uniform float u_globel;
|
||||
uniform float u_r;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
varying vec4 v_color;
|
||||
|
||||
uniform float u_opacity : 1;
|
||||
uniform float u_lightEnable: 1;
|
||||
|
||||
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
|
||||
|
||||
#pragma include "styleMapping"
|
||||
#pragma include "styleMappingCalOpacity"
|
||||
|
||||
#pragma include "projection"
|
||||
#pragma include "light"
|
||||
#pragma include "picking"
|
||||
|
||||
float getYRadian(float x, float z) {
|
||||
if(x > 0.0 && z > 0.0) {
|
||||
return atan(x/z);
|
||||
} else if(x > 0.0 && z <= 0.0){
|
||||
return atan(-z/x) + pi/2.0;
|
||||
} else if(x <= 0.0 && z <= 0.0) {
|
||||
return pi + atan(x/z); //atan(x/z) +
|
||||
} else {
|
||||
return atan(z/-x) + pi*3.0/2.0;
|
||||
}
|
||||
}
|
||||
|
||||
float getXRadian(float y, float r) {
|
||||
return atan(y/r);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
// cal style mapping - 数据纹理映射部分的计算
|
||||
styleMappingMat = mat4(
|
||||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA - lightWeight
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1] - linearZ(垂直方向 0 - 1 的值)
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
float columnCount = u_cellTypeLayout[0][1]; // 当看到数据纹理有几列
|
||||
float columnWidth = 1.0/columnCount; // 列宽
|
||||
float rowHeight = 1.0/rowCount; // 行高
|
||||
float cellCount = calCellCount(); // opacity - strokeOpacity - strokeWidth - stroke - offsets
|
||||
float id = a_vertexId; // 第n个顶点
|
||||
float cellCurrentRow = floor(id * cellCount / columnCount) + 1.0; // 起始点在第几行
|
||||
float cellCurrentColumn = mod(id * cellCount, columnCount) + 1.0; // 起始点在第几列
|
||||
|
||||
// cell 固定顺序 opacity -> strokeOpacity -> strokeWidth -> stroke ...
|
||||
// 按顺序从 cell 中取值、若没有则自动往下取值
|
||||
float textureOffset = 0.0; // 在 cell 中取值的偏移量
|
||||
|
||||
vec2 opacityAndOffset = calOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
|
||||
styleMappingMat[0][0] = opacityAndOffset.r;
|
||||
textureOffset = opacityAndOffset.g;
|
||||
// cal style mapping - 数据纹理映射部分的计算
|
||||
vec3 size = a_Size * a_Position;
|
||||
|
||||
// a_Position.z 是在构建网格的时候传入的标准值 0 - 1,在插值器插值可以获取 0~1 线性渐变的值
|
||||
styleMappingMat[2][3] = a_Position.z;
|
||||
|
||||
vec3 offset = size; // 控制圆柱体的大小 - 从标准单位圆柱体进行偏移
|
||||
if(u_heightfixed < 1.0) { // 圆柱体不固定高度
|
||||
|
||||
if (u_CoordinateSystem == COORDINATE_SYSTEM_P20 || u_CoordinateSystem == COORDINATE_SYSTEM_P20_OFFSET) {
|
||||
// P20 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减1
|
||||
offset = offset * pow(2.0, (19.0 - u_Zoom));
|
||||
}
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) {
|
||||
// P20_2 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减3
|
||||
offset = offset * pow(2.0, (19.0 - 3.0 - u_Zoom));
|
||||
}
|
||||
} else {// 圆柱体固定高度 ( 处理 mapbox )
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) {
|
||||
offset *= 4.0/pow(2.0, 21.0 - u_Zoom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vec4 project_pos = project_position(vec4(a_Pos.xy, 0., 1.0));
|
||||
|
||||
// u_r 控制圆柱的生长
|
||||
vec4 pos = vec4(project_pos.xy + offset.xy, offset.z * u_r, 1.0);
|
||||
|
||||
// 圆柱光照效果
|
||||
float lightWeight = 1.0;
|
||||
if(u_lightEnable > 0.0) { // 取消三元表达式,增强健壮性
|
||||
lightWeight = calc_lighting(pos);
|
||||
}
|
||||
styleMappingMat[1][3] = lightWeight;
|
||||
|
||||
v_color =vec4(a_Color.rgb * lightWeight, a_Color.w);
|
||||
|
||||
|
||||
// 在地球模式下,将原本垂直于 xy 平面的圆柱调整姿态到适应圆的角度
|
||||
//旋转矩阵mx,创建绕x轴旋转矩阵
|
||||
float r = sqrt(a_Pos.z*a_Pos.z + a_Pos.x*a_Pos.x);
|
||||
float xRadian = getXRadian(a_Pos.y, r);
|
||||
float xcos = cos(xRadian);//求解旋转角度余弦值
|
||||
float xsin = sin(xRadian);//求解旋转角度正弦值
|
||||
mat4 mx = mat4(
|
||||
1,0,0,0,
|
||||
0,xcos,-xsin,0,
|
||||
0,xsin,xcos,0,
|
||||
0,0,0,1);
|
||||
|
||||
//旋转矩阵my,创建绕y轴旋转矩阵
|
||||
float yRadian = getYRadian(a_Pos.x, a_Pos.z);
|
||||
float ycos = cos(yRadian);//求解旋转角度余弦值
|
||||
float ysin = sin(yRadian);//求解旋转角度正弦值
|
||||
mat4 my = mat4(
|
||||
ycos,0,-ysin,0,
|
||||
0,1,0,0,
|
||||
ysin,0,ycos,0,
|
||||
0,0,0,1);
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * vec4(( my * mx * vec4(a_Position * a_Size, 1.0)).xyz + a_Pos, 1.0);
|
||||
|
||||
|
||||
setPickingColor(a_PickingColor);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
uniform float u_additive;
|
||||
|
||||
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
|
||||
|
||||
varying vec4 v_data;
|
||||
varying vec4 v_color;
|
||||
varying float v_radius;
|
||||
|
||||
#pragma include "sdf_2d"
|
||||
#pragma include "picking"
|
||||
|
||||
|
||||
void main() {
|
||||
int shape = int(floor(v_data.w + 0.5));
|
||||
|
||||
vec4 textrueStroke = vec4(
|
||||
styleMappingMat[1][0],
|
||||
styleMappingMat[1][1],
|
||||
styleMappingMat[1][2],
|
||||
styleMappingMat[1][3]
|
||||
);
|
||||
|
||||
float opacity = styleMappingMat[0][0];
|
||||
float stroke_opacity = styleMappingMat[0][1];
|
||||
float strokeWidth = styleMappingMat[0][2];
|
||||
vec4 strokeColor = textrueStroke == vec4(0) ? v_color : textrueStroke;
|
||||
|
||||
lowp float antialiasblur = v_data.z;
|
||||
float r = v_radius / (v_radius + strokeWidth);
|
||||
|
||||
float outer_df;
|
||||
float inner_df;
|
||||
// 'circle', 'triangle', 'square', 'pentagon', 'hexagon', 'octogon', 'hexagram', 'rhombus', 'vesica'
|
||||
if (shape == 0) {
|
||||
outer_df = sdCircle(v_data.xy, 1.0);
|
||||
inner_df = sdCircle(v_data.xy, r);
|
||||
} else if (shape == 1) {
|
||||
outer_df = sdEquilateralTriangle(1.1 * v_data.xy);
|
||||
inner_df = sdEquilateralTriangle(1.1 / r * v_data.xy);
|
||||
} else if (shape == 2) {
|
||||
outer_df = sdBox(v_data.xy, vec2(1.));
|
||||
inner_df = sdBox(v_data.xy, vec2(r));
|
||||
} else if (shape == 3) {
|
||||
outer_df = sdPentagon(v_data.xy, 0.8);
|
||||
inner_df = sdPentagon(v_data.xy, r * 0.8);
|
||||
} else if (shape == 4) {
|
||||
outer_df = sdHexagon(v_data.xy, 0.8);
|
||||
inner_df = sdHexagon(v_data.xy, r * 0.8);
|
||||
} else if (shape == 5) {
|
||||
outer_df = sdOctogon(v_data.xy, 1.0);
|
||||
inner_df = sdOctogon(v_data.xy, r);
|
||||
} else if (shape == 6) {
|
||||
outer_df = sdHexagram(v_data.xy, 0.52);
|
||||
inner_df = sdHexagram(v_data.xy, r * 0.52);
|
||||
} else if (shape == 7) {
|
||||
outer_df = sdRhombus(v_data.xy, vec2(1.0));
|
||||
inner_df = sdRhombus(v_data.xy, vec2(r));
|
||||
} else if (shape == 8) {
|
||||
outer_df = sdVesica(v_data.xy, 1.1, 0.8);
|
||||
inner_df = sdVesica(v_data.xy, r * 1.1, r * 0.8);
|
||||
}
|
||||
|
||||
if(outer_df > antialiasblur + 0.018) discard;
|
||||
|
||||
float opacity_t = smoothstep(0.0, antialiasblur, outer_df);
|
||||
|
||||
float color_t = strokeWidth < 0.01 ? 0.0 : smoothstep(
|
||||
antialiasblur,
|
||||
0.0,
|
||||
inner_df
|
||||
);
|
||||
|
||||
if(strokeWidth < 0.01) {
|
||||
gl_FragColor = vec4(v_color.rgb, v_color.a * opacity);
|
||||
} else {
|
||||
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * opacity), strokeColor * stroke_opacity, color_t);
|
||||
}
|
||||
|
||||
if(u_additive > 0.0) {
|
||||
gl_FragColor *= opacity_t;
|
||||
gl_FragColor = filterColorAlpha(gl_FragColor, gl_FragColor.a);
|
||||
} else {
|
||||
gl_FragColor.a *= opacity_t;
|
||||
gl_FragColor = filterColor(gl_FragColor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
attribute vec4 a_Color;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec3 a_Extrude;
|
||||
attribute float a_Size;
|
||||
attribute float a_Shape;
|
||||
|
||||
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
|
||||
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
|
||||
varying vec4 v_data;
|
||||
varying vec4 v_color;
|
||||
varying float v_radius;
|
||||
|
||||
uniform float u_opacity : 1;
|
||||
uniform float u_stroke_opacity : 1;
|
||||
uniform float u_stroke_width : 2;
|
||||
uniform vec4 u_stroke_color : [0.0, 0.0, 0.0, 0.0];
|
||||
uniform vec2 u_offsets;
|
||||
|
||||
uniform float u_blur : 0.0;
|
||||
|
||||
#pragma include "styleMapping"
|
||||
#pragma include "styleMappingCalOpacity"
|
||||
#pragma include "styleMappingCalStrokeOpacity"
|
||||
#pragma include "styleMappingCalStrokeWidth"
|
||||
|
||||
#pragma include "projection"
|
||||
#pragma include "picking"
|
||||
|
||||
|
||||
void main() {
|
||||
vec3 extrude = a_Extrude;
|
||||
float shape_type = a_Shape;
|
||||
/*
|
||||
* setPickingSize 设置拾取大小
|
||||
*/
|
||||
float newSize = setPickingSize(a_Size);
|
||||
// float newSize = setPickingSize(a_Size) * 0.00001038445708445579;
|
||||
|
||||
// cal style mapping - 数据纹理映射部分的计算
|
||||
styleMappingMat = mat4(
|
||||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
float columnCount = u_cellTypeLayout[0][1]; // 当看到数据纹理有几列
|
||||
float columnWidth = 1.0/columnCount; // 列宽
|
||||
float rowHeight = 1.0/rowCount; // 行高
|
||||
float cellCount = calCellCount(); // opacity - strokeOpacity - strokeWidth - stroke - offsets
|
||||
float id = a_vertexId; // 第n个顶点
|
||||
float cellCurrentRow = floor(id * cellCount / columnCount) + 1.0; // 起始点在第几行
|
||||
float cellCurrentColumn = mod(id * cellCount, columnCount) + 1.0; // 起始点在第几列
|
||||
|
||||
// cell 固定顺序 opacity -> strokeOpacity -> strokeWidth -> stroke ...
|
||||
// 按顺序从 cell 中取值、若没有则自动往下取值
|
||||
float textureOffset = 0.0; // 在 cell 中取值的偏移量
|
||||
|
||||
vec2 opacityAndOffset = calOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
|
||||
styleMappingMat[0][0] = opacityAndOffset.r;
|
||||
textureOffset = opacityAndOffset.g;
|
||||
|
||||
vec2 strokeOpacityAndOffset = calStrokeOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
|
||||
styleMappingMat[0][1] = strokeOpacityAndOffset.r;
|
||||
textureOffset = strokeOpacityAndOffset.g;
|
||||
|
||||
vec2 strokeWidthAndOffset = calStrokeWidthAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
|
||||
styleMappingMat[0][2] = strokeWidthAndOffset.r;
|
||||
textureOffset = strokeWidthAndOffset.g;
|
||||
|
||||
vec4 textrueStroke = vec4(-1.0, -1.0, -1.0, -1.0);
|
||||
if(hasStroke()) {
|
||||
vec2 valueRPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
|
||||
styleMappingMat[1][0] = pos2value(valueRPos, columnWidth, rowHeight); // R
|
||||
textureOffset += 1.0;
|
||||
|
||||
vec2 valueGPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
|
||||
styleMappingMat[1][1] = pos2value(valueGPos, columnWidth, rowHeight); // G
|
||||
textureOffset += 1.0;
|
||||
|
||||
vec2 valueBPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
|
||||
styleMappingMat[1][2] = pos2value(valueBPos, columnWidth, rowHeight); // B
|
||||
textureOffset += 1.0;
|
||||
|
||||
vec2 valueAPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
|
||||
styleMappingMat[1][3] = pos2value(valueAPos, columnWidth, rowHeight); // A
|
||||
textureOffset += 1.0;
|
||||
} else {
|
||||
if(u_stroke_color == vec4(0.0)) {
|
||||
styleMappingMat[1][0] = v_color.r;
|
||||
styleMappingMat[1][1] = v_color.g;
|
||||
styleMappingMat[1][2] = v_color.b;
|
||||
styleMappingMat[1][3] = v_color.a;
|
||||
} else {
|
||||
styleMappingMat[1][0] = u_stroke_color.r;
|
||||
styleMappingMat[1][1] = u_stroke_color.g;
|
||||
styleMappingMat[1][2] = u_stroke_color.b;
|
||||
styleMappingMat[1][3] = u_stroke_color.a;
|
||||
}
|
||||
}
|
||||
|
||||
// cal style mapping
|
||||
|
||||
// unpack color(vec2)
|
||||
v_color = a_Color;
|
||||
|
||||
// radius(16-bit)
|
||||
v_radius = newSize;
|
||||
|
||||
// TODO: billboard
|
||||
// anti-alias
|
||||
// float antialiased_blur = -max(u_blur, antialiasblur);
|
||||
float antialiasblur = -max(2.0 / u_DevicePixelRatio / newSize, u_blur);
|
||||
|
||||
// TODP: /abs(extrude.x) 是为了兼容地球模式
|
||||
v_data = vec4(extrude.x/abs(extrude.x), extrude.y/abs(extrude.y), antialiasblur,shape_type);
|
||||
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * vec4(a_Position + extrude * newSize * 0.1, 1.0);
|
||||
|
||||
setPickingColor(a_PickingColor);
|
||||
}
|
|
@ -12,7 +12,6 @@ attribute vec3 a_Size;
|
|||
attribute vec3 a_Normal;
|
||||
|
||||
uniform float u_heightfixed: 0.0; // 默认不固定
|
||||
uniform float u_globel;
|
||||
uniform float u_r;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
|
@ -118,31 +117,5 @@ void main() {
|
|||
gl_Position = project_common_position_to_clipspace(pos);
|
||||
}
|
||||
|
||||
if(u_globel > 0.0) {
|
||||
// 在地球模式下,将原本垂直于 xy 平面的圆柱调整姿态到适应圆的角度
|
||||
//旋转矩阵mx,创建绕x轴旋转矩阵
|
||||
float r = sqrt(a_Pos.z*a_Pos.z + a_Pos.x*a_Pos.x);
|
||||
float xRadian = getXRadian(a_Pos.y, r);
|
||||
float xcos = cos(xRadian);//求解旋转角度余弦值
|
||||
float xsin = sin(xRadian);//求解旋转角度正弦值
|
||||
mat4 mx = mat4(
|
||||
1,0,0,0,
|
||||
0,xcos,-xsin,0,
|
||||
0,xsin,xcos,0,
|
||||
0,0,0,1);
|
||||
|
||||
//旋转矩阵my,创建绕y轴旋转矩阵
|
||||
float yRadian = getYRadian(a_Pos.x, a_Pos.z);
|
||||
float ycos = cos(yRadian);//求解旋转角度余弦值
|
||||
float ysin = sin(yRadian);//求解旋转角度正弦值
|
||||
mat4 my = mat4(
|
||||
ycos,0,-ysin,0,
|
||||
0,1,0,0,
|
||||
ysin,0,ycos,0,
|
||||
0,0,0,1);
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * vec4(( my * mx * vec4(a_Position * a_Size, 1.0)).xyz + a_Pos, 1.0);
|
||||
}
|
||||
|
||||
setPickingColor(a_PickingColor);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
uniform float u_globel;
|
||||
uniform float u_additive;
|
||||
|
||||
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
|
||||
|
@ -62,11 +60,6 @@ void main() {
|
|||
inner_df = sdVesica(v_data.xy, r * 1.1, r * 0.8);
|
||||
}
|
||||
|
||||
if(u_globel > 0.0) {
|
||||
// TODO: 地球模式下避免多余片元绘制,同时也能避免有用片元在透明且重叠的情况下无法写入
|
||||
// 付出的代价是边缘会有一些锯齿
|
||||
if(outer_df > antialiasblur + 0.018) discard;
|
||||
}
|
||||
float opacity_t = smoothstep(0.0, antialiasblur, outer_df);
|
||||
|
||||
float color_t = strokeWidth < 0.01 ? 0.0 : smoothstep(
|
||||
|
|
|
@ -6,7 +6,6 @@ attribute float a_Shape;
|
|||
|
||||
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
|
||||
|
||||
uniform float u_globel;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
uniform float u_meter2coord;
|
||||
|
@ -177,10 +176,6 @@ void main() {
|
|||
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, u_raisingHeight, 1.0));
|
||||
}
|
||||
|
||||
if(u_globel > 0.0) {
|
||||
gl_Position = u_ViewProjectionMatrix * vec4(a_Position + extrude * newSize * 0.1, 1.0);
|
||||
}
|
||||
|
||||
// gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, 0.0, 1.0));
|
||||
|
||||
setPickingColor(a_PickingColor);
|
||||
|
|
|
@ -37,71 +37,39 @@ export default class Amap2demo extends React.Component {
|
|||
|
||||
this.scene = scene;
|
||||
|
||||
const layer = new LineLayer()
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
color: '#0f0',
|
||||
},
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: [
|
||||
[120, 40],
|
||||
[100, 30],
|
||||
[110, 20],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
color: '#f00',
|
||||
},
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: [
|
||||
[130, 30],
|
||||
[100, 20],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
color: '#ff0',
|
||||
},
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: [
|
||||
[100, 20],
|
||||
[130, 30],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
const layer = new PointLayer({
|
||||
visible: false,
|
||||
})
|
||||
.shape('halfLine')
|
||||
.size(20)
|
||||
.color('color')
|
||||
.active(true)
|
||||
.style({
|
||||
// opacity: 0.3,
|
||||
sourceColor: '#f00',
|
||||
targetColor: '#ff0',
|
||||
arrow: {
|
||||
enable: true,
|
||||
arrowWidth: 2,
|
||||
// arrowHeight: 3,
|
||||
// tailWidth: 0,
|
||||
.source(
|
||||
[
|
||||
{
|
||||
lng: 120,
|
||||
lat: 30,
|
||||
},
|
||||
});
|
||||
],
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
},
|
||||
)
|
||||
.shape('circle')
|
||||
.size(10)
|
||||
.color('#f00');
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.addLayer(layer);
|
||||
// console.log(scene.getMapService().lngLatToMercator([100, 30], 0))
|
||||
|
||||
setTimeout(() => {
|
||||
layer.show();
|
||||
layer.style({
|
||||
opacity: 1,
|
||||
});
|
||||
|
||||
console.log(layer.isVisible());
|
||||
}, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -277,7 +277,9 @@ export default class ScaleComponent extends React.Component {
|
|||
{ lng: 127.657407, lat: 49.76027 },
|
||||
];
|
||||
|
||||
let pointlayer = new PointLayer()
|
||||
// let pointlayer = new PointLayer({ layerType: 'earthFill' })
|
||||
// let pointlayer = new PointLayer({ })
|
||||
let pointlayer = new PointLayer({ layerType: 'earthExtrude' })
|
||||
.source(
|
||||
d,
|
||||
// [
|
||||
|
@ -374,11 +376,11 @@ export default class ScaleComponent extends React.Component {
|
|||
},
|
||||
},
|
||||
)
|
||||
.shape('circle')
|
||||
// .shape('cylinder')
|
||||
// .shape('circle')
|
||||
.shape('cylinder')
|
||||
.color('#f00')
|
||||
// .size('', () => [1, 1, 10])
|
||||
.size(20)
|
||||
.size('', () => [1, 1, 10])
|
||||
// .size(20)
|
||||
.style({
|
||||
// opacity: 0.6,
|
||||
})
|
||||
|
|
|
@ -36,7 +36,10 @@ export default class ScaleComponent extends React.Component {
|
|||
});
|
||||
return { coord: [latlng1, latlng2] };
|
||||
});
|
||||
const flyLine = new LineLayer({ blend: 'normal' })
|
||||
const flyLine = new LineLayer({
|
||||
blend: 'normal',
|
||||
layerType: 'earthArc3d',
|
||||
})
|
||||
.source(flydata, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
|
|
Loading…
Reference in New Issue