diff --git a/packages-user/client-modules/src/render/map/element.ts b/packages-user/client-modules/src/render/map/element.ts index ad96947..680017f 100644 --- a/packages-user/client-modules/src/render/map/element.ts +++ b/packages-user/client-modules/src/render/map/element.ts @@ -44,6 +44,8 @@ export class MapRender extends RenderItem { this.renderer.setCellSize(CELL_WIDTH, CELL_HEIGHT); this.renderer.setRenderSize(MAP_WIDTH, MAP_HEIGHT); + this.delegateTicker(time => this.renderer.tick(time)); + gl.viewport(0, 0, this.canvas.width, this.canvas.height); } @@ -73,8 +75,6 @@ export class MapRender extends RenderItem { } protected render(canvas: MotaOffscreenCanvas2D): void { - console.log('----- render start -----'); - console.time('map-element-render'); this.renderer.render(this.gl); diff --git a/packages-user/client-modules/src/render/map/renderer.ts b/packages-user/client-modules/src/render/map/renderer.ts index a5191b1..bbe6ceb 100644 --- a/packages-user/client-modules/src/render/map/renderer.ts +++ b/packages-user/client-modules/src/render/map/renderer.ts @@ -315,10 +315,8 @@ export class MapRenderer return a.zIndex - b.zIndex; }); this.sortedLayers.forEach((v, i) => this.layerIndexMap.set(v, i)); - this.forEachHook((hook, controller) => { - hook.onUpdate?.(controller); - }); this.layerListDirty = true; + this.requestUpdate(); } private updateAllLayers() { @@ -381,6 +379,7 @@ export class MapRenderer this.contextData.backgroundHeight ); this.layerAllDirty = true; + this.requestUpdate(); } //#endregion @@ -421,19 +420,25 @@ export class MapRenderer } configBackground(config: Partial): void { + let needUpdate = false; if (!isNil(config.renderWidth)) { + needUpdate = true; this.backRenderWidth = config.renderWidth; } if (!isNil(config.renderHeight)) { + needUpdate = true; this.backRenderHeight = config.renderHeight; } if (!isNil(config.repeatX)) { + needUpdate = true; this.backRepeatModeX = config.repeatX; } if (!isNil(config.repeatY)) { + needUpdate = true; this.backRepeatModeY = config.repeatY; } if (!isNil(config.useImageSize)) { + needUpdate = true; this.backUseImageSize = config.useImageSize; } if (!isNil(config.frameSpeed)) { @@ -445,6 +450,9 @@ export class MapRenderer this.contextData.backgroundWidth, this.contextData.backgroundHeight ); + if (needUpdate) { + this.requestUpdate(); + } } getBackgroundConfig(): Readonly { @@ -475,6 +483,7 @@ export class MapRenderer this.sortedLayers.forEach(v => { this.vertex.updateArea(v, 0, 0, this.mapWidth, this.mapHeight); }); + this.requestUpdate(); } setCellSize(width: number, height: number): void { @@ -483,6 +492,7 @@ export class MapRenderer this.sortedLayers.forEach(v => { this.vertex.updateArea(v, 0, 0, this.mapWidth, this.mapHeight); }); + this.requestUpdate(); } configRendering(config: Partial): void { @@ -511,9 +521,7 @@ export class MapRenderer this.frameSpeed = config.frameSpeed; } if (needUpdate) { - this.sortedLayers.forEach(v => { - this.vertex.updateArea(v, 0, 0, this.mapWidth, this.mapHeight); - }); + this.requestUpdate(); } } @@ -1188,9 +1196,7 @@ export class MapRenderer ); this.backgroundPending = false; gl.bindTexture(gl.TEXTURE_2D_ARRAY, null); - this.forEachHook((hook, controller) => { - hook.onUpdate?.(controller); - }); + this.requestUpdate(); } render(): void { @@ -1200,7 +1206,6 @@ export class MapRenderer logger.error(31); return; } - console.time('render-map'); const { backVAO, @@ -1221,7 +1226,6 @@ export class MapRenderer insTexDataAttribLocation: texData } = data; - console.time('layer-check'); // 图层检查 if (this.layerSizeDirty) { this.vertex.resizeMap(); @@ -1236,28 +1240,18 @@ export class MapRenderer this.layerAllDirty = false; } this.vertex.checkRebuild(); - console.timeEnd('layer-check'); - - console.time('texture-check'); // 数据检查 this.checkTexture(gl, data); this.checkTileVertexArray(gl, data); - console.timeEnd('texture-check'); - - console.time('update-block-cache'); - const area = this.viewport.getRenderArea(); area.blockList.forEach(v => { this.vertex.updateBlockCache(v); v.data.render(); }); - console.timeEnd('update-block-cache'); - if (area.dirty.length > 0) { - console.time('upload-block-buffer'); // 如果需要更新顶点数组... const array = this.vertex.getVertexArray(); gl.bindBuffer(gl.ARRAY_BUFFER, instancedBuffer); @@ -1272,11 +1266,9 @@ export class MapRenderer ); }); gl.bindBuffer(gl.ARRAY_BUFFER, null); - console.timeEnd('upload-block-buffer'); } // 背景 - console.time('render-call'); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.useProgram(backProgram); if (this.needUpdateBackgroundFrame) { @@ -1333,8 +1325,6 @@ export class MapRenderer }); gl.bindVertexArray(null); gl.bindTexture(gl.TEXTURE_2D_ARRAY, null); - console.timeEnd('render-call'); - console.timeEnd('render-map'); } //#endregion @@ -1357,9 +1347,7 @@ export class MapRenderer h: number ) { this.vertex.updateArea(layer, x, y, w, h); - this.forEachHook((hook, controller) => { - hook.onUpdate?.(controller); - }); + this.requestUpdate(); } /** @@ -1371,9 +1359,7 @@ export class MapRenderer */ updateLayerBlock(layer: IMapLayer, block: number, x: number, y: number) { this.vertex.updateBlock(layer, block, x, y); - this.forEachHook((hook, controller) => { - hook.onUpdate?.(controller); - }); + this.requestUpdate(); } //#endregion @@ -1414,6 +1400,7 @@ export class MapRenderer map.set(v, item); }); this.vertex.reduceMoving(half, map); + this.requestUpdate(); } /** @@ -1453,6 +1440,7 @@ export class MapRenderer this.movingBlock.add(moving); this.movingIndexMap.set(index, moving); this.vertex.updateMoving(moving, true); + this.requestUpdate(); return moving; } @@ -1469,6 +1457,7 @@ export class MapRenderer this.movingBlock.delete(block); this.movingIndexMap.delete(block.index); this.vertex.deleteMoving(block); + this.requestUpdate(); } hasMoving(moving: IMovingBlock): boolean { @@ -1495,18 +1484,26 @@ export class MapRenderer //#region 其他方法 + private requestUpdate() { + this.forEachHook((hook, controller) => { + hook.onUpdate?.(controller); + }); + } + getTimestamp(): number { return this.timestamp; } tick(timestamp: number) { this.timestamp = timestamp; + let update = false; // 移动数组 const expandDT = timestamp - this.lastExpandTime; if (expandDT > MOVING_TOLERANCE * 1000) { this.reduceMoving(); this.lastExpandTime = timestamp; + update = true; } // 背景 @@ -1516,13 +1513,16 @@ export class MapRenderer this.backgroundFrame %= this.backgroundFrameCount; this.backLastFrame = timestamp; this.needUpdateBackgroundFrame = true; + update = true; } // 地图帧动画 const frameDT = timestamp - this.lastFrameTime; if (frameDT > this.frameSpeed) { + this.lastFrameTime = timestamp; this.frameCounter++; this.needUpdateFrameCounter = true; + update = true; } // 图块移动 @@ -1533,14 +1533,17 @@ export class MapRenderer if (move) toUpdate.push(v); }); this.vertex.updateMovingList(toUpdate, false); + update = true; + } + + if (update) { + this.requestUpdate(); } } updateTransform(): void { this.needUpdateTransform = true; - this.forEachHook((hook, controller) => { - hook.onUpdate?.(controller); - }); + this.requestUpdate(); } //#endregion diff --git a/packages-user/client-modules/src/render/map/types.ts b/packages-user/client-modules/src/render/map/types.ts index 67ed1ba..6572432 100644 --- a/packages-user/client-modules/src/render/map/types.ts +++ b/packages-user/client-modules/src/render/map/types.ts @@ -426,6 +426,12 @@ export interface IMapRenderer extends IHookable { * @param y 图块纵坐标 */ setTileAlpha(layer: IMapLayer, alpha: number, x: number, y: number): void; + + /** + * 进行一帧更新 + * @param timestamp 时间戳 + */ + tick(timestamp: number): void; } export interface IMapVertexArray { diff --git a/packages-user/client-modules/src/render/map/viewport.ts b/packages-user/client-modules/src/render/map/viewport.ts index 5c17309..96b5624 100644 --- a/packages-user/client-modules/src/render/map/viewport.ts +++ b/packages-user/client-modules/src/render/map/viewport.ts @@ -59,42 +59,26 @@ export class MapViewport implements IMapViewportController { if (widthOne && heightOne) { // 只能看到一个分块 const block = this.vertex.block.getBlockByLoc(blockLeft, blockTop)!; - if (block.data.dirty || block.data.renderDirty) { - blockList.push(block); - } + blockList.push(block); } else if (widthOne) { // 看到的区域分块宽度是 1 for (let ny = blockTop; ny <= blockBottom; ny++) { const block = this.vertex.block.getBlockByLoc(blockLeft, ny)!; - if (block.data.dirty || block.data.renderDirty) { - blockList.push(block); - } + blockList.push(block); } } else if (heightOne) { // 看到的区域分块高度是 1 for (let nx = blockLeft; nx <= blockRight; nx++) { const block = this.vertex.block.getBlockByLoc(nx, blockTop)!; - if (block.data.dirty || block.data.renderDirty) { - blockList.push(block); - } + blockList.push(block); } } else { // 看到的区域分块宽高都不是 1 // 使用这种方式的话,索引在换行之前都是连续的,方便整合 for (let ny = blockTop; ny <= blockBottom; ny++) { - const first = this.vertex.block.getBlockByLoc(blockLeft, ny)!; - const last = this.vertex.block.getBlockByLoc(blockRight, ny)!; - if (first.data.dirty) { - blockList.push(first); - } - if (last.data.dirty && first !== last) { - blockList.push(last); - } - for (let nx = blockLeft + 1; nx < blockRight; nx++) { + for (let nx = blockLeft; nx <= blockRight; nx++) { const block = this.vertex.block.getBlockByLoc(nx, ny)!; - if (block.data.dirty) { - blockList.push(block); - } + blockList.push(block); } } } @@ -143,7 +127,7 @@ export class MapViewport implements IMapViewportController { return { render: renderArea, dirty: updateArea, - blockList + blockList: blockList.filter(v => v.data.dirty) }; }