Browse Source

Grid background pattern

ssao
A.Olokhtonov 6 months ago
parent
commit
bf2eace6fe
  1. 4
      client/index.js
  2. 61
      client/webgl_draw.js
  3. 24
      client/webgl_geometry.js
  4. 75
      client/webgl_shaders.js

4
client/index.js

@ -14,7 +14,7 @@ const config = { @@ -14,7 +14,7 @@ const config = {
buffer_first_touchmoves: 5,
debug_print: false,
zoom_delta: 0.05,
min_zoom_level: -150,
min_zoom_level: -250,
max_zoom_level: 40,
initial_offline_timeout: 1000,
default_color: 0x00,
@ -230,6 +230,8 @@ async function main() { @@ -230,6 +230,8 @@ async function main() {
'color_picked': null,
'wasm': {},
'background_pattern': 'dots',
};
const context = {

61
client/webgl_draw.js

@ -103,11 +103,12 @@ async function draw(state, context) { @@ -103,11 +103,12 @@ async function draw(state, context) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Draw the background pattern
gl.useProgram(context.programs['pattern'].dots);
buffers = context.buffers['pattern'];
locations = context.locations['pattern'].dots;
{
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']);
if (state.background_pattern === 'dots') {
gl.useProgram(context.programs['pattern'].dots);
buffers = context.buffers['pattern'];
locations = context.locations['pattern'].dots;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance_dot']);
gl.enableVertexAttribArray(locations['a_center']);
gl.vertexAttribPointer(locations['a_center'], 2, gl.FLOAT, false, 2 * 4, 0);
gl.vertexAttribDivisor(locations['a_center'], 1);
@ -129,7 +130,7 @@ async function draw(state, context) { @@ -129,7 +130,7 @@ async function draw(state, context) {
gl.uniform1f(locations['u_fadeout'], t);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance_dot']);
gl.bufferData(gl.ARRAY_BUFFER, dot_instances, gl.STREAM_DRAW);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, dot_instances.length / 2);
@ -142,14 +143,58 @@ async function draw(state, context) { @@ -142,14 +143,58 @@ async function draw(state, context) {
gl.uniform1f(locations['u_fadeout'], t);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance_dot']);
gl.bufferData(gl.ARRAY_BUFFER, dot_instances, gl.STREAM_DRAW);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, dot_instances.length / 2);
}
} else if (state.background_pattern === 'grid') {
const zoom = state.canvas.zoom;
const zoom_log10 = Math.log10(zoom);
const zoom_previous = Math.pow(10, Math.floor(zoom_log10));
gl.useProgram(context.programs['pattern'].grid);
buffers = context.buffers['pattern'];
locations = context.locations['pattern'].grid;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance_grid']);
gl.enableVertexAttribArray(locations['a_data']);
gl.vertexAttribPointer(locations['a_data'], 2, gl.FLOAT, false, 2 * 4, 0);
gl.vertexAttribDivisor(locations['a_data'], 1);
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.uniform1f(locations['u_fadeout'], 1.0);
// Previous level
{
const grid_instances = new Float32Array(geometry_gen_fullscreen_grid_1d(state, context, 10 / zoom_previous, 10 / zoom_previous));
const t = Math.min(1.0, (zoom / zoom_previous) / 10.0);
gl.uniform1f(locations['u_fadeout'], t);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance_grid']);
gl.bufferData(gl.ARRAY_BUFFER, grid_instances, gl.STREAM_DRAW);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, grid_instances.length / 2);
}
// Next level
{
const grid_instances = new Float32Array(geometry_gen_fullscreen_grid_1d(state, context, 100 / zoom_previous, 100 / zoom_previous));
const t = Math.min(1.0, 1.0 - (zoom / zoom_previous) / 10.0);
gl.uniform1f(locations['u_fadeout'], t);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance_grid']);
gl.bufferData(gl.ARRAY_BUFFER, grid_instances, gl.STREAM_DRAW);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, grid_instances.length / 2);
}
}
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.clear(gl.DEPTH_BUFFER_BIT); // draw strokes above the background pattern
gl.useProgram(context.programs['sdf'].main);
buffers = context.buffers['sdf'];
locations = context.locations['sdf'].main;

24
client/webgl_geometry.js

@ -333,3 +333,27 @@ function geometry_gen_fullscreen_grid(state, context, step_x, step_y) { @@ -333,3 +333,27 @@ function geometry_gen_fullscreen_grid(state, context, step_x, step_y) {
return result;
}
function geometry_gen_fullscreen_grid_1d(state, context, step_x, step_y) {
const result = [];
const width = context.canvas.width;
const height = context.canvas.height;
const topleft = screen_to_canvas(state, {'x': 0, 'y': 0});
const bottomright = screen_to_canvas(state, {'x': width, 'y': height});
topleft.x = Math.floor(topleft.x / step_x) * step_x;
topleft.y = Math.ceil(topleft.y / step_y) * step_y;
bottomright.x = Math.floor(bottomright.x / step_x) * step_x;
bottomright.y = Math.ceil(bottomright.y / step_y) * step_y;
for (let x = topleft.x; x <= bottomright.x; x += step_x) {
result.push(1, x);
}
for (let y = topleft.y; y <= bottomright.y; y += step_y) {
result.push(-1, y);
}
return result;
}

75
client/webgl_shaders.js

@ -249,6 +249,66 @@ const tquad_fs_src = `#version 300 es @@ -249,6 +249,66 @@ const tquad_fs_src = `#version 300 es
}
`;
const grid_vs_src = `#version 300 es
in vec2 a_data; // per-instance
out float v_fadeout;
uniform vec2 u_scale;
uniform vec2 u_res;
uniform vec2 u_translation;
uniform float u_fadeout;
void main() {
vec2 origin;
vec2 minor_offset;
vec2 major_offset;
vec2 pixel = 2.0 / u_res;
if (a_data.x > 0.0) {
// Vertical, treat Y as X
float x = a_data.y;
origin = vec2(x, 0.0);
minor_offset = pixel * vec2(1.0, 0.0);
major_offset = vec2(0.0, 2.0);
} else {
// Horizontal, treat Y as Y
float y = a_data.y;
origin = vec2(0.0, y);
minor_offset = pixel * vec2(0.0, 1.0);
major_offset = vec2(2.0, 0.0);
}
vec2 v = (origin * u_scale + u_translation) / u_res * 2.0;
vec2 pos;
if (a_data.x > 0.0) {
v.y = 0.0;
} else {
v.x = 0.0;
}
if (gl_VertexID % 6 == 0) {
pos = v;
} else if (gl_VertexID % 6 == 1 || gl_VertexID % 6 == 5) {
pos = v + (a_data.x > 0.0 ? minor_offset : major_offset);
//pos = v + minor_offset;
} else if (gl_VertexID % 6 == 2 || gl_VertexID % 6 == 4) {
pos = v + (a_data.x > 0.0 ? major_offset : minor_offset);
//pos = v + major_offset;
} else if (gl_VertexID % 6 == 3) {
pos = v + major_offset + minor_offset;
//pos = v + major_offset + minor_offset;
}
vec2 screen02 = pos;
screen02.y = 2.0 - screen02.y;
v_fadeout = u_fadeout;
gl_Position = vec4(screen02 - 1.0, 0.0, 1.0);
}
`;
const dots_vs_src = `#version 300 es
in vec2 a_center; // per-instance
@ -334,6 +394,8 @@ function init_webgl(state, context) { @@ -334,6 +394,8 @@ function init_webgl(state, context) {
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'] = {
@ -342,6 +404,7 @@ function init_webgl(state, context) { @@ -342,6 +404,7 @@ function init_webgl(state, context) {
};
context.programs['pattern'] = {
'dots': create_program(gl, dots_vs, dots_fs),
'grid': create_program(gl, grid_vs, dots_fs),
};
context.locations['debug'] = {
@ -389,6 +452,15 @@ function init_webgl(state, context) { @@ -389,6 +452,15 @@ function init_webgl(state, context) {
'u_scale': gl.getUniformLocation(context.programs['pattern'].dots, 'u_scale'),
'u_translation': gl.getUniformLocation(context.programs['pattern'].dots, 'u_translation'),
'u_fadeout': gl.getUniformLocation(context.programs['pattern'].dots, 'u_fadeout'),
},
'grid': {
'a_data': gl.getAttribLocation(context.programs['pattern'].grid, 'a_data'),
'u_res': gl.getUniformLocation(context.programs['pattern'].grid, 'u_res'),
'u_scale': gl.getUniformLocation(context.programs['pattern'].grid, 'u_scale'),
'u_translation': gl.getUniformLocation(context.programs['pattern'].grid, 'u_translation'),
'u_fadeout': gl.getUniformLocation(context.programs['pattern'].grid, 'u_fadeout'),
}
};
@ -402,7 +474,8 @@ function init_webgl(state, context) { @@ -402,7 +474,8 @@ function init_webgl(state, context) {
};
context.buffers['pattern'] = {
'b_instance': gl.createBuffer(),
'b_instance_dot': gl.createBuffer(),
'b_instance_grid': gl.createBuffer(),
'b_dot': gl.createBuffer(),
};

Loading…
Cancel
Save