diff --git a/client/webgl_draw.js b/client/webgl_draw.js index 06faa1a..5121d41 100644 --- a/client/webgl_draw.js +++ b/client/webgl_draw.js @@ -320,7 +320,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, 6, segment_count); + gl.drawArraysInstanced(gl.TRIANGLES, 0, 32 * 3 + 6 + 32 * 3, segment_count); // I don't really know why I need to do this, but it // makes background patter drawcall work properly @@ -391,7 +391,7 @@ async function draw(state, context, animate, ts) { gl.vertexAttribDivisor(pr.locations['a_stroke_id'], 1); gl.vertexAttribDivisor(pr.locations['a_pressure'], 1); - gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, dynamic_segment_count); + gl.drawArraysInstanced(gl.TRIANGLES, 0, 32 * 3 + 6 + 32 * 3, dynamic_segment_count); gl.vertexAttribDivisor(pr.locations['a_a'], 0); gl.vertexAttribDivisor(pr.locations['a_b'], 0); @@ -438,8 +438,7 @@ async function draw(state, context, animate, ts) { 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, 6, ui_segments); + gl.drawArraysInstanced(gl.TRIANGLES, 0, 32 * 3 + 6 + 32 * 3, ui_segments); // I don't really know why I need to do this, but it // makes background patter drawcall work properly diff --git a/client/webgl_shaders.js b/client/webgl_shaders.js index b5dfce3..30ec993 100644 --- a/client/webgl_shaders.js +++ b/client/webgl_shaders.js @@ -12,23 +12,20 @@ const sdf_vs_src = `#version 300 es uniform int u_stroke_texture_size; uniform highp usampler2D u_stroke_data; uniform float u_fixed_pixel_width; - - out vec4 v_line; - out vec2 v_texcoord; + out vec3 v_color; flat out vec2 v_thickness; void main() { + const float PI = 3.1415926; vec2 screen02; - float apron = 1.0; // google "futanari inflation rule 34" int stroke_data_y = a_stroke_id / u_stroke_texture_size; int stroke_data_x = a_stroke_id % u_stroke_texture_size; vec2 line_dir = normalize(a_b - a_a); vec2 up_dir = vec2(line_dir.y, -line_dir.x); - vec2 pixel = vec2(2.0) / u_res; uvec4 stroke_data = texelFetch(u_stroke_data, ivec2(stroke_data_x, stroke_data_y), 0); float radius = float(stroke_data.w); @@ -37,40 +34,65 @@ const sdf_vs_src = `#version 300 es radius = u_fixed_pixel_width / u_scale.x; } - float rscale = apron / u_scale.x; - int vertex_index = gl_VertexID % 6; + int vertex_index = gl_VertexID % 198; - vec2 outwards; - vec2 origin; + vec2 pos; + + if (vertex_index < 32 * 3) { + // first cap + float angle1 = float(vertex_index / 3) / 32.0 * PI * 2.0; + float angle2 = float((vertex_index + 1) / 3) / 32.0 * PI * 2.0; + vec2 dir1 = vec2(cos(angle1), sin(angle1)); + vec2 dir2 = vec2(cos(angle2), sin(angle2)); + + if (vertex_index % 3 == 0) { + pos = a_a + dir1 * radius * a_pressure.x * 2.0; + } else if (vertex_index % 3 == 1) { + pos = a_a; + } else { + pos = a_a + dir2 * radius * a_pressure.x * 2.0; + } + } else if (vertex_index < 102) { + // connecting line + if (vertex_index == 96) { + // top left + pos = a_a + up_dir * radius * a_pressure.x * 2.0; + } else if (vertex_index == 97 || vertex_index == 101) { + // top right + pos = a_b + up_dir * radius * a_pressure.y * 2.0; + } else if (vertex_index == 98 || vertex_index == 100) { + // bottom left + pos = a_a - up_dir * radius * a_pressure.x * 2.0; + } else { + // bottom right + pos = a_b - up_dir * radius * a_pressure.y * 2.0; + } - if (vertex_index == 0) { - // "top left" aka "p1" - origin = a_a; - outwards = up_dir - line_dir; - } else if (vertex_index == 1 || vertex_index == 5) { - // "top right" aka "p2" - origin = a_b; - outwards = up_dir + line_dir; - } else if (vertex_index == 2 || vertex_index == 4) { - // "bottom left" aka "p3" - origin = a_a; - outwards = -up_dir - line_dir; } else { - // "bottom right" aka "p4" - origin = a_b; - outwards = -up_dir + line_dir; + // second cap + float angle1 = float((vertex_index - 102) / 3) / 32.0 * PI * 2.0; + float angle2 = float((vertex_index - 101) / 3) / 32.0 * PI * 2.0; + vec2 dir1 = vec2(cos(angle1), sin(angle1)); + vec2 dir2 = vec2(cos(angle2), sin(angle2)); + + if ((vertex_index - 102) % 3 == 0) { + pos = a_b + dir1 * radius * a_pressure.y * 2.0; + } else if ((vertex_index - 102) % 3 == 1) { + pos = a_a; + } else { + pos = a_b + dir2 * radius * a_pressure.y * 2.0; + } } - - vec2 pos = origin + normalize(outwards) * radius * 2.0 * max(a_pressure.x, a_pressure.y); // doubling is to account for max possible pressure - screen02 = (pos.xy * u_scale + u_translation) / u_res * 2.0 + outwards * pixel * apron; - v_texcoord = pos.xy + outwards * rscale; + + screen02 = (pos.xy * u_scale + u_translation) / u_res * 2.0; screen02.y = 2.0 - screen02.y; - v_line = vec4(a_a, a_b); - v_thickness = radius * a_pressure; // pressure 0.5 is the "neutral" pressure + v_color = vec3(stroke_data.xyz) / 255.0; + if (a_stroke_id >> 31 != 0) { screen02 += vec2(100.0); // shift offscreen } + gl_Position = vec4(screen02 - 1.0, (float(a_stroke_id) / float(u_stroke_count)) * 2.0 - 1.0, 1.0); } `; @@ -80,36 +102,13 @@ const sdf_fs_src = `#version 300 es uniform int u_debug_mode; - in vec4 v_line; - in vec2 v_texcoord; in vec3 v_color; - flat in vec2 v_thickness; - layout(location = 0) out vec4 FragColor; void main() { if (u_debug_mode == 0) { - vec2 a = v_line.xy; - vec2 b = v_line.zw; - - vec2 pa = v_texcoord - a.xy, ba = b.xy - a.xy; - float dba = dot(ba, ba); - float dist; - - if (dba > 0.0) { - float h = clamp(dot(pa, ba) / dba, 0.0, 1.0); - dist = length(v_texcoord - (a + ba * h)) - mix(v_thickness.x, v_thickness.y, h); - } else { - // Special case for when we are drawing a single point. Just a circle SDF - dist = length(v_texcoord - a.xy - v_thickness.x); - } - - float fade = 0.5 * length(fwidth(v_texcoord)); - float alpha = 1.0 - smoothstep(-fade, fade, dist); - - //if (alpha > 0.5) alpha = 0.5; - + float alpha = 0.5; FragColor = vec4(v_color * alpha, alpha); } else { FragColor = vec4(0.2, 0.0, 0.0, 0.2); @@ -340,7 +339,7 @@ function init_webgl(state, context) { context.gl = context.canvas.getContext('webgl2', { 'preserveDrawingBuffer': true, 'desynchronized': true, - 'antialias': false, + 'antialias': true, }); const gl = context.gl; @@ -349,8 +348,8 @@ function init_webgl(state, context) { gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); //gl.blendEquation(gl.MAX); - //gl.enable(gl.DEPTH_TEST); - //gl.depthFunc(gl.GEQUAL); + gl.enable(gl.DEPTH_TEST); + gl.depthFunc(gl.NOTEQUAL); context.gpu_timer_ext = gl.getExtension('EXT_disjoint_timer_query_webgl2'); if (context.gpu_timer_ext === null) {