Browse Source

SDF bull fixed boxes + passed stroke width to shader

ssao
A.Olokhtonov 1 year ago
parent
commit
f72cbf5941
  1. 2
      client/tools.js
  2. 56
      client/webgl_draw.js
  3. 35
      client/webgl_geometry.js
  4. 16
      client/webgl_shaders.js

2
client/tools.js

@ -48,7 +48,7 @@ function hide_stroke_preview() { @@ -48,7 +48,7 @@ function hide_stroke_preview() {
function switch_stroke_width(e, state) {
if (!state.online) return;
const value = e.target.value;
const value = parseInt(e.target.value);
state.players[state.me].width = value;
show_stroke_preview(state, value);

56
client/webgl_draw.js

@ -31,41 +31,43 @@ function draw(state, context) { @@ -31,41 +31,43 @@ function draw(state, context) {
gl.enableVertexAttribArray(locations['a_pos']);
gl.enableVertexAttribArray(locations['a_color']);
gl.vertexAttribPointer(locations['a_pos'], 2, gl.FLOAT, false, 4 * 3, 0);
gl.vertexAttribPointer(locations['a_color'], 3, gl.UNSIGNED_BYTE, true, 4 * 3, 4 * 2);
gl.vertexAttribPointer(locations['a_pos'], 3, gl.FLOAT, false, 4 * 4, 0);
gl.vertexAttribPointer(locations['a_color'], 3, gl.UNSIGNED_BYTE, true, 4 * 4, 4 * 3);
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, textures['points']);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
const npoints = context.point_serializer.offset / (4 * 2);
const nstrokes = context.quad_serializer.offset / (6 * 3 * 4);
// TOOD: if points changed
if (true) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32F, npoints, 1, 0, gl.RG, gl.FLOAT, new Float32Array(context.point_serializer.buffer, 0, context.point_serializer.offset / 4));
}
gl.activeTexture(gl.TEXTURE0 + 1);
gl.bindTexture(gl.TEXTURE_2D, textures['indices']);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
// TOOD: if points changed
if (true) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32UI, nstrokes, 1, 0, gl.RG_INTEGER, gl.UNSIGNED_INT, new Uint32Array(context.index_serializer.buffer, 0, context.index_serializer.offset / 4));
const npoints = context.point_serializer.offset / (4 * 2);
const nstrokes = context.quad_serializer.offset / (6 * 4 * 4);
if (npoints > 0) {
// TOOD: if points changed
if (true) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32F, npoints, 1, 0, gl.RG, gl.FLOAT, new Float32Array(context.point_serializer.buffer, 0, context.point_serializer.offset / 4));
}
gl.activeTexture(gl.TEXTURE0 + 1);
gl.bindTexture(gl.TEXTURE_2D, textures['indices']);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
// TOOD: if points changed
if (true) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32UI, nstrokes, 1, 0, gl.RG_INTEGER, gl.UNSIGNED_INT, new Uint32Array(context.index_serializer.buffer, 0, context.index_serializer.offset / 4));
}
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height);
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.uniform1i(locations['u_texture_points'], 0);
gl.uniform1i(locations['u_texture_indices'], 1);
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.quad_serializer.buffer, 0, context.quad_serializer.offset), gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, nstrokes * 6);
}
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height);
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.uniform1i(locations['u_texture_points'], 0);
gl.uniform1i(locations['u_texture_indices'], 1);
gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(context.quad_serializer.buffer, 0, context.quad_serializer.offset), gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, nstrokes * 6);
// Images
// locations = context.locations['image'];
// buffers = context.buffers['image'];

35
client/webgl_geometry.js

