Browse Source

Use straight up geometry for everything, finally obtaining TRANSPARENCY!

Freya 🙏 🙏 🙏
sdf
A.Olokhtonov 4 weeks ago
parent
commit
78ba044527
  1. 7
      client/webgl_draw.js
  2. 113
      client/webgl_shaders.js

7
client/webgl_draw.js

@ -320,7 +320,7 @@ async function draw(state, context, animate, ts) {
gl.vertexAttribDivisor(pr.locations['a_pressure'], 1); gl.vertexAttribDivisor(pr.locations['a_pressure'], 1);
// Static draw (everything already bound) // 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 // I don't really know why I need to do this, but it
// makes background patter drawcall work properly // 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_stroke_id'], 1);
gl.vertexAttribDivisor(pr.locations['a_pressure'], 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_a'], 0);
gl.vertexAttribDivisor(pr.locations['a_b'], 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_stroke_id'], 1);
gl.vertexAttribDivisor(pr.locations['a_pressure'], 1); gl.vertexAttribDivisor(pr.locations['a_pressure'], 1);
// Static draw (everything already bound) gl.drawArraysInstanced(gl.TRIANGLES, 0, 32 * 3 + 6 + 32 * 3, ui_segments);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, ui_segments);
// I don't really know why I need to do this, but it // I don't really know why I need to do this, but it
// makes background patter drawcall work properly // makes background patter drawcall work properly

113
client/webgl_shaders.js

@ -12,23 +12,20 @@ const sdf_vs_src = `#version 300 es
uniform int u_stroke_texture_size; uniform int u_stroke_texture_size;
uniform highp usampler2D u_stroke_data; uniform highp usampler2D u_stroke_data;
uniform float u_fixed_pixel_width; uniform float u_fixed_pixel_width;
out vec4 v_line;
out vec2 v_texcoord;
out vec3 v_color; out vec3 v_color;
flat out vec2 v_thickness; flat out vec2 v_thickness;
void main() { void main() {
const float PI = 3.1415926;
vec2 screen02; 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_y = a_stroke_id / u_stroke_texture_size;
int stroke_data_x = 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 line_dir = normalize(a_b - a_a);
vec2 up_dir = vec2(line_dir.y, -line_dir.x); 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); uvec4 stroke_data = texelFetch(u_stroke_data, ivec2(stroke_data_x, stroke_data_y), 0);
float radius = float(stroke_data.w); 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; radius = u_fixed_pixel_width / u_scale.x;
} }
float rscale = apron / u_scale.x; int vertex_index = gl_VertexID % 198;
int vertex_index = gl_VertexID % 6;
vec2 outwards; vec2 pos;
vec2 origin;
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 { } else {
// "bottom right" aka "p4" // second cap
origin = a_b; float angle1 = float((vertex_index - 102) / 3) / 32.0 * PI * 2.0;
outwards = -up_dir + line_dir; 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;
screen02 = (pos.xy * u_scale + u_translation) / u_res * 2.0 + outwards * pixel * apron;
v_texcoord = pos.xy + outwards * rscale;
screen02.y = 2.0 - screen02.y; 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; v_color = vec3(stroke_data.xyz) / 255.0;
if (a_stroke_id >> 31 != 0) { if (a_stroke_id >> 31 != 0) {
screen02 += vec2(100.0); // shift offscreen 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); 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; uniform int u_debug_mode;
in vec4 v_line;
in vec2 v_texcoord;
in vec3 v_color; in vec3 v_color;
flat in vec2 v_thickness;
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
void main() { void main() {
if (u_debug_mode == 0) { if (u_debug_mode == 0) {
vec2 a = v_line.xy; float alpha = 0.5;
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;
FragColor = vec4(v_color * alpha, alpha); FragColor = vec4(v_color * alpha, alpha);
} else { } else {
FragColor = vec4(0.2, 0.0, 0.0, 0.2); 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', { context.gl = context.canvas.getContext('webgl2', {
'preserveDrawingBuffer': true, 'preserveDrawingBuffer': true,
'desynchronized': true, 'desynchronized': true,
'antialias': false, 'antialias': true,
}); });
const gl = context.gl; const gl = context.gl;
@ -349,8 +348,8 @@ function init_webgl(state, context) {
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
//gl.blendEquation(gl.MAX); //gl.blendEquation(gl.MAX);
//gl.enable(gl.DEPTH_TEST); gl.enable(gl.DEPTH_TEST);
//gl.depthFunc(gl.GEQUAL); gl.depthFunc(gl.NOTEQUAL);
context.gpu_timer_ext = gl.getExtension('EXT_disjoint_timer_query_webgl2'); context.gpu_timer_ext = gl.getExtension('EXT_disjoint_timer_query_webgl2');
if (context.gpu_timer_ext === null) { if (context.gpu_timer_ext === null) {

Loading…
Cancel
Save