|
|
|
@ -273,9 +273,24 @@ async function draw(state, context, animate, ts) {
@@ -273,9 +273,24 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const circle_segments = 32; |
|
|
|
|
const circle_points = circle_segments * 3; |
|
|
|
|
const circle_data = geometry_line_segments_with_two_circles(circle_segments); |
|
|
|
|
if (false) { |
|
|
|
|
// TODO: @speed maybe we can get this while clipping "for free"?
|
|
|
|
|
let largest_width = 0; |
|
|
|
|
|
|
|
|
|
for (let i = 0; i < context.clipped_indices.size; ++i) { |
|
|
|
|
const stroke_id = context.clipped_indices.data[i]; |
|
|
|
|
const stroke = state.events[stroke_id]; |
|
|
|
|
if (stroke.width > largest_width) { |
|
|
|
|
largest_width = stroke.width; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
largest_width *= state.canvas.zoom; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Largest distance from N-th circle LOD to a real circle should be less than 1 unit (pixel)
|
|
|
|
|
const circle_lod = 4; // largest_width > 0 ? Math.ceil(Math.PI / Math.acos(1 - 1 / largest_width)) : 0;
|
|
|
|
|
const circle_data = geometry_good_circle_and_dummy(circle_lod); |
|
|
|
|
|
|
|
|
|
// "Static" data upload
|
|
|
|
|
if (segment_count > 0) { |
|
|
|
@ -287,16 +302,17 @@ async function draw(state, context, animate, ts) {
@@ -287,16 +302,17 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
const total_static_size = context.instance_data_points.size * 4 + |
|
|
|
|
context.instance_data_ids.size * 4 + |
|
|
|
|
round_to_pow2(context.instance_data_pressures.size, 4) + |
|
|
|
|
circle_data.length * 4; |
|
|
|
|
circle_data.points.size * 4; |
|
|
|
|
|
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_strokes_static']); |
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, total_static_size, gl.DYNAMIC_DRAW); |
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, total_static_size, gl.STREAM_DRAW); |
|
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, tv_data(context.instance_data_points)); |
|
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, context.instance_data_points.size * 4, tv_data(context.instance_data_ids)); |
|
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, context.instance_data_points.size * 4 + context.instance_data_ids.size * 4, |
|
|
|
|
tv_data(context.instance_data_pressures)); |
|
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, context.instance_data_points.size * 4 + context.instance_data_ids.size * 4 + round_to_pow2(context.instance_data_pressures.size, 4), |
|
|
|
|
circle_data); |
|
|
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, context.instance_data_points.size * 4 + context.instance_data_ids.size * 4 + round_to_pow2(context.instance_data_pressures.size, 4), tv_data(circle_data.points)); |
|
|
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers['i_strokes_static']); |
|
|
|
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, tv_data(circle_data.indices), gl.STREAM_DRAW); |
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, textures['stroke_data']); |
|
|
|
|
upload_square_rgba16ui_texture(gl, context.stroke_data, config.stroke_texture_size); |
|
|
|
|
|
|
|
|
@ -307,8 +323,7 @@ async function draw(state, context, animate, ts) {
@@ -307,8 +323,7 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
gl.uniform1i(pr.locations['u_debug_mode'], state.debug.red); |
|
|
|
|
gl.uniform1i(pr.locations['u_stroke_data'], 0); |
|
|
|
|
gl.uniform1i(pr.locations['u_stroke_texture_size'], config.stroke_texture_size); |
|
|
|
|
gl.uniform1f(pr.locations['u_fixed_pixel_width'], 0); |
|
|
|
|
gl.uniform1i(pr.locations['u_circle_points'], circle_points); |
|
|
|
|
gl.uniform1i(pr.locations['u_circle_points'], circle_data.points.size / 2 - 4); |
|
|
|
|
|
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_pos']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_a']); |
|
|
|
@ -332,7 +347,7 @@ async function draw(state, context, animate, ts) {
@@ -332,7 +347,7 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_pressure'], 1); |
|
|
|
|
|
|
|
|
|
// Static draw (everything already bound)
|
|
|
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, circle_points + 6, segment_count); |
|
|
|
|
gl.drawElementsInstanced(gl.TRIANGLES, circle_data.indices.size, gl.UNSIGNED_INT, 0, segment_count); |
|
|
|
|
|
|
|
|
|
// I don't really know why I need to do this, but it
|
|
|
|
|
// makes background patter drawcall work properly
|
|
|
|
@ -379,7 +394,6 @@ async function draw(state, context, animate, ts) {
@@ -379,7 +394,6 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
gl.uniform1i(pr.locations['u_debug_mode'], state.debug.red); |
|
|
|
|
gl.uniform1i(pr.locations['u_stroke_data'], 0); |
|
|
|
|
gl.uniform1i(pr.locations['u_stroke_texture_size'], config.dynamic_stroke_texture_size); |
|
|
|
|
gl.uniform1f(pr.locations['u_fixed_pixel_width'], 0); |
|
|
|
|
|
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_a']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_b']); |
|
|
|
@ -434,7 +448,6 @@ async function draw(state, context, animate, ts) {
@@ -434,7 +448,6 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
gl.uniform1i(pr.locations['u_debug_mode'], 0); |
|
|
|
|
gl.uniform1i(pr.locations['u_stroke_data'], 0); |
|
|
|
|
gl.uniform1i(pr.locations['u_stroke_texture_size'], config.ui_texture_size); |
|
|
|
|
gl.uniform1f(pr.locations['u_fixed_pixel_width'], 2); |
|
|
|
|
|
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_a']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_b']); |
|
|
|
|