@ -3,23 +3,24 @@ function push_point_xy(s, x, y) { @@ -3,23 +3,24 @@ function push_point_xy(s, x, y) {
ser_f32(s, y);
}
function push_point_xyrgb(s, x, y, r, g, b) {
function push_point_xyzrgb(s, x, y, z, r, g, b) {
ser_f32(s, x);
ser_f32(s, y);
ser_f32(s, z);
ser_u8(s, r);
ser_u8(s, g);
ser_u8(s, b);
ser_align(s, 4);
}
function push_quad_xyrgb(s, p1x, p1y, p4x, p4y, r, g, b) {
push_point_xyrgb(s, p1x, p1y, r, g, b);
push_point_xyrgb(s, p4x, p1y, r, g, b);
push_point_xyrgb(s, p1x, p4y, r, g, b);
function push_quad_xyzrgb(s, p1x, p1y, p4x, p4y, z, r, g, b) {
push_point_xyzrgb(s, p1x, p1y, z, r, g, b);
push_point_xyzrgb(s, p4x, p1y, z, r, g, b);
push_point_xyzrgb(s, p1x, p4y, z, r, g, b);
push_point_xyrgb(s, p4x, p4y, r, g, b);
push_point_xyrgb(s, p1x, p4y, r, g, b);
push_point_xyrgb(s, p4x, p1y, r, g, b);
push_point_xyzrgb(s, p4x, p4y, z, r, g, b);
push_point_xyzrgb(s, p1x, p4y, z, r, g, b);
push_point_xyzrgb(s, p4x, p1y, z, r, g, b);
}
function push_stroke(context, stroke) {
@ -43,21 +44,21 @@ function push_stroke(context, stroke) { @@ -43,21 +44,21 @@ function push_stroke(context, stroke) {
let min_x, min_y, max_x, max_y;
min_x = Math.floor(points[0].x);
max_x = Math.ceil(points[0].x);
min_x = Math.floor(points[0].x - stroke_width / 2);
max_x = Math.ceil(points[0].x + stroke_width / 2);
min_y = Math.floor(points[0].y);
max_y = Math.ceil(points[0].y);
min_y = Math.floor(points[0].y - stroke_width / 2);
max_y = Math.ceil(points[0].y + stroke_width / 2);
for (const p of points) {
min_x = Math.min(min_x, Math.floor(p.x));
min_y = Math.min(min_y, Math.floor(p.y));
max_x = Math.max(max_x, Math.ceil(p.x));
max_y = Math.max(max_y, Math.ceil(p.y));
min_x = Math.min(min_x, Math.floor(p.x - stroke_width / 2));
min_y = Math.min(min_y, Math.floor(p.y - stroke_width / 2));
max_x = Math.max(max_x, Math.ceil(p.x + stroke_width / 2));
max_y = Math.max(max_y, Math.ceil(p.y + stroke_width / 2));
push_point_xy(context.point_serializer, p.x, p.y);
}
push_quad_xyrgb(context.quad_serializer, min_x, min_y, max_x, max_y, r, g, b);
push_quad_xyzrgb(context.quad_serializer, min_x, min_y, max_x, max_y, stroke_width / 2, r, g, b);
}
function geometry_prepare_stroke(state) {

16
client/webgl_shaders.js

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
const sdf_vs_src = `#version 300 es
in vec2 a_pos;
in vec3 a_pos;
in vec3 a_color;
uniform vec2 u_scale;
@ -8,16 +8,19 @@ const sdf_vs_src = `#version 300 es @@ -8,16 +8,19 @@ const sdf_vs_src = `#version 300 es
out vec2 v_texcoord;
out vec3 v_color;
flat out float v_thickness;
flat out int v_vertexid;
void main() {
vec2 screen01 = (a_pos * u_scale + u_translation) / u_res;
vec2 screen01 = (a_pos.xy * u_scale + u_translation) / u_res;
vec2 screen02 = screen01 * 2.0;
screen02.y = 2.0 - screen02.y;
v_texcoord = a_pos + vec2(0.5);
v_texcoord = a_pos.xy;
v_vertexid = gl_VertexID;
v_color = a_color;
v_thickness = a_pos.z;
gl_Position = vec4(screen02 - 1.0, 0, 1);
}
@ -31,13 +34,14 @@ const sdf_fs_src = `#version 300 es @@ -31,13 +34,14 @@ const sdf_fs_src = `#version 300 es
in vec2 v_texcoord;
in vec3 v_color;
flat in float v_thickness;
flat in int v_vertexid;
out vec4 FragColor;
void main() {
float mindist = 99999.9;
float th = 5.0;
uvec4 indices = texelFetch(u_texture_indices, ivec2(v_vertexid / 6, 0), 0);
@ -50,7 +54,7 @@ const sdf_fs_src = `#version 300 es @@ -50,7 +54,7 @@ const sdf_fs_src = `#version 300 es
vec2 pa = v_texcoord - a.xy, ba = b.xy - a.xy;
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
float dist = length(pa - ba * h) - th;
float dist = length(pa - ba * h) - v_thickness;
mindist = min(mindist, dist);
}
@ -58,7 +62,7 @@ const sdf_fs_src = `#version 300 es @@ -58,7 +62,7 @@ const sdf_fs_src = `#version 300 es
float fade = 0.5 * length(fwidth(v_texcoord));
float alpha = 1.0 - smoothstep(-fade, fade, mindist);
FragColor = vec4(v_color * alpha, 0.1 + alpha);
FragColor = vec4(v_color * alpha, alpha);
// FragColor = vec4(v_color, 1.0);
}
`;

Loading…
Cancel
Save