Browse Source

Basic snapping to grid is kinda working (needs more testing). Deleted obsolete shaders and debug options

ssao
A.Olokhtonov 5 months ago
parent
commit
ea409f76c4
  1. 2
      README.txt
  2. 12
      client/aux.js
  3. 3
      client/client_recv.js
  4. 2
      client/default.css
  5. 12
      client/index.html
  6. 5
      client/index.js
  7. 3
      client/webgl_geometry.js
  8. 78
      client/webgl_listeners.js
  9. 134
      client/webgl_shaders.js

2
README.txt

@ -48,7 +48,7 @@ Release: @@ -48,7 +48,7 @@ Release:
- Undo for images (add, move, scale)
- Undo for eraser
- Redo
- Snapping to grid
+ Snapping to grid
- Snapping to other points?
* Polish
+ Use typedvector where appropriate

12
client/aux.js

@ -253,3 +253,15 @@ function get_image(context, key) { @@ -253,3 +253,15 @@ function get_image(context, key) {
return null;
}
function grid_snap_step(state) {
const zoom_log2 = Math.log2(state.canvas.zoom);
const zoom_previous = Math.pow(2, Math.floor(zoom_log2));
const zoom_next = Math.pow(2, Math.ceil(zoom_log2));
if (Math.abs(state.canvas.zoom - zoom_previous) < Math.abs(state.canvas.zoom - zoom_next)) {
return 32 / zoom_previous;
} else {
return 32 / zoom_next;
}
}

3
client/client_recv.js

@ -541,9 +541,6 @@ async function handle_message(state, context, d) { @@ -541,9 +541,6 @@ async function handle_message(state, context, d) {
bvh_construct(state);
document.getElementById('debug-render-from').max = state.stroke_count;
document.getElementById('debug-render-to').max = state.stroke_count;
do_draw = true;
send_ack(event_count);

2
client/default.css

@ -414,7 +414,7 @@ body.offline * { @@ -414,7 +414,7 @@ body.offline * {
.debug-window {
position: absolute;
min-width: 256px;
min-width: 320px;
top: 20px;
right: 20px;
display: flex;

12
client/index.html

@ -41,17 +41,7 @@ @@ -41,17 +41,7 @@
</div>
<label><input type="checkbox" id="debug-red">Simple shader</label>
<label><input type="checkbox" id="debug-do-prepass">Depth prepass</label>
<div class="flexcol">
<label><input type="checkbox" id="debug-limit-from">Limit events from</label>
<input type="range" min="0" max="0" value="0" id="debug-render-from">
</div>
<div class="flexcol">
<label><input type="checkbox" id="debug-limit-to">Limit events to</label>
<input type="range" min="0" max="0" value="0" id="debug-render-to">
</div>
<label><input type="checkbox" id="do-snap">Snap to grid</label>
<button id="debug-begin-benchmark" title="Do not forget to enable recording in your browser!">Benchmark</button>
</div>

5
client/index.js

@ -224,9 +224,6 @@ async function main() { @@ -224,9 +224,6 @@ async function main() {
'debug': {
'red': false,
'do_prepass': true,
'limit_from': false,
'limit_to': false,
'render_from': 0,
'render_to': 0,
},
@ -243,6 +240,8 @@ async function main() { @@ -243,6 +240,8 @@ async function main() {
'background_pattern': 'dots',
'erase_candidates': tv_create(Uint32Array, 4096),
'snap': null,
};
const context = {

3
client/webgl_geometry.js

@ -189,7 +189,8 @@ function add_image(context, image_id, bitmap, p, width, height) { @@ -189,7 +189,8 @@ function add_image(context, image_id, bitmap, p, width, height) {
entry = {
'texture': gl.createTexture(),
'key': image_id,
'at': p,
'at': {...p},
'raw_at': {...p},
'width': width,
'height': height,
};

78
client/webgl_listeners.js

@ -24,38 +24,15 @@ function init_listeners(state, context) { @@ -24,38 +24,15 @@ function init_listeners(state, context) {
function debug_panel_init(state, context) {
document.getElementById('debug-red').checked = state.debug.red;
document.getElementById('debug-do-prepass').checked = state.debug.do_prepass;
document.getElementById('debug-limit-from').checked = state.debug.limit_from;
document.getElementById('debug-limit-to').checked = state.debug.limit_to;
document.getElementById('do-snap').checked = state.snap !== null;
document.getElementById('debug-red').addEventListener('change', (e) => {
state.debug.red = e.target.checked;
schedule_draw(state, context);
});
document.getElementById('debug-do-prepass').addEventListener('change', (e) => {
state.debug.do_prepass = e.target.checked;
schedule_draw(state, context);
});
document.getElementById('debug-limit-from').addEventListener('change', (e) => {
state.debug.limit_from = e.target.checked;
schedule_draw(state, context);
});
document.getElementById('debug-limit-to').addEventListener('change', (e) => {
state.debug.limit_to = e.target.checked;
schedule_draw(state, context);
});
document.getElementById('debug-render-from').addEventListener('input', (e) => {
state.debug.render_from = parseInt(e.target.value);
schedule_draw(state, context);
});
document.getElementById('debug-render-to').addEventListener('input', (e) => {
state.debug.render_to = parseInt(e.target.value);
schedule_draw(state, context);
document.getElementById('do-snap').addEventListener('change', (e) => {
state.snap = e.target.checked ? 'grid' : null;
});
document.getElementById('debug-begin-benchmark').addEventListener('click', (e) => {
@ -173,6 +150,13 @@ function keyup(e, state, context) { @@ -173,6 +150,13 @@ function keyup(e, state, context) {
function mousedown(e, state, context) {
const screenp = {'x': window.devicePixelRatio * e.clientX, 'y': window.devicePixelRatio * e.clientY};
const canvasp = screen_to_canvas(state, screenp);
const raw_canvasp = {...canvasp};
if (state.snap === 'grid') {
const step = grid_snap_step(state);
canvasp.x = Math.round(canvasp.x / step) * step;
canvasp.y = Math.round(canvasp.y / step) * step;
}
if (e.button !== 0 && e.button !== 1) {
return;
@ -225,7 +209,7 @@ function mousedown(e, state, context) { @@ -225,7 +209,7 @@ function mousedown(e, state, context) {
// Check for resize first, because it supports
// clicking slightly outside of the image
const image = get_image(context, state.active_image);
const corner = image_corner(state, image, canvasp);
const corner = image_corner(state, image, raw_canvasp);
if (corner !== null) {
// Resize
state.imagescaling = true;
@ -244,11 +228,13 @@ function mousedown(e, state, context) { @@ -244,11 +228,13 @@ function mousedown(e, state, context) {
// Only do picking logic if we haven't started imagescaling already
if (!state.imagescaling) {
const image = image_at(context, canvasp.x, canvasp.y);
const image = image_at(context, raw_canvasp.x, raw_canvasp.y);
if (image !== null) {
state.active_image = image.key;
// Allow immediately moving
state.imagemoving = true;
image.raw_at.x = image.at.x;
image.raw_at.y = image.at.y;
} else {
state.active_image = null;
}
@ -278,11 +264,18 @@ function mousemove(e, state, context) { @@ -278,11 +264,18 @@ function mousemove(e, state, context) {
const screenp = {'x': window.devicePixelRatio * e.clientX, 'y': window.devicePixelRatio * e.clientY};
const canvasp = screen_to_canvas(state, screenp);
const raw_canvasp = {...canvasp};
if (state.snap === 'grid') {
const step = grid_snap_step(state);
canvasp.x = Math.round(canvasp.x / step) * step;
canvasp.y = Math.round(canvasp.y / step) * step;
}
if (state.tools.active === 'pointer') {
if (state.active_image !== null) {
const image = get_image(context, state.active_image);
const corner = image_corner(state, image, canvasp);
const corner = image_corner(state, image, raw_canvasp);
if (state.scaling_corner === null) {
document.querySelector('canvas').classList.remove('resize-topleft');
@ -301,8 +294,9 @@ function mousemove(e, state, context) { @@ -301,8 +294,9 @@ function mousemove(e, state, context) {
const me = state.players[state.me];
const width = Math.max(me.width * state.canvas.zoom, 2.0);
const radius = Math.round(width / 2);
const brush_x = screenp.x - radius - 2;
const brush_y = screenp.y - radius - 2;
const brush_screen = canvas_to_screen(state, canvasp);
const brush_x = brush_screen.x - radius - 2;
const brush_y = brush_screen.y - radius - 2;
document.querySelector('.brush-dom').style.transform = `translate(${brush_x}px, ${brush_y}px)`;
}
@ -367,8 +361,17 @@ function mousemove(e, state, context) { @@ -367,8 +361,17 @@ function mousemove(e, state, context) {
const dx = e.movementX / state.canvas.zoom;
const dy = e.movementY / state.canvas.zoom;
image.at.x += dx;
image.at.y += dy;
image.raw_at.x += dx;
image.raw_at.y += dy;
if (state.snap === 'grid') {
const step = grid_snap_step(state);
image.at.x = Math.round(image.raw_at.x / step) * step;
image.at.y = Math.round(image.raw_at.y / step) * step;
} else if (state.snap === null) {
image.at.x = image.raw_at.x;
image.at.y = image.raw_at.y;
}
do_draw = true;
}
@ -438,6 +441,13 @@ function mousemove(e, state, context) { @@ -438,6 +441,13 @@ function mousemove(e, state, context) {
function mouseup(e, state, context) {
const screenp = {'x': window.devicePixelRatio * e.clientX, 'y': window.devicePixelRatio * e.clientY};
const canvasp = screen_to_canvas(state, screenp);
const raw_canvasp = {...canvasp};
if (state.snap === 'grid') {
const step = grid_snap_step(state);
canvasp.x = Math.round(canvasp.x / step) * step;
canvasp.y = Math.round(canvasp.y / step) * step;
}
if (e.button !== 0 && e.button !== 1) {
return;
@ -451,6 +461,8 @@ function mouseup(e, state, context) { @@ -451,6 +461,8 @@ function mouseup(e, state, context) {
if (state.imagemoving) {
state.imagemoving = false;
const image = get_image(context, state.active_image);
image.raw_at.x = image.at.x;
image.raw_at.y = image.at.y;
queue_event(state, image_move_event(state.active_image, image.at.x, image.at.y));
schedule_draw(state, context);
return;

134
client/webgl_shaders.js

@ -1,106 +1,3 @@ @@ -1,106 +1,3 @@
const simple_vs_src = `#version 300 es
in vec2 a_pos;
uniform vec2 u_scale;
uniform vec2 u_res;
uniform vec2 u_translation;
out vec2 v_uv;
flat out int v_quad_id;
void main() {
vec2 screen01 = (a_pos * u_scale + u_translation) / u_res;
vec2 screen02 = screen01 * 2.0;
screen02.y = 2.0 - screen02.y;
int vertex_index = gl_VertexID % 6;
if (vertex_index == 0) {
v_uv = vec2(0.0, 0.0);
} else if (vertex_index == 1 || vertex_index == 5) {
v_uv = vec2(1.0, 0.0);
} else if (vertex_index == 2 || vertex_index == 4) {
v_uv = vec2(0.0, 1.0);
} else {
v_uv = vec2(1.0, 1.0);
}
v_quad_id = gl_VertexID / 6;
gl_Position = vec4(screen02 - 1.0, 0.0, 1.0);
}
`;
const simple_fs_src = `#version 300 es
precision highp float;
in vec2 v_uv;
flat in int v_quad_id;
layout(location = 0) out vec4 FragColor;
void main() {
vec2 pixel = fwidth(v_uv);
vec2 border = 2.0 * pixel;
if (border.x <= v_uv.x && v_uv.x <= 1.0 - border.x && border.y <= v_uv.y && v_uv.y <= 1.0 - border.y) {
discard;
} else {
vec3 color = vec3(float(v_quad_id * 869363 % 255) / 255.0, float(v_quad_id * 278975 % 255) / 255.0, float(v_quad_id * 587286 % 255) / 255.0);
float alpha = 0.5;
FragColor = vec4(color * alpha, alpha);
}
}
`;
const opaque_vs_src = `#version 300 es
in vec3 a_pos; // .z is radius
in vec4 a_line;
in int a_stroke_id;
uniform vec2 u_scale;
uniform vec2 u_res;
uniform vec2 u_translation;
uniform int u_stroke_count;
flat out int v_stroke_id;
void main() {
// Do not inflate quad (as opposed to the full sdf shader), thus only leaving the opaque part
// Shrink to not include the caps
vec2 line_dir = normalize(a_line.zw - a_line.xy);
int vertex_index = gl_VertexID % 4;
vec2 pos = a_pos.xy;
if (vertex_index == 0 || vertex_index == 2) {
// vertices on the "beginning" side of the line
pos.xy += line_dir * a_pos.z / 2.0;
} else {
// on the "ending" side of the line
pos.xy -= line_dir * a_pos.z / 2.0;
}
vec2 screen01 = (pos * u_scale + u_translation) / u_res;
vec2 screen02 = screen01 * 2.0;
screen02.y = 2.0 - screen02.y;
v_stroke_id = a_stroke_id;
gl_Position = vec4(screen02 - 1.0, (float(a_stroke_id) / float(u_stroke_count)) * 2.0 - 1.0, 1.0);
}
`;
const nop_fs_src = `#version 300 es
precision highp float;
flat in int v_stroke_id;
layout(location = 0) out vec4 FragColor;
void main() {
vec3 color = vec3(float(v_stroke_id * 3245 % 255) / 255.0, float(v_stroke_id * 7343 % 255) / 255.0, float(v_stroke_id * 5528 % 255) / 255.0);
FragColor = vec4(color, 1.0);
}
`;
const sdf_vs_src = `#version 300 es
in vec2 a_a; // point from
in vec2 a_b; // point to
@ -398,21 +295,13 @@ function init_webgl(state, context) { @@ -398,21 +295,13 @@ function init_webgl(state, context) {
const sdf_vs = create_shader(gl, gl.VERTEX_SHADER, sdf_vs_src);
const sdf_fs = create_shader(gl, gl.FRAGMENT_SHADER, sdf_fs_src);
const opaque_vs = create_shader(gl, gl.VERTEX_SHADER, opaque_vs_src);
const nop_fs = create_shader(gl, gl.FRAGMENT_SHADER, nop_fs_src);
const simple_vs = create_shader(gl, gl.VERTEX_SHADER, simple_vs_src);
const simple_fs = create_shader(gl, gl.FRAGMENT_SHADER, simple_fs_src);
const dots_vs = create_shader(gl, gl.VERTEX_SHADER, dots_vs_src);
const dots_fs = create_shader(gl, gl.FRAGMENT_SHADER, dots_fs_src);
const grid_vs = create_shader(gl, gl.VERTEX_SHADER, grid_vs_src);
context.programs['image'] = create_program(gl, quad_vs, quad_fs);
context.programs['debug'] = create_program(gl, simple_vs, simple_fs);
context.programs['sdf'] = {
'opaque': create_program(gl, opaque_vs, nop_fs),
'main': create_program(gl, sdf_vs, sdf_fs),
};
context.programs['pattern'] = {
@ -431,26 +320,7 @@ function init_webgl(state, context) { @@ -431,26 +320,7 @@ function init_webgl(state, context) {
'u_color': gl.getUniformLocation(context.programs['image'], 'u_color'),
};
context.locations['debug'] = {
'a_pos': gl.getAttribLocation(context.programs['debug'], 'a_pos'),
'u_res': gl.getUniformLocation(context.programs['debug'], 'u_res'),
'u_scale': gl.getUniformLocation(context.programs['debug'], 'u_scale'),
'u_translation': gl.getUniformLocation(context.programs['debug'], 'u_translation'),
};
context.locations['sdf'] = {
'opaque': {
'a_pos': gl.getAttribLocation(context.programs['sdf'].opaque, 'a_pos'),
'a_line': gl.getAttribLocation(context.programs['sdf'].opaque, 'a_line'),
'a_stroke_id': gl.getAttribLocation(context.programs['sdf'].opaque, 'a_stroke_id'),
'u_res': gl.getUniformLocation(context.programs['sdf'].opaque, 'u_res'),
'u_scale': gl.getUniformLocation(context.programs['sdf'].opaque, 'u_scale'),
'u_translation': gl.getUniformLocation(context.programs['sdf'].opaque, 'u_translation'),
'u_stroke_count': gl.getUniformLocation(context.programs['sdf'].opaque, 'u_stroke_count'),
},
'main': {
'a_a': gl.getAttribLocation(context.programs['sdf'].main, 'a_a'),
'a_b': gl.getAttribLocation(context.programs['sdf'].main, 'a_b'),
@ -489,10 +359,6 @@ function init_webgl(state, context) { @@ -489,10 +359,6 @@ function init_webgl(state, context) {
}
};
context.buffers['debug'] = {
'b_packed': gl.createBuffer(),
};
context.buffers['image'] = {
'b_quads': gl.createBuffer(),
};

Loading…
Cancel
Save