|
|
|
@ -273,6 +273,9 @@ async function draw(state, context, animate, ts) {
@@ -273,6 +273,9 @@ 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); |
|
|
|
|
|
|
|
|
|
// "Static" data upload
|
|
|
|
|
if (segment_count > 0) { |
|
|
|
@ -283,14 +286,17 @@ async function draw(state, context, animate, ts) {
@@ -283,14 +286,17 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
|
|
|
|
|
const total_static_size = context.instance_data_points.size * 4 + |
|
|
|
|
context.instance_data_ids.size * 4 + |
|
|
|
|
context.instance_data_pressures.size; |
|
|
|
|
round_to_pow2(context.instance_data_pressures.size, 4) + |
|
|
|
|
circle_data.length * 4; |
|
|
|
|
|
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_strokes_static']); |
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, total_static_size, gl.STREAM_DRAW); |
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, total_static_size, gl.DYNAMIC_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.bindTexture(gl.TEXTURE_2D, textures['stroke_data']); |
|
|
|
|
upload_square_rgba16ui_texture(gl, context.stroke_data, config.stroke_texture_size); |
|
|
|
|
|
|
|
|
@ -302,28 +308,35 @@ async function draw(state, context, animate, ts) {
@@ -302,28 +308,35 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
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.enableVertexAttribArray(pr.locations['a_pos']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_a']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_b']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_stroke_id']); |
|
|
|
|
gl.enableVertexAttribArray(pr.locations['a_pressure']); |
|
|
|
|
|
|
|
|
|
// Circle meshes (shared for all instances)
|
|
|
|
|
gl.vertexAttribPointer(pr.locations['a_pos'], 2, gl.FLOAT, false, 2 * 4, context.instance_data_points.size * 4 + context.instance_data_ids.size * 4 + round_to_pow2(context.instance_data_pressures.size, 4)); |
|
|
|
|
|
|
|
|
|
// Points (a, b) and stroke ids are stored in separate cpu buffers so that points can be reused (look at stride and offset values)
|
|
|
|
|
gl.vertexAttribPointer(pr.locations['a_a'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
|
gl.vertexAttribPointer(pr.locations['a_b'], 2, gl.FLOAT, false, 2 * 4, 2 * 4); |
|
|
|
|
gl.vertexAttribIPointer(pr.locations['a_stroke_id'], 1, gl.INT, 4, context.instance_data_points.size * 4); |
|
|
|
|
gl.vertexAttribPointer(pr.locations['a_pressure'], 2, gl.UNSIGNED_BYTE, true, 1, context.instance_data_points.size * 4 + context.instance_data_ids.size * 4); |
|
|
|
|
|
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_pos'], 0); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_a'], 1); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_b'], 1); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_stroke_id'], 1); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_pressure'], 1); |
|
|
|
|
|
|
|
|
|
// Static draw (everything already bound)
|
|
|
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 32 * 3 + 6 + 32 * 3, segment_count); |
|
|
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, circle_points + 6, segment_count); |
|
|
|
|
|
|
|
|
|
// I don't really know why I need to do this, but it
|
|
|
|
|
// makes background patter drawcall work properly
|
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_pos'], 0); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_a'], 0); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_b'], 0); |
|
|
|
|
gl.vertexAttribDivisor(pr.locations['a_stroke_id'], 0); |
|
|
|
@ -332,7 +345,7 @@ async function draw(state, context, animate, ts) {
@@ -332,7 +345,7 @@ async function draw(state, context, animate, ts) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Dynamic draw (strokes currently being drawn)
|
|
|
|
|
if (dynamic_segment_count > 0) { |
|
|
|
|
if (false && dynamic_segment_count > 0) { |
|
|
|
|
const pr = programs['main']; // same as static
|
|
|
|
|
|
|
|
|
|
// Dynamic strokes should be drawn above static strokes
|
|
|
|
|