From 0d8667aa3a44f629bd18e29ce0f3a0c01cf92095 Mon Sep 17 00:00:00 2001 From: "A.Olokhtonov" Date: Tue, 7 Nov 2023 22:28:19 +0300 Subject: [PATCH] Use TypedArray for culling. This is up to 10 times faster! --- client/index.js | 2 +- client/math.js | 26 +++++++++++++++++++++++--- client/webgl_draw.js | 8 ++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/client/index.js b/client/index.js index 7efa149..be8101f 100644 --- a/client/index.js +++ b/client/index.js @@ -173,7 +173,7 @@ function main() { }, 'players': {}, - 'onscreen_segments': [], + 'onscreen_segments': null, }; const context = { diff --git a/client/math.js b/client/math.js index 39c7d7a..73d31c8 100644 --- a/client/math.js +++ b/client/math.js @@ -217,8 +217,20 @@ function quad_fully_onscreen(screen, bbox) { function segments_onscreen(state, context) { // TODO: handle stroke width + + if (state.onscreen_segments === null) { + let total_points = 0; - state.onscreen_segments.length = 0; + for (const event of state.events) { + if (event.type === EVENT.STROKE && !event.deleted) { + total_points += event.points.length - 1; + } + } + + state.onscreen_segments = new Uint32Array(total_points * 6); + } + + let at = 0; const screen_topleft = screen_to_canvas(state, {'x': 0, 'y': 0}); const screen_bottomright = screen_to_canvas(state, {'x': context.canvas.width, 'y': context.canvas.height}); @@ -240,12 +252,20 @@ function segments_onscreen(state, context) { if (fully_onscreen || segment_interesects_quad(a, b, screen_topleft, screen_bottomright, screen_topright, screen_bottomleft)) { let base = head + j * 4; // We draw quads as [1, 2, 3, 4, 3, 2] - state.onscreen_segments.push(base + 0, base + 1, base + 2); - state.onscreen_segments.push(base + 3, base + 2, base + 1); + state.onscreen_segments[at + 0] = base + 0; + state.onscreen_segments[at + 1] = base + 1; + state.onscreen_segments[at + 2] = base + 2; + state.onscreen_segments[at + 3] = base + 3; + state.onscreen_segments[at + 4] = base + 2; + state.onscreen_segments[at + 5] = base + 1; + + at += 6; } } } head += (event.points.length - 1) * 4; } } + + return at; } diff --git a/client/webgl_draw.js b/client/webgl_draw.js index ef87a4c..7703e50 100644 --- a/client/webgl_draw.js +++ b/client/webgl_draw.js @@ -69,16 +69,16 @@ function draw(state, context) { } const before_clip = performance.now(); - segments_onscreen(state, context); + const index_count = segments_onscreen(state, context); const after_clip = performance.now(); console.debug('clip', after_clip - before_clip); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers['b_packed_static_index']); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(state.onscreen_segments), gl.DYNAMIC_DRAW); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(state.onscreen_segments.buffer, 0, index_count), gl.DYNAMIC_DRAW); const after_index_uploads = performance.now(); - console.debug('index upload', after_index_uploads - after_clip); + // console.debug('index upload', after_index_uploads - after_clip); - gl.drawElements(gl.TRIANGLES, state.onscreen_segments.length, gl.UNSIGNED_INT, 0); + gl.drawElements(gl.TRIANGLES, index_count, gl.UNSIGNED_INT, 0); } if (dynamic_points > 0) {