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

View File

@ -50,20 +50,10 @@ export default class StyleAttribute implements IStyleAttribute {
Object.assign(this, options);
}
public mapping(params: unknown[]): unknown[] {
/**
* callback null , callback
*/
if (this.scale?.callback) {
// 使用用户返回的值处理
const ret = this.scale?.callback(...params);
if (!isNil(ret)) {
return [ret];
}
}
// 没有 callback 或者用户 callback 返回值为空,则使用默认的逻辑处理
return this.defaultCallback(params);
public mapping(){
// console.log(this.scale?.defaultValues);
return this.scale?.defaultValues;
}
public resetDescriptor() {
@ -71,18 +61,4 @@ export default class StyleAttribute implements IStyleAttribute {
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 gl: any
private hooks: {
init: AsyncSeriesHook;
};
@ -182,12 +184,11 @@ export default class Scene extends EventEmitter implements ISceneService {
this.$container,
) as HTMLCanvasElement;
this.setCanvas();
await this.rendererService.init(
// @ts-ignore
this.gl = this.rendererService.init(
this.canvas,
this.configService.getSceneConfig(this.id) as IRenderConfig,
sceneConfig.gl,
);
this.initContainer();
elementResizeEvent(
@ -431,15 +432,10 @@ export default class Scene extends EventEmitter implements ISceneService {
if (canvas) {
canvas.width = w * pixelRatio;
canvas.height = h * pixelRatio;
// canvas.style.width = `${w}px`;
// canvas.style.height = `${h}px`;
}
this.rendererService.viewport({
x: 0,
y: 0,
width: pixelRatio * w,
height: pixelRatio * h,
});
// set view port
this.gl._gl.viewport(0, 0, pixelRatio * w, pixelRatio * h);
}
private setCanvas() {

View File

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

View File

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

View File

@ -4,7 +4,6 @@ import {
IBuffer,
} from '@antv/l7-core';
import regl from 'l7regl';
import ReglBuffer from './ReglBuffer';
/**
* @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;
this.buffer = buffer;
this.attribute = {
buffer: (buffer as ReglBuffer).get(),
buffer,
offset: offset || 0,
stride: stride || 0,
normalized: normalized || false,
@ -33,16 +32,4 @@ export default class ReglAttribute implements IAttribute {
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;
}
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 { 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
*/
import {
IAttribute,
IAttributeInitializationOptions,
IBuffer,
IBufferInitializationOptions,
IClearOptions,
IElements,
IElementsInitializationOptions,
IExtensions,
IFramebuffer,
IFramebufferInitializationOptions,
IModel,
IModelInitializationOptions,
IReadPixelsOptions,
IRenderConfig,
IRendererService,
ITexture2D,
ITexture2DInitializationOptions,
} from '@antv/l7-core';
import { isMini } from '@antv/l7-utils';
import { injectable } from 'inversify';
import regl from 'l7regl';
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
*/
@injectable()
export default class ReglRendererService implements IRendererService {
export default class ReglRendererService {
public extensionObject: IExtensions;
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,
cfg: IRenderConfig,
gl?: regl.Regl,
): Promise<void> {
// this.$container = $container;
this.canvas = canvas;
if (gl) {
this.gl = gl;
} else {
// tslint:disable-next-line:typedef
this.gl = await new Promise((resolve, reject) => {
regl({
canvas: this.canvas,
attributes: {
alpha: true,
// use TAA instead of MSAA
// @see https://www.khronos.org/registry/webgl/specs/1.0/#5.2.1
antialias: cfg.antialias,
premultipliedAlpha: true,
preserveDrawingBuffer: cfg.preserveDrawingBuffer,
stencil: cfg.stencil,
},
// 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,
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);
) {
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,
});
return this.gl;
}
public createModel = (options: IModelInitializationOptions): IModel =>
@ -113,172 +61,108 @@ export default class ReglRendererService implements IRendererService {
public createAttribute = (
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 =>
new ReglBuffer(this.gl, options);
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,
): 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,
})(drawCommands);
const { data, count } = options;
return this.gl.elements({
data,
usage: "static",
count,
});
};
public clear = (options: IClearOptions) => {
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#clear-the-draw-buffer
const { color, depth, stencil, framebuffer = null } = options;
const { color, depth, stencil } = options;
const reglClearOptions: regl.ClearOptions = {
color,
depth,
stencil,
};
reglClearOptions.framebuffer =
framebuffer === null
? framebuffer
: (framebuffer as ReglFramebuffer).get();
this.gl?.clear(reglClearOptions);
};
public viewport = ({
x,
y,
width,
height,
}: {
x: number;
y: number;
width: number;
height: number;
}) => {
// use WebGL context directly
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#unsafe-escape-hatch
this.gl._gl.viewport(x, y, width, height);
this.width = width;
this.height = height;
this.gl._refresh();
};
public readPixels = (options: IReadPixelsOptions) => {
const { framebuffer, x, y, width, height } = options;
const readPixelsOptions: regl.ReadOptions = {
x,
y,
width,
height,
};
if (framebuffer) {
readPixelsOptions.framebuffer = (framebuffer as ReglFramebuffer).get();
}
return this.gl.read(readPixelsOptions);
};
public getViewportSize = () => {
return {
width: this.gl._gl.drawingBufferWidth,
height: this.gl._gl.drawingBufferHeight,
};
};
public getContainer = () => {
if (isMini) {
return this.canvas;
} else {
return this.canvas?.parentElement;
}
};
public getCanvas = () => {
// return this.$container?.getElementsByTagName('canvas')[0] || null;
return this.canvas;
};
public getGLContext = () => {
return this.gl._gl;
};
// 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;
};
}
class ReglModel {
private drawCommand: any;
private uniforms: any = {};
constructor(reGl: any, options: any) {
const {
vs,
fs,
attributes,
uniforms,
elements,
} = options;
const reglUniforms: any = {};
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];
});
const drawParams: any = {
attributes: reglAttributes,
frag: fs,
uniforms: reglUniforms,
vert: vs,
primitive: 'triangles'
};
drawParams.elements = elements;
this.drawCommand = reGl(drawParams);
}
public addUniforms(uniforms: any ) {
this.uniforms = {
...this.uniforms,
...this.extractUniforms(uniforms),
};
}
public draw(options: any) {
this.drawCommand(this.uniforms);
}
private extractUniforms(uniforms:any): any {
const extractedUniforms = {};
Object.keys(uniforms).forEach((uniformName) => {
extractedUniforms[uniformName] = uniforms[uniformName];
});
return extractedUniforms;
}
}

View File

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