mirror of https://gitee.com/antv-l7/antv-l7
feat: 渲染流程代码简化
This commit is contained in:
parent
99b10bf662
commit
b450900f02
|
@ -17,12 +17,12 @@ export default class LayerModelPlugin implements ILayerPlugin {
|
|||
}
|
||||
|
||||
public async prepareLayerModel(layer: ILayer) {
|
||||
// 更新Model 配置项
|
||||
layer.prepareBuildModel();
|
||||
// clear layerModel resource
|
||||
// 初始化 Model
|
||||
await layer.buildModels();
|
||||
// layer.layerModelNeedUpdate = false;
|
||||
// // 更新Model 配置项
|
||||
// layer.prepareBuildModel();
|
||||
// // clear layerModel resource
|
||||
// // 初始化 Model
|
||||
// await layer.buildModels();
|
||||
// // layer.layerModelNeedUpdate = false;
|
||||
}
|
||||
|
||||
public apply(layer: ILayer) {
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
ILayer,
|
||||
TYPES,
|
||||
IRendererService,
|
||||
} from '@antv/l7-core';
|
||||
|
||||
import StyleAttribute from '../../../../core/src/services/layer/StyleAttribute'
|
||||
import { vert, frag } from './fillShader';
|
||||
export default class FillModel {
|
||||
protected layer: ILayer;
|
||||
private attributes: any[] = [];
|
||||
|
||||
protected rendererService: IRendererService;
|
||||
|
||||
constructor(layer: ILayer) {
|
||||
|
@ -21,253 +13,11 @@ export default class FillModel {
|
|||
.getContainer()
|
||||
.get<IRendererService>(TYPES.IRendererService);
|
||||
|
||||
this.registerBuiltinAttributes();
|
||||
}
|
||||
|
||||
public createAttributesAndIndices(
|
||||
features: IEncodeFeature[],
|
||||
|
||||
) {
|
||||
|
||||
function triangulation() {
|
||||
const coordinates = [120, 30]
|
||||
return {
|
||||
vertices: [...coordinates, ...coordinates, ...coordinates, ...coordinates],
|
||||
indices: [0, 1, 2, 2, 3, 0],
|
||||
size: 2,
|
||||
};
|
||||
}
|
||||
|
||||
const descriptors = this.attributes.map((attr) => {
|
||||
attr.resetDescriptor();
|
||||
return attr.descriptor;
|
||||
});
|
||||
let verticesNum = 0;
|
||||
let vecticesCount = 0; // 在不使用 element 的时候记录顶点、图层所有顶点的总数
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const vertices: number[] = [];
|
||||
const indices: number[] = [];
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const normals: number[] = [];
|
||||
let size = 3;
|
||||
features.forEach((feature, featureIdx) => {
|
||||
// 逐 feature 进行三角化
|
||||
const {
|
||||
indices: indicesForCurrentFeature,
|
||||
vertices: verticesForCurrentFeature,
|
||||
normals: normalsForCurrentFeature,
|
||||
size: vertexSize,
|
||||
indexes,
|
||||
count,
|
||||
} = triangulation(feature);
|
||||
|
||||
if (typeof count === 'number') {
|
||||
vecticesCount += count;
|
||||
}
|
||||
|
||||
indicesForCurrentFeature.forEach((i) => {
|
||||
indices.push(i + verticesNum);
|
||||
});
|
||||
size = vertexSize;
|
||||
const verticesNumForCurrentFeature =
|
||||
verticesForCurrentFeature.length / vertexSize;
|
||||
|
||||
|
||||
verticesNum += verticesNumForCurrentFeature;
|
||||
// 根据 position 顶点生成其他顶点数据
|
||||
for (
|
||||
let vertexIdx = 0;
|
||||
vertexIdx < verticesNumForCurrentFeature;
|
||||
vertexIdx++
|
||||
) {
|
||||
const normal =
|
||||
normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) ||
|
||||
[];
|
||||
const vertice = verticesForCurrentFeature.slice(
|
||||
vertexIdx * vertexSize,
|
||||
vertexIdx * vertexSize + vertexSize,
|
||||
);
|
||||
|
||||
let vertexIndex = 0;
|
||||
if (indexes && indexes[vertexIdx] !== undefined) {
|
||||
vertexIndex = indexes[vertexIdx];
|
||||
}
|
||||
|
||||
descriptors.forEach((descriptor) => {
|
||||
if (descriptor && descriptor.update) {
|
||||
(descriptor.buffer.data as number[]).push(
|
||||
...descriptor.update(
|
||||
feature,
|
||||
featureIdx,
|
||||
vertice,
|
||||
vertexIdx, // 当前顶点所在feature索引
|
||||
normal,
|
||||
vertexIndex,
|
||||
// 传入顶点索引 vertexIdx
|
||||
),
|
||||
);
|
||||
} // end if
|
||||
}); // end for each
|
||||
} // end for
|
||||
}); // end features for Each
|
||||
const {
|
||||
createAttribute,
|
||||
createBuffer,
|
||||
createElements,
|
||||
} = this.rendererService;
|
||||
|
||||
const attributes = {};
|
||||
|
||||
descriptors.forEach((descriptor) => {
|
||||
if (descriptor) {
|
||||
const { buffer, update, name, ...rest } = descriptor;
|
||||
|
||||
const vertexAttribute = createAttribute({
|
||||
// IBuffer 参数透传
|
||||
buffer: createBuffer(buffer),
|
||||
...rest,
|
||||
});
|
||||
attributes[descriptor.name || ''] = vertexAttribute;
|
||||
}
|
||||
});
|
||||
|
||||
const elements = createElements({
|
||||
data: indices,
|
||||
type: gl.UNSIGNED_INT,
|
||||
count: indices.length,
|
||||
});
|
||||
|
||||
// console.log(attributes);
|
||||
|
||||
const a_posotion_data = {
|
||||
data: [120, 30, 0, 120, 30, 0, 120, 30, 0, 120, 30, 0],
|
||||
type: 5126
|
||||
}
|
||||
const a_extrude_data = {
|
||||
data: [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0],
|
||||
type: 5126,
|
||||
usage: 35048
|
||||
}
|
||||
|
||||
|
||||
|
||||
const attributesAndIndices = {
|
||||
attributes,
|
||||
elements,
|
||||
count: vecticesCount,
|
||||
};
|
||||
return attributesAndIndices;
|
||||
}
|
||||
|
||||
public buildLayerModel() {
|
||||
const uniforms = {
|
||||
u_CameraPosition: [0, 0, 0],
|
||||
u_CoordinateSystem: 0,
|
||||
u_DevicePixelRatio: 0,
|
||||
u_FocalDistance: 0,
|
||||
u_ModelMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_Mvp: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_PixelsPerDegree: [0, 0, 0],
|
||||
u_PixelsPerDegree2: [0, 0, 0],
|
||||
u_PixelsPerMeter: [0, 0, 0],
|
||||
u_ProjectionMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_ViewMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_ViewProjectionMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_ViewportCenter: [0, 0],
|
||||
u_ViewportCenterProjection: [0, 0, 0, 0],
|
||||
u_ViewportSize: [0, 0],
|
||||
u_Zoom: 1,
|
||||
u_ZoomScale: 1
|
||||
}
|
||||
|
||||
const { createModel } = this.rendererService;
|
||||
const { attributes, elements } =this.createAttributesAndIndices(
|
||||
[{
|
||||
coordinates: [120, 30],
|
||||
id: 0,
|
||||
}],
|
||||
);
|
||||
|
||||
const modelOptions = {
|
||||
attributes,
|
||||
uniforms,
|
||||
fs: frag,
|
||||
vs: vert,
|
||||
elements,
|
||||
};
|
||||
|
||||
return createModel(modelOptions);
|
||||
}
|
||||
|
||||
|
||||
public buildModels() {
|
||||
const model = this.buildLayerModel();
|
||||
return [model];
|
||||
}
|
||||
|
||||
public registerStyleAttribute(
|
||||
options: any
|
||||
) {
|
||||
const attributeToUpdate = new StyleAttribute(options);
|
||||
// console.log(options);
|
||||
// console.log(attributeToUpdate);
|
||||
|
||||
|
||||
this.attributes.push(attributeToUpdate);
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
|
||||
this.registerStyleAttribute({
|
||||
name: 'position',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Position',
|
||||
buffer: {
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
) => {
|
||||
return vertex.length === 2
|
||||
? [vertex[0], vertex[1], 0]
|
||||
: [vertex[0], vertex[1], vertex[2]];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.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 extrude = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0];
|
||||
const extrudeIndex = (attributeIdx % 4) * 3;
|
||||
return [
|
||||
extrude[extrudeIndex],
|
||||
extrude[extrudeIndex + 1],
|
||||
extrude[extrudeIndex + 2],
|
||||
];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { createModel } = this.rendererService;
|
||||
const model = createModel();
|
||||
return [model];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,94 @@
|
|||
/**
|
||||
* render w/ regl
|
||||
* @see https://github.com/regl-project/regl/blob/gh-pages/API.md
|
||||
*/
|
||||
import {
|
||||
IAttributeInitializationOptions,
|
||||
IBufferInitializationOptions,
|
||||
IClearOptions,
|
||||
IElementsInitializationOptions,
|
||||
IExtensions,
|
||||
IModel,
|
||||
IModelInitializationOptions,
|
||||
} from '@antv/l7-core';
|
||||
const vert = `
|
||||
#define TILE_SIZE 512.0
|
||||
#define PI 3.1415926536
|
||||
#define WORLD_SCALE TILE_SIZE / (PI * 2.0)
|
||||
|
||||
#define COORDINATE_SYSTEM_P20 5.0 // amap
|
||||
#define COORDINATE_SYSTEM_P20_OFFSET 6.0 // amap offset
|
||||
|
||||
attribute vec3 a_Position;
|
||||
attribute vec3 a_Extrude;
|
||||
|
||||
uniform mat4 u_ViewProjectionMatrix;
|
||||
|
||||
uniform float u_Zoom;
|
||||
|
||||
uniform float u_ZoomScale;
|
||||
|
||||
uniform float u_CoordinateSystem;
|
||||
|
||||
uniform vec2 u_ViewportCenter;
|
||||
|
||||
uniform vec4 u_ViewportCenterProjection;
|
||||
|
||||
uniform vec3 u_PixelsPerDegree;
|
||||
|
||||
uniform vec3 u_PixelsPerDegree2;
|
||||
|
||||
vec2 project_mercator(vec2 lnglat) {
|
||||
float x = lnglat.x;
|
||||
return vec2(
|
||||
radians(x) + PI,
|
||||
PI - log(tan(PI * 0.25 + radians(lnglat.y) * 0.5))
|
||||
);
|
||||
}
|
||||
|
||||
// offset coords -> world coords 偏移坐标转成世界坐标
|
||||
vec4 project_offset(vec4 offset) {
|
||||
float dy = offset.y;
|
||||
dy = clamp(dy, -1., 1.);
|
||||
vec3 pixels_per_unit = u_PixelsPerDegree + u_PixelsPerDegree2 * dy;
|
||||
return vec4(offset.xy * pixels_per_unit.xy, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// 投影方法 - 将经纬度转化为平面坐标(xy 平面)
|
||||
vec4 project_position(vec4 position) {
|
||||
|
||||
if (u_CoordinateSystem == COORDINATE_SYSTEM_P20_OFFSET) {
|
||||
float X = position.x - u_ViewportCenter.x;
|
||||
float Y = position.y - u_ViewportCenter.y;
|
||||
return project_offset(vec4(X, Y, 0.0, 1.0));
|
||||
}
|
||||
|
||||
if (u_CoordinateSystem == COORDINATE_SYSTEM_P20) {
|
||||
return vec4(
|
||||
(project_mercator(position.xy) * WORLD_SCALE * u_ZoomScale - vec2(215440491., 106744817.)) * vec2(1., -1.),
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
vec2 project_pixel(vec2 pixel) {
|
||||
// P20 坐标系下,为了和 Web 墨卡托坐标系统一,zoom 默认减1
|
||||
return pixel * pow(2.0, (19.0 - u_Zoom));
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
vec2 offset = a_Extrude.xy * 10.0;
|
||||
|
||||
offset = project_pixel(offset);
|
||||
|
||||
vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0));
|
||||
|
||||
vec4 worldPos = u_ViewProjectionMatrix * vec4(project_pos.xy + offset, 0.0, 1.0) + u_ViewportCenterProjection;
|
||||
gl_Position = worldPos;
|
||||
}
|
||||
`;
|
||||
const frag = `
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
import { injectable } from 'inversify';
|
||||
import regl from 'l7regl';
|
||||
import 'reflect-metadata';
|
||||
|
@ -20,87 +98,25 @@ import 'reflect-metadata';
|
|||
*/
|
||||
@injectable()
|
||||
export default class ReglRendererService {
|
||||
public extensionObject: IExtensions;
|
||||
private gl: regl.Regl;
|
||||
|
||||
public init(
|
||||
canvas: HTMLCanvasElement,
|
||||
) {
|
||||
|
||||
this.gl = regl({
|
||||
// creates a full screen canvas element and WebGLRenderingContext
|
||||
// var regl = require('regl')()
|
||||
canvas: canvas,
|
||||
attributes: {
|
||||
alpha: true,
|
||||
antialias: true,
|
||||
premultipliedAlpha: true,
|
||||
preserveDrawingBuffer: false,
|
||||
stencil: false,
|
||||
},
|
||||
// TODO: use extensions
|
||||
extensions: [
|
||||
'OES_element_index_uint',
|
||||
'OES_standard_derivatives', // wireframe
|
||||
'ANGLE_instanced_arrays', // VSM shadow map
|
||||
],
|
||||
optionalExtensions: [
|
||||
'oes_texture_float_linear',
|
||||
'OES_texture_float',
|
||||
'EXT_texture_filter_anisotropic',
|
||||
'EXT_blend_minmax',
|
||||
'WEBGL_depth_texture',
|
||||
],
|
||||
profile: true,
|
||||
this.gl = regl({
|
||||
canvas,
|
||||
});
|
||||
return this.gl;
|
||||
}
|
||||
|
||||
public createModel = (options: IModelInitializationOptions): IModel =>
|
||||
new ReglModel(this.gl, options);
|
||||
public createModel = () =>
|
||||
new ReglModel(this.gl);
|
||||
|
||||
public createAttribute = (
|
||||
options: IAttributeInitializationOptions,
|
||||
) => {
|
||||
const { buffer, offset, stride, normalized, size, divisor } = options;
|
||||
|
||||
const attribute = {
|
||||
buffer,
|
||||
offset: offset || 0,
|
||||
stride: stride || 0,
|
||||
normalized: normalized || false,
|
||||
divisor: divisor || 0,
|
||||
};
|
||||
|
||||
if (size) {
|
||||
attribute.size = size;
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
public createBuffer = (options: IBufferInitializationOptions) => {
|
||||
const { data } = options;
|
||||
return this.gl.buffer({
|
||||
data,
|
||||
usage: 'static',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public createElements = (
|
||||
options: IElementsInitializationOptions,
|
||||
) => {
|
||||
|
||||
const { data, count } = options;
|
||||
return this.gl.elements({
|
||||
data,
|
||||
usage: "static",
|
||||
count,
|
||||
});
|
||||
};
|
||||
|
||||
public clear = (options: IClearOptions) => {
|
||||
public clear = (options: any) => {
|
||||
const { color, depth, stencil } = options;
|
||||
const reglClearOptions: regl.ClearOptions = {
|
||||
const reglClearOptions: any = {
|
||||
color,
|
||||
depth,
|
||||
stencil,
|
||||
|
@ -113,36 +129,51 @@ class ReglModel {
|
|||
private drawCommand: any;
|
||||
private uniforms: any = {};
|
||||
|
||||
constructor(reGl: any, options: any) {
|
||||
const {
|
||||
vs,
|
||||
fs,
|
||||
attributes,
|
||||
uniforms,
|
||||
elements,
|
||||
} = options;
|
||||
constructor(reGl: any) {
|
||||
const reglUniforms: any = {};
|
||||
|
||||
const uniforms = {
|
||||
u_CameraPosition: [0, 0, 0],
|
||||
u_CoordinateSystem: 0,
|
||||
u_DevicePixelRatio: 0,
|
||||
u_ModelMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_PixelsPerDegree: [0, 0, 0],
|
||||
u_PixelsPerDegree2: [0, 0, 0],
|
||||
u_PixelsPerMeter: [0, 0, 0],
|
||||
u_ProjectionMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_ViewMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_ViewProjectionMatrix: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
u_ViewportCenter: [0, 0],
|
||||
u_ViewportCenterProjection: [0, 0, 0, 0],
|
||||
u_ViewportSize: [0, 0],
|
||||
u_Zoom: 1,
|
||||
u_ZoomScale: 1
|
||||
}
|
||||
|
||||
this.uniforms = this.extractUniforms(uniforms);
|
||||
Object.keys(uniforms).forEach((uniformName) => {
|
||||
// pass data into regl
|
||||
reglUniforms[uniformName] = reGl.prop(uniformName);
|
||||
});
|
||||
|
||||
|
||||
|
||||
const reglAttributes: any = {};
|
||||
Object.keys(attributes).forEach((name: string) => {
|
||||
reglAttributes[name] = attributes[name];
|
||||
});
|
||||
// [{
|
||||
// coordinates: [120, 30],
|
||||
// id: 0,
|
||||
// }],
|
||||
|
||||
const drawParams: any = {
|
||||
attributes: reglAttributes,
|
||||
frag: fs,
|
||||
attributes: {
|
||||
a_Extrude: [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0],
|
||||
a_Position: [120, 30, 0, 120, 30, 0, 120, 30, 0, 120, 30, 0],
|
||||
},
|
||||
frag,
|
||||
uniforms: reglUniforms,
|
||||
vert: vs,
|
||||
vert,
|
||||
primitive: 'triangles'
|
||||
};
|
||||
|
||||
drawParams.elements = elements;
|
||||
drawParams.elements = [0, 1, 2, 2, 3, 0];
|
||||
this.drawCommand = reGl(drawParams);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue