feat: 删除渲染多余代码

This commit is contained in:
shihui 2022-12-04 22:37:26 +08:00
parent c6994d0cd3
commit 99b10bf662
11 changed files with 162 additions and 519 deletions

View File

@ -44,34 +44,7 @@ export default class PickingService implements IPickingService {
private pickBufferScale: number = 1.0; private pickBufferScale: number = 1.0;
public init(id: string) { public init(id: string) {
const {
createTexture2D,
createFramebuffer,
getContainer,
} = this.rendererService;
let { width, height } = this.getContainerSize(
getContainer() as HTMLCanvasElement | HTMLElement,
);
width *= DOM.DPR;
height *= DOM.DPR;
this.pickBufferScale =
this.configService.getSceneConfig(id).pickBufferScale || 1;
// 创建 picking framebuffer后续实时 resize
this.pickingFBO = createFramebuffer({
color: createTexture2D({
width: Math.round(width / this.pickBufferScale),
height: Math.round(height / this.pickBufferScale),
wrapS: gl.CLAMP_TO_EDGE,
wrapT: gl.CLAMP_TO_EDGE,
}),
});
// 监听 hover 事件
this.interactionService.on(
InteractionEvent.Hover,
this.pickingAllLayer.bind(this),
);
} }
public async boxPickLayer( public async boxPickLayer(

View File

@ -50,20 +50,10 @@ export default class StyleAttribute implements IStyleAttribute {
Object.assign(this, options); Object.assign(this, options);
} }
public mapping(params: unknown[]): unknown[] { public mapping(){
/** // console.log(this.scale?.defaultValues);
* callback null , callback
*/ return this.scale?.defaultValues;
if (this.scale?.callback) {
// 使用用户返回的值处理
const ret = this.scale?.callback(...params);
if (!isNil(ret)) {
return [ret];
}
}
// 没有 callback 或者用户 callback 返回值为空,则使用默认的逻辑处理
return this.defaultCallback(params);
} }
public resetDescriptor() { public resetDescriptor() {
@ -71,18 +61,4 @@ export default class StyleAttribute implements IStyleAttribute {
this.descriptor.buffer.data = []; this.descriptor.buffer.data = [];
} }
} }
private defaultCallback = (params: unknown[]): unknown[] => {
// 没有 params 的情况,是指没有指定 fields直接返回配置的 values 常量
if (params.length === 0) {
return this.scale?.defaultValues || [];
}
return params.map((param, idx) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const scaleFunc = this.scale?.scalers![idx].func;
// @ts-ignore // TODO 支持双变量映射
const value = scaleFunc(param);
return value;
});
};
} }

View File

