diff --git a/packages/core/src/services/interaction/PickingService.ts b/packages/core/src/services/interaction/PickingService.ts index 7e8d639db4..4a04ab3693 100644 --- a/packages/core/src/services/interaction/PickingService.ts +++ b/packages/core/src/services/interaction/PickingService.ts @@ -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( diff --git a/packages/core/src/services/layer/StyleAttribute.ts b/packages/core/src/services/layer/StyleAttribute.ts index 8c7e42626d..edbf346d22 100644 --- a/packages/core/src/services/layer/StyleAttribute.ts +++ b/packages/core/src/services/layer/StyleAttribute.ts @@ -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; - }); - }; } diff --git a/packages/core/src/services/scene/SceneService.ts b/packages/core/src/services/scene/SceneService.ts index b259627395..6aa5212c39 100644 --- a/packages/core/src/services/scene/SceneService.ts +++ b/packages/core/src/services/scene/SceneService.ts @@ -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() { diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index d4978ed5ea..838a76b1bd 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -695,8 +695,10 @@ export default class BaseLayer 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 矩阵、缩放等级 diff --git a/packages/layers/src/point/models/fill.ts b/packages/layers/src/point/models/fill.ts index 62de56c921..484ae47819 100644 --- a/packages/layers/src/point/models/fill.ts +++ b/packages/layers/src/point/models/fill.ts @@ -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); } diff --git a/packages/renderer/src/regl/ReglAttribute.ts b/packages/renderer/src/regl/ReglAttribute.ts index 15f20b0848..03d082fc86 100644 --- a/packages/renderer/src/regl/ReglAttribute.ts +++ b/packages/renderer/src/regl/ReglAttribute.ts @@ -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(); - } } diff --git a/packages/renderer/src/regl/ReglBuffer.ts b/packages/renderer/src/regl/ReglBuffer.ts index a880e530ed..1299f558d6 100644 --- a/packages/renderer/src/regl/ReglBuffer.ts +++ b/packages/renderer/src/regl/ReglBuffer.ts @@ -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); - } } diff --git a/packages/renderer/src/regl/ReglElements.ts b/packages/renderer/src/regl/ReglElements.ts index 6c1b2cddc3..00199bb30b 100644 --- a/packages/renderer/src/regl/ReglElements.ts +++ b/packages/renderer/src/regl/ReglElements.ts @@ -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(); - } -} diff --git a/packages/renderer/src/regl/ReglModel.ts b/packages/renderer/src/regl/ReglModel.ts index 1f74ea85c4..e69de29bb2 100644 --- a/packages/renderer/src/regl/ReglModel.ts +++ b/packages/renderer/src/regl/ReglModel.ts @@ -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}]`, - ); - }); - }); - } - } -} diff --git a/packages/renderer/src/regl/index.ts b/packages/renderer/src/regl/index.ts index b62a8f3799..8386b23db6 100644 --- a/packages/renderer/src/regl/index.ts +++ b/packages/renderer/src/regl/index.ts @@ -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 { - // 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; + } } diff --git a/packages/scene/src/index.ts b/packages/scene/src/index.ts index a5cd45e792..c6fb8e7c5d 100644 --- a/packages/scene/src/index.ts +++ b/packages/scene/src/index.ts @@ -100,17 +100,13 @@ class Scene this.popupService = sceneContainer.get(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() {