|
|
@ -86,6 +86,8 @@ async function draw(state, context, animate, ts) { |
|
|
|
const width = window.innerWidth; |
|
|
|
const width = window.innerWidth; |
|
|
|
const height = window.innerHeight; |
|
|
|
const height = window.innerHeight; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const canvas = canvas_css_rect(context); |
|
|
|
|
|
|
|
|
|
|
|
bvh_clip(state, context); |
|
|
|
bvh_clip(state, context); |
|
|
|
|
|
|
|
|
|
|
|
const segment_count = await geometry_write_instances(state, context); |
|
|
|
const segment_count = await geometry_write_instances(state, context); |
|
|
@ -100,10 +102,10 @@ async function draw(state, context, animate, ts) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Only clear once we have the data, this might not always be on the same frame?
|
|
|
|
// Only clear once we have the data, this might not always be on the same frame?
|
|
|
|
gl.viewport(0, 0, context.canvas.width, context.canvas.height); |
|
|
|
gl.viewport(0, 0, canvas.width, canvas.height); |
|
|
|
gl.clearColor(context.bgcolor.r, context.bgcolor.g, context.bgcolor.b, 1); |
|
|
|
gl.clearColor(context.bgcolor.r, context.bgcolor.g, context.bgcolor.b, 1); |
|
|
|
gl.clearDepth(0.0); |
|
|
|
gl.clearDepth(0.0); |
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); |
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); |
|
|
|
|
|
|
|
|
|
|
|
// Draw the background pattern
|
|
|
|
// Draw the background pattern
|
|
|
|
if (state.background_pattern === 'dots') { |
|
|
|
if (state.background_pattern === 'dots') { |
|
|
@ -116,7 +118,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.vertexAttribPointer(locations['a_center'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribPointer(locations['a_center'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribDivisor(locations['a_center'], 1); |
|
|
|
gl.vertexAttribDivisor(locations['a_center'], 1); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
gl.uniform2f(locations['u_res'], canvas.width, canvas.height); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
|
|
|
|
|
|
|
@ -124,11 +126,12 @@ async function draw(state, context, animate, ts) { |
|
|
|
const zoom_log2 = Math.log2(zoom); |
|
|
|
const zoom_log2 = Math.log2(zoom); |
|
|
|
const zoom_previous = Math.pow(2, Math.floor(zoom_log2)); |
|
|
|
const zoom_previous = Math.pow(2, Math.floor(zoom_log2)); |
|
|
|
const zoom_next = Math.pow(2, Math.ceil(zoom_log2)); |
|
|
|
const zoom_next = Math.pow(2, Math.ceil(zoom_log2)); |
|
|
|
|
|
|
|
const grid_step = 32; |
|
|
|
|
|
|
|
|
|
|
|
// Previous level
|
|
|
|
// Previous level
|
|
|
|
{ |
|
|
|
{ |
|
|
|
const one_dot = new Float32Array(geometry_gen_quad(0, 0, 1 / zoom_previous)); |
|
|
|
const one_dot = new Float32Array(geometry_gen_quad(0, 0, 1 / zoom_previous)); |
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, 32 / zoom_previous, 32 / zoom_previous)); |
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, grid_step / zoom_previous, grid_step / zoom_previous)); |
|
|
|
const t = Math.min(1.0, 1.0 - (zoom / zoom_previous) / 2.0); |
|
|
|
const t = Math.min(1.0, 1.0 - (zoom / zoom_previous) / 2.0); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
@ -141,7 +144,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
|
|
|
|
|
|
|
|
// Next level
|
|
|
|
// Next level
|
|
|
|
if (zoom_previous != zoom_next) { |
|
|
|
if (zoom_previous != zoom_next) { |
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, 32 / zoom_next, 32 / zoom_next)); |
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, grid_step / zoom_next, grid_step / zoom_next)); |
|
|
|
const t = Math.min(1.0, 1.0 - (zoom_next / zoom) / 2.0); |
|
|
|
const t = Math.min(1.0, 1.0 - (zoom_next / zoom) / 2.0); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
@ -155,7 +158,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
const zoom = state.canvas.zoom; |
|
|
|
const zoom = state.canvas.zoom; |
|
|
|
|
|
|
|
|
|
|
|
let zoom_log8 = Math.log(zoom) / Math.log(8); |
|
|
|
let zoom_log8 = Math.log(zoom) / Math.log(8); |
|
|
|
//if (zoom_log2 === Math.floor(zoom_log2)) {
|
|
|
|
//if (zoom_log2 === Math.floor(zoom_log2))
|
|
|
|
// zoom_log2 -= 0.001;
|
|
|
|
// zoom_log2 -= 0.001;
|
|
|
|
//}
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
@ -175,14 +178,14 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.vertexAttribPointer(locations['a_data'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribPointer(locations['a_data'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribDivisor(locations['a_data'], 1); |
|
|
|
gl.vertexAttribDivisor(locations['a_data'], 1); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
gl.uniform2f(locations['u_res'], canvas.width, canvas.height); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform1f(locations['u_fadeout'], 1.0); |
|
|
|
gl.uniform1f(locations['u_fadeout'], 1.0); |
|
|
|
|
|
|
|
|
|
|
|
// Previous level (major lines)
|
|
|
|
// Previous level (major lines)
|
|
|
|
{ |
|
|
|
{ |
|
|
|
const grid_instances = new Float32Array(geometry_gen_fullscreen_grid_1d(state, context, 32 / zoom_previous, 32 / zoom_previous)); |
|
|
|
const grid_instances = new Float32Array(geometry_gen_fullscreen_grid_1d(state, context, grid_step / zoom_previous, grid_step / zoom_previous)); |
|
|
|
let t = (zoom / zoom_previous - 1) / -7 + 1; |
|
|
|
let t = (zoom / zoom_previous - 1) / -7 + 1; |
|
|
|
t = 0.25; |
|
|
|
t = 0.25; |
|
|
|
|
|
|
|
|
|
|
@ -196,7 +199,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
|
|
|
|
|
|
|
|
// Next level (minor lines)
|
|
|
|
// Next level (minor lines)
|
|
|
|
{ |
|
|
|
{ |
|
|
|
const grid_instances = new Float32Array(geometry_gen_fullscreen_grid_1d(state, context, 32 / zoom_next, 32 / zoom_next)); |
|
|
|
const grid_instances = new Float32Array(geometry_gen_fullscreen_grid_1d(state, context, grid_step / zoom_next, grid_step / zoom_next)); |
|
|
|
let t = (zoom_next / zoom - 1) / 7; |
|
|
|
let t = (zoom_next / zoom - 1) / 7; |
|
|
|
t = Math.min(0.1, -t + 1); // slight fade-in
|
|
|
|
t = Math.min(0.1, -t + 1); // slight fade-in
|
|
|
|
|
|
|
|
|
|
|
@ -226,7 +229,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.vertexAttribPointer(locations['a_pos'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribPointer(locations['a_pos'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
|
|
|
|
|
|
|
|
for (const entry of context.images) { |
|
|
|
for (const entry of context.images) { |
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
gl.uniform2f(locations['u_res'], canvas.width, canvas.height); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform1i(locations['u_texture'], 0); // Only 1 active texture for each drawcall
|
|
|
|
gl.uniform1i(locations['u_texture'], 0); // Only 1 active texture for each drawcall
|
|
|
@ -266,7 +269,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.bindTexture(gl.TEXTURE_2D, context.textures['stroke_data']); |
|
|
|
gl.bindTexture(gl.TEXTURE_2D, context.textures['stroke_data']); |
|
|
|
upload_square_rgba16ui_texture(gl, context.stroke_data, config.stroke_texture_size); |
|
|
|
upload_square_rgba16ui_texture(gl, context.stroke_data, config.stroke_texture_size); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
gl.uniform2f(locations['u_res'], canvas.width, canvas.height); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform1i(locations['u_stroke_count'], state.events.length); |
|
|
|
gl.uniform1i(locations['u_stroke_count'], state.events.length); |
|
|
@ -274,6 +277,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.uniform1i(locations['u_stroke_data'], 0); |
|
|
|
gl.uniform1i(locations['u_stroke_data'], 0); |
|
|
|
gl.uniform1i(locations['u_stroke_texture_size'], config.stroke_texture_size); |
|
|
|
gl.uniform1i(locations['u_stroke_texture_size'], config.stroke_texture_size); |
|
|
|
gl.uniform1f(locations['u_fixed_pixel_width'], 0); |
|
|
|
gl.uniform1f(locations['u_fixed_pixel_width'], 0); |
|
|
|
|
|
|
|
gl.uniform2f(locations['u_ssao'], config.ssao, config.ssao); |
|
|
|
|
|
|
|
|
|
|
|
gl.enableVertexAttribArray(locations['a_a']); |
|
|
|
gl.enableVertexAttribArray(locations['a_a']); |
|
|
|
gl.enableVertexAttribArray(locations['a_b']); |
|
|
|
gl.enableVertexAttribArray(locations['a_b']); |
|
|
@ -326,7 +330,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.bindTexture(gl.TEXTURE_2D, context.textures['dynamic_stroke_data']); |
|
|
|
gl.bindTexture(gl.TEXTURE_2D, context.textures['dynamic_stroke_data']); |
|
|
|
upload_square_rgba16ui_texture(gl, context.dynamic_stroke_data, config.dynamic_stroke_texture_size); |
|
|
|
upload_square_rgba16ui_texture(gl, context.dynamic_stroke_data, config.dynamic_stroke_texture_size); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
gl.uniform2f(locations['u_res'], canvas.width, canvas.height); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
|
|
|
|
|
|
|
@ -335,6 +339,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.uniform1i(locations['u_stroke_data'], 0); |
|
|
|
gl.uniform1i(locations['u_stroke_data'], 0); |
|
|
|
gl.uniform1i(locations['u_stroke_texture_size'], config.dynamic_stroke_texture_size); |
|
|
|
gl.uniform1i(locations['u_stroke_texture_size'], config.dynamic_stroke_texture_size); |
|
|
|
gl.uniform1f(locations['u_fixed_pixel_width'], 0); |
|
|
|
gl.uniform1f(locations['u_fixed_pixel_width'], 0); |
|
|
|
|
|
|
|
gl.uniform2f(locations['u_ssao'], config.ssao, config.ssao); |
|
|
|
|
|
|
|
|
|
|
|
gl.enableVertexAttribArray(locations['a_a']); |
|
|
|
gl.enableVertexAttribArray(locations['a_a']); |
|
|
|
gl.enableVertexAttribArray(locations['a_b']); |
|
|
|
gl.enableVertexAttribArray(locations['a_b']); |
|
|
@ -374,7 +379,7 @@ async function draw(state, context, animate, ts) { |
|
|
|
gl.bindTexture(gl.TEXTURE_2D, context.textures['ui']); |
|
|
|
gl.bindTexture(gl.TEXTURE_2D, context.textures['ui']); |
|
|
|
upload_square_rgba16ui_texture(gl, handles.stroke_data, config.ui_texture_size); |
|
|
|
upload_square_rgba16ui_texture(gl, handles.stroke_data, config.ui_texture_size); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
gl.uniform2f(locations['u_res'], canvas.width, canvas.height); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform1i(locations['u_stroke_count'], 8); |
|
|
|
gl.uniform1i(locations['u_stroke_count'], 8); |
|
|
|