Browse Source

Faster clipping

ssao
A.Olokhtonov 1 year ago
parent
commit
e41997563f
  1. 1
      client/index.js
  2. 22
      client/math.js
  3. 52
      client/webgl_draw.js
  4. 4
      client/webgl_shaders.js

1
client/index.js

@ -173,6 +173,7 @@ function main() { @@ -173,6 +173,7 @@ function main() {
},
'players': {},
'onscreen_segments': [],
};
const context = {

22
client/math.js

@ -207,8 +207,19 @@ function quad_onscreen(screen, bbox) { @@ -207,8 +207,19 @@ function quad_onscreen(screen, bbox) {
return false;
}
function quad_fully_onscreen(screen, bbox) {
if (screen.x1 < bbox.x1 && screen.x2 > bbox.x2 && screen.y1 < bbox.y1 && screen.y2 > bbox.y2) {
return true;
}
return false;
}
function segments_onscreen(state, context) {
const result = [];
// TODO: handle stroke width
state.onscreen_segments.length = 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});
const screen_topright = { 'x': screen_bottomright.x, 'y': screen_topleft.y };
@ -221,21 +232,20 @@ function segments_onscreen(state, context) { @@ -221,21 +232,20 @@ function segments_onscreen(state, context) {
const event = state.events[i];
if (event.type === EVENT.STROKE && !event.deleted) {
if (quad_onscreen(screen, event.bbox)) {
const fully_onscreen = quad_fully_onscreen(screen, event.bbox);
for (let j = 0; j < event.points.length - 1; ++j) {
const a = event.points[j + 0];
const b = event.points[j + 1];
if (segment_interesects_quad(a, b, screen_topleft, screen_bottomright, screen_topright, screen_bottomleft)) {
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]
result.push(base + 0, base + 1, base + 2);
result.push(base + 3, base + 2, base + 1);
state.onscreen_segments.push(base + 0, base + 1, base + 2);
state.onscreen_segments.push(base + 3, base + 2, base + 1);
}
}
}
head += (event.points.length - 1) * 4;
}
}
return result;
}

52
client/webgl_draw.js

@ -11,9 +11,13 @@ function draw(state, context) { @@ -11,9 +11,13 @@ function draw(state, context) {
const gl = context.gl;
const width = window.innerWidth;
const height = window.innerHeight;
let query = null;
const frame_start = performance.now();
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
if (context.gpu_timer_ext !== null) {
query = gl.createQuery();
gl.beginQuery(context.gpu_timer_ext.TIME_ELAPSED_EXT, query);
}
let locations;
let buffers;
@ -64,11 +68,17 @@ function draw(state, context) { @@ -64,11 +68,17 @@ function draw(state, context) {
context.static_upload_from = context.static_serializer.offset;
}
const indices = segments_onscreen(state, context);
const before_clip = performance.now();
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(indices), gl.DYNAMIC_DRAW);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_INT, 0);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(state.onscreen_segments), gl.DYNAMIC_DRAW);
const after_index_uploads = performance.now();
console.debug('index upload', after_index_uploads - after_clip);
gl.drawElements(gl.TRIANGLES, state.onscreen_segments.length, gl.UNSIGNED_INT, 0);
}
if (dynamic_points > 0) {
@ -89,7 +99,7 @@ function draw(state, context) { @@ -89,7 +99,7 @@ function draw(state, context) {
gl.drawArrays(gl.TRIANGLES, 0, dynamic_points);
}
/*
const next_tick = () => {
const wait_status = gl.clientWaitSync(sync, 0, 0);
const frame_end = performance.now();
@ -104,8 +114,36 @@ function draw(state, context) { @@ -104,8 +114,36 @@ function draw(state, context) {
}
setTimeout(next_tick, 0);
*/
if (context.gpu_timer_ext) {
gl.endQuery(context.gpu_timer_ext.TIME_ELAPSED_EXT);
const next_tick = () => {
if (query) {
// At some point in the future, after returning control to the browser
const available = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
const disjoint = gl.getParameter(context.gpu_timer_ext.GPU_DISJOINT_EXT);
if (available && !disjoint) {
// See how much time the rendering of the object took in nanoseconds.
const timeElapsed = gl.getQueryParameter(query, gl.QUERY_RESULT);
console.debug(timeElapsed / 1000000);
}
if (available || disjoint) {
// Clean up the query object.
gl.deleteQuery(query);
// Don't re-enter this polling loop.
query = null;
} else {
setTimeout(next_tick, 0);
}
}
}
setTimeout(next_tick, 0);
}
// Images
// locations = context.locations['image'];
// buffers = context.buffers['image'];

4
client/webgl_shaders.js

@ -80,7 +80,7 @@ const sdf_fs_src = `#version 300 es @@ -80,7 +80,7 @@ const sdf_fs_src = `#version 300 es
// float alpha = 1.0 - step(0.0, dist);
if (u_debug_mode == 1) {
FragColor = vec4(1.0, 0.0, 0.0, 0.5);
FragColor = vec4(1.0, 0.0, 0.0, 0.1);
} else {
FragColor = vec4(v_color * alpha, alpha);
// FragColor = vec4(v_color * alpha, 0.1 + alpha);
@ -140,6 +140,8 @@ function init_webgl(state, context) { @@ -140,6 +140,8 @@ function init_webgl(state, context) {
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
context.gpu_timer_ext = gl.getExtension('EXT_disjoint_timer_query_webgl2');
const quad_vs = create_shader(gl, gl.VERTEX_SHADER, tquad_vs_src);
const quad_fs = create_shader(gl, gl.FRAGMENT_SHADER, tquad_fs_src);

Loading…
Cancel
Save