@ -101,6 +101,8 @@ export default class Scene extends EventEmitter implements ISceneService {
private markerContainer: HTMLElement; private markerContainer: HTMLElement;
private gl: any
private hooks: { private hooks: {
init: AsyncSeriesHook; init: AsyncSeriesHook;
}; };
@ -182,12 +184,11 @@ export default class Scene extends EventEmitter implements ISceneService {
this.$container, this.$container,
) as HTMLCanvasElement; ) as HTMLCanvasElement;
this.setCanvas(); this.setCanvas();
await this.rendererService.init(
// @ts-ignore this.gl = this.rendererService.init(
this.canvas, this.canvas,
this.configService.getSceneConfig(this.id) as IRenderConfig,
sceneConfig.gl,
); );
this.initContainer(); this.initContainer();
elementResizeEvent( elementResizeEvent(
@ -431,15 +432,10 @@ export default class Scene extends EventEmitter implements ISceneService {
if (canvas) { if (canvas) {
canvas.width = w * pixelRatio; canvas.width = w * pixelRatio;
canvas.height = h * pixelRatio; canvas.height = h * pixelRatio;
// canvas.style.width = `${w}px`;
// canvas.style.height = `${h}px`;
} }
this.rendererService.viewport({
x: 0, // set view port
y: 0, this.gl._gl.viewport(0, 0, pixelRatio * w, pixelRatio * h);
width: pixelRatio * w,
height: pixelRatio * h,
});
} }
private setCanvas() { private setCanvas() {

View File

@ -695,8 +695,10 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
public updateUniform() { public updateUniform() {
// 重新计算坐标系参数 // 重新计算坐标系参数
this.coordinateSystemService.refresh(); this.coordinateSystemService.refresh();
const { width: w, height: h } = this.mapService.getMapCanvasContainer().getBoundingClientRect();
const { width, height } = this.rendererService.getViewportSize(); const width = w * window.devicePixelRatio;
const height = h * window.devicePixelRatio
this.models.forEach((model) => { this.models.forEach((model) => {
model.addUniforms({ model.addUniforms({
// 相机参数,包含 VP 矩阵、缩放等级 // 相机参数,包含 VP 矩阵、缩放等级

View File

@ -136,6 +136,21 @@ export default class FillModel {
type: gl.UNSIGNED_INT, type: gl.UNSIGNED_INT,
count: indices.length, 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 = { const attributesAndIndices = {
attributes, attributes,
elements, elements,
@ -194,6 +209,10 @@ export default class FillModel {
options: any options: any
) { ) {
const attributeToUpdate = new StyleAttribute(options); const attributeToUpdate = new StyleAttribute(options);
// console.log(options);
// console.log(attributeToUpdate);
this.attributes.push(attributeToUpdate); this.attributes.push(attributeToUpdate);
} }

View File

@ -4,7 +4,6 @@ import {
IBuffer, IBuffer,
} from '@antv/l7-core'; } from '@antv/l7-core';
import regl from 'l7regl'; import regl from 'l7regl';
import ReglBuffer from './ReglBuffer';
/** /**
* @see https://github.com/regl-project/regl/blob/gh-pages/API.md#attributes * @see https://github.com/regl-project/regl/blob/gh-pages/API.md#attributes
@ -17,7 +16,7 @@ export default class ReglAttribute implements IAttribute {
const { buffer, offset, stride, normalized, size, divisor } = options; const { buffer, offset, stride, normalized, size, divisor } = options;
this.buffer = buffer; this.buffer = buffer;
this.attribute = { this.attribute = {
buffer: (buffer as ReglBuffer).get(), buffer,
offset: offset || 0, offset: offset || 0,
stride: stride || 0, stride: stride || 0,
normalized: normalized || false, normalized: normalized || false,
@ -33,16 +32,4 @@ export default class ReglAttribute implements IAttribute {
return this.attribute; return this.attribute;
} }
public updateBuffer(options: {
// 用于替换的数据
data: number[] | number[][] | Uint8Array | Uint16Array | Uint32Array;
// 原 Buffer 替换位置,单位为 byte
offset: number;
}) {
this.buffer.subData(options);
}
public destroy() {
this.buffer.destroy();
}
} }

View File

@ -23,17 +23,4 @@ export default class ReglBuffer implements IBuffer {
return this.buffer; return this.buffer;
} }
public destroy() {
this.buffer.destroy();
}
public subData({
data,
offset,
}: {
data: number[] | number[][] | Uint8Array | Uint16Array | Uint32Array;
offset: number;
}) {
this.buffer.subdata(data, offset);
}
} }

View File

@ -2,38 +2,3 @@ import { gl, IElements, IElementsInitializationOptions } from '@antv/l7-core';
import regl from 'l7regl'; import regl from 'l7regl';
import { dataTypeMap, usageMap } from './constants'; import { dataTypeMap, usageMap } from './constants';
/**
* @see https://github.com/regl-project/regl/blob/gh-pages/API.md#elements
*/
export default class ReglElements implements IElements {
private elements: regl.Elements;
constructor(reGl: regl.Regl, options: IElementsInitializationOptions) {
const { data, usage, type, count } = options;
this.elements = reGl.elements({
data,
usage: usageMap[usage || gl.STATIC_DRAW],
type: dataTypeMap[type || gl.UNSIGNED_BYTE] as
| 'uint8'
| 'uint16'
| 'uint32',
count,
});
}
public get() {
return this.elements;
}
public subData({
data,
}: {
data: number[] | number[][] | Uint8Array | Uint16Array | Uint32Array;
}) {
this.elements.subdata(data);
}
public destroy() {
// this.elements.destroy();
}
}

View File

@ -1,142 +0,0 @@
import {
IModel,
IModelDrawOptions,
IModelInitializationOptions,
IUniform,
} from '@antv/l7-core';
import regl from 'l7regl';
import { isPlainObject, isTypedArray } from 'lodash';
import ReglAttribute from './ReglAttribute';
import ReglElements from './ReglElements';
/**
* adaptor for regl.DrawCommand
*/
export default class ReglModel implements IModel {
private reGl: regl.Regl;
private drawCommand: regl.DrawCommand;
private uniforms: {
[key: string]: IUniform;
} = {};
constructor(reGl: regl.Regl, options: IModelInitializationOptions) {
this.reGl = reGl;
const {
vs,
fs,
attributes,
uniforms,
elements,
} = options;
const reglUniforms: { [key: string]: IUniform } = {};
if (uniforms) {
this.uniforms = this.extractUniforms(uniforms);
Object.keys(uniforms).forEach((uniformName) => {
// use regl prop API
// @ts-ignore
reglUniforms[uniformName] = reGl.prop(uniformName);
});
}
const reglAttributes: { [key: string]: regl.Attribute } = {};
Object.keys(attributes).forEach((name: string) => {
reglAttributes[name] = (attributes[name] as ReglAttribute).get();
});
const drawParams: regl.DrawConfig = {
attributes: reglAttributes,
frag: fs,
uniforms: reglUniforms,
vert: vs,
primitive: 'triangles'
};
drawParams.elements = (elements as ReglElements).get();
this.drawCommand = reGl(drawParams);
}
public addUniforms(uniforms: { [key: string]: IUniform }) {
this.uniforms = {
...this.uniforms,
...this.extractUniforms(uniforms),
};
}
public draw(options: IModelDrawOptions) {
this.drawCommand(this.uniforms);
}
/**
* , eg:
* a: { b: 1 } -> 'a.b'
* a: [ { b: 1 } ] -> 'a[0].b'
*/
private extractUniforms(uniforms: { [key: string]: IUniform }): {
[key: string]: IUniform;
} {
const extractedUniforms = {};
Object.keys(uniforms).forEach((uniformName) => {
this.extractUniformsRecursively(
uniformName,
uniforms[uniformName],
extractedUniforms,
'',
);
});
return extractedUniforms;
}
private extractUniformsRecursively(
uniformName: string,
uniformValue: IUniform,
uniforms: {
[key: string]: IUniform;
},
prefix: string,
) {
if (
uniformValue === null ||
typeof uniformValue === 'number' || // u_A: 1
typeof uniformValue === 'boolean' || // u_A: false
(Array.isArray(uniformValue) && typeof uniformValue[0] === 'number') || // u_A: [1, 2, 3]
isTypedArray(uniformValue) || // u_A: Float32Array
// @ts-ignore
uniformValue === '' ||
'resize' in uniformValue
) {
uniforms[`${prefix && prefix + '.'}${uniformName}`] = uniformValue;
return;
}
// u_Struct.a.b.c
if (isPlainObject(uniformValue)) {
Object.keys(uniformValue).forEach((childName) => {
this.extractUniformsRecursively(
childName,
// @ts-ignore
uniformValue[childName],
uniforms,
`${prefix && prefix + '.'}${uniformName}`,
);
});
}
// u_Struct[0].a
if (Array.isArray(uniformValue)) {
uniformValue.forEach((child, idx) => {
Object.keys(child).forEach((childName) => {
this.extractUniformsRecursively(
childName,
// @ts-ignore
child[childName],
uniforms,
`${prefix && prefix + '.'}${uniformName}[${idx}]`,
);
});
});
}
}
}

View File

@ -3,109 +3,57 @@
* @see https://github.com/regl-project/regl/blob/gh-pages/API.md * @see https://github.com/regl-project/regl/blob/gh-pages/API.md
*/ */
import { import {
IAttribute,
IAttributeInitializationOptions, IAttributeInitializationOptions,
IBuffer,
IBufferInitializationOptions, IBufferInitializationOptions,
IClearOptions, IClearOptions,
IElements,
IElementsInitializationOptions, IElementsInitializationOptions,
IExtensions, IExtensions,
IFramebuffer,
IFramebufferInitializationOptions,
IModel, IModel,
IModelInitializationOptions, IModelInitializationOptions,
IReadPixelsOptions,
IRenderConfig,
IRendererService,
ITexture2D,
ITexture2DInitializationOptions,
} from '@antv/l7-core'; } from '@antv/l7-core';
import { isMini } from '@antv/l7-utils';
import { injectable } from 'inversify'; import { injectable } from 'inversify';
import regl from 'l7regl'; import regl from 'l7regl';
import 'reflect-metadata'; import 'reflect-metadata';
import ReglAttribute from './ReglAttribute';
import ReglBuffer from './ReglBuffer';
import ReglElements from './ReglElements';
import ReglFramebuffer from './ReglFramebuffer';
import ReglModel from './ReglModel';
import ReglTexture2D from './ReglTexture2D';
/** /**
* regl renderer * regl renderer
*/ */
@injectable() @injectable()
export default class ReglRendererService implements IRendererService { export default class ReglRendererService {
public extensionObject: IExtensions; public extensionObject: IExtensions;
private gl: regl.Regl; private gl: regl.Regl;
private $container: HTMLDivElement | null;
private canvas: HTMLCanvasElement;
private width: number;
private height: number;
private isDirty: boolean;
public async init( public init(
canvas: HTMLCanvasElement, canvas: HTMLCanvasElement,
cfg: IRenderConfig, ) {
gl?: regl.Regl,
): Promise<void> { this.gl = regl({
// this.$container = $container; // creates a full screen canvas element and WebGLRenderingContext
this.canvas = canvas; // var regl = require('regl')()
if (gl) { canvas: canvas,
this.gl = gl; attributes: {
} else { alpha: true,
// tslint:disable-next-line:typedef antialias: true,
this.gl = await new Promise((resolve, reject) => { premultipliedAlpha: true,
regl({ preserveDrawingBuffer: false,
canvas: this.canvas, stencil: false,
attributes: { },
alpha: true, // TODO: use extensions
// use TAA instead of MSAA extensions: [
// @see https://www.khronos.org/registry/webgl/specs/1.0/#5.2.1 'OES_element_index_uint',
antialias: cfg.antialias, 'OES_standard_derivatives', // wireframe
premultipliedAlpha: true, 'ANGLE_instanced_arrays', // VSM shadow map
preserveDrawingBuffer: cfg.preserveDrawingBuffer, ],
optionalExtensions: [
stencil: cfg.stencil, 'oes_texture_float_linear',
}, 'OES_texture_float',
// TODO: use extensions 'EXT_texture_filter_anisotropic',
extensions: [ 'EXT_blend_minmax',
'OES_element_index_uint', 'WEBGL_depth_texture',
'OES_standard_derivatives', // wireframe ],
'ANGLE_instanced_arrays', // VSM shadow map profile: true,
], });
optionalExtensions: [ return this.gl;
'oes_texture_float_linear',
'OES_texture_float',
'EXT_texture_filter_anisotropic',
'EXT_blend_minmax',
'WEBGL_depth_texture',
],
profile: true,
onDone: (err: Error | null, r?: regl.Regl | undefined): void => {
if (err || !r) {
reject(err);
}
// @ts-ignore
resolve(r);
},
});
});
}
this.extensionObject = {
OES_texture_float: this.testExtension('OES_texture_float'),
};
}
public getPointSizeRange() {
return this.gl._gl.getParameter(this.gl._gl.ALIASED_POINT_SIZE_RANGE);
}
public testExtension(name: string) {
// OES_texture_float
return !!this.getGLContext().getExtension(name);
} }
public createModel = (options: IModelInitializationOptions): IModel => public createModel = (options: IModelInitializationOptions): IModel =>
@ -113,172 +61,108 @@ export default class ReglRendererService implements IRendererService {
public createAttribute = ( public createAttribute = (
options: IAttributeInitializationOptions, options: IAttributeInitializationOptions,
): IAttribute => new ReglAttribute(this.gl, options); ) => {
const { buffer, offset, stride, normalized, size, divisor } = options;
const attribute = {
buffer,
offset: offset || 0,
stride: stride || 0,
normalized: normalized || false,
divisor: divisor || 0,
};
public createBuffer = (options: IBufferInitializationOptions): IBuffer => if (size) {
new ReglBuffer(this.gl, options); attribute.size = size;
}
return attribute;
}
public createBuffer = (options: IBufferInitializationOptions) => {
const { data } = options;
return this.gl.buffer({
data,
usage: 'static',
});
}
public createElements = ( public createElements = (
options: IElementsInitializationOptions, options: IElementsInitializationOptions,
): IElements => new ReglElements(this.gl, options);
public createTexture2D = (
options: ITexture2DInitializationOptions,
): ITexture2D => new ReglTexture2D(this.gl, options);
public createFramebuffer = (options: IFramebufferInitializationOptions) =>
new ReglFramebuffer(this.gl, options);
public useFramebuffer = (
framebuffer: IFramebuffer | null,
drawCommands: () => void,
) => { ) => {
this.gl({
framebuffer: framebuffer ? (framebuffer as ReglFramebuffer).get() : null, const { data, count } = options;
})(drawCommands); return this.gl.elements({
data,
usage: "static",
count,
});
}; };
public clear = (options: IClearOptions) => { public clear = (options: IClearOptions) => {
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#clear-the-draw-buffer const { color, depth, stencil } = options;
const { color, depth, stencil, framebuffer = null } = options;
const reglClearOptions: regl.ClearOptions = { const reglClearOptions: regl.ClearOptions = {
color, color,
depth, depth,
stencil, stencil,
}; };
reglClearOptions.framebuffer =
framebuffer === null
? framebuffer
: (framebuffer as ReglFramebuffer).get();
this.gl?.clear(reglClearOptions); this.gl?.clear(reglClearOptions);
}; };
}
public viewport = ({
x, class ReglModel {
y, private drawCommand: any;
width, private uniforms: any = {};
height,
}: { constructor(reGl: any, options: any) {
x: number; const {
y: number; vs,
width: number; fs,
height: number; attributes,
}) => { uniforms,
// use WebGL context directly elements,
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#unsafe-escape-hatch } = options;
this.gl._gl.viewport(x, y, width, height); const reglUniforms: any = {};
this.width = width;
this.height = height; this.uniforms = this.extractUniforms(uniforms);
this.gl._refresh(); Object.keys(uniforms).forEach((uniformName) => {
}; // pass data into regl
reglUniforms[uniformName] = reGl.prop(uniformName);
public readPixels = (options: IReadPixelsOptions) => { });
const { framebuffer, x, y, width, height } = options;
const readPixelsOptions: regl.ReadOptions = {
x, const reglAttributes: any = {};
y, Object.keys(attributes).forEach((name: string) => {
width, reglAttributes[name] = attributes[name];
height, });
}; const drawParams: any = {
if (framebuffer) { attributes: reglAttributes,
readPixelsOptions.framebuffer = (framebuffer as ReglFramebuffer).get(); frag: fs,
} uniforms: reglUniforms,
return this.gl.read(readPixelsOptions); vert: vs,
}; primitive: 'triangles'
};
public getViewportSize = () => {
return { drawParams.elements = elements;
width: this.gl._gl.drawingBufferWidth, this.drawCommand = reGl(drawParams);
height: this.gl._gl.drawingBufferHeight, }
};
}; public addUniforms(uniforms: any ) {
this.uniforms = {
public getContainer = () => { ...this.uniforms,
if (isMini) { ...this.extractUniforms(uniforms),
return this.canvas; };
} else { }
return this.canvas?.parentElement;
} public draw(options: any) {
}; this.drawCommand(this.uniforms);
}
public getCanvas = () => {
// return this.$container?.getElementsByTagName('canvas')[0] || null; private extractUniforms(uniforms:any): any {
return this.canvas; const extractedUniforms = {};
}; Object.keys(uniforms).forEach((uniformName) => {
extractedUniforms[uniformName] = uniforms[uniformName];
public getGLContext = () => { });
return this.gl._gl;
}; return extractedUniforms;
}
// TODO: 临时方法
public setState() {
this.gl({
cull: {
enable: false,
face: 'back',
},
viewport: {
x: 0,
y: 0,
height: this.width,
width: this.height,
},
blend: {
enable: true,
equation: 'add',
},
framebuffer: null,
});
this.gl._refresh();
}
public setBaseState() {
this.gl({
cull: {
enable: false,
face: 'back',
},
viewport: {
x: 0,
y: 0,
height: this.width,
width: this.height,
},
blend: {
enable: false,
equation: 'add',
},
framebuffer: null,
});
this.gl._refresh();
}
public setCustomLayerDefaults() {
const gl = this.getGLContext();
gl.disable(gl.CULL_FACE);
}
public setDirty(flag: boolean): void {
this.isDirty = flag;
}
public getDirty(): boolean {
return this.isDirty;
}
public destroy = () => {
// this.canvas = null 清除对 webgl 实例的引用
// @ts-ignore
this.canvas = null;
// make sure release webgl context
this.gl?._gl?.getExtension('WEBGL_lose_context')?.loseContext();
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#clean-up
this.gl.destroy();
// @ts-ignore
this.gl = null;
};
} }

View File

@ -100,17 +100,13 @@ class Scene
this.popupService = sceneContainer.get<IPopupService>(TYPES.IPopupService); this.popupService = sceneContainer.get<IPopupService>(TYPES.IPopupService);
this.boxSelect = new BoxSelect(this, {}); this.boxSelect = new BoxSelect(this, {});
if (isMini) { this.initComponent(id);
this.sceneService.initMiniScene(config);
} else {
this.initComponent(id);
// 初始化 scene // 初始化 scene
this.sceneService.init(config); this.sceneService.init(config);
// TODO: 初始化组件 // TODO: 初始化组件
this.initControl(); this.initControl();
}
} }
public get map() { public get map() {