|
|
@ -106,21 +106,8 @@ async function draw(state, context) { |
|
|
|
gl.useProgram(context.programs['pattern'].dots); |
|
|
|
gl.useProgram(context.programs['pattern'].dots); |
|
|
|
buffers = context.buffers['pattern']; |
|
|
|
buffers = context.buffers['pattern']; |
|
|
|
locations = context.locations['pattern'].dots; |
|
|
|
locations = context.locations['pattern'].dots; |
|
|
|
|
|
|
|
{ |
|
|
|
if (state.canvas.zoom >= config.pattern_fadeout_min) { |
|
|
|
|
|
|
|
// Reused data
|
|
|
|
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_dot']); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const one_dot = new Float32Array(geometry_gen_circle(0, 0, 1, 32)); |
|
|
|
|
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, 32, 32, 50, 50)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, one_dot, gl.STREAM_DRAW); |
|
|
|
|
|
|
|
gl.enableVertexAttribArray(locations['a_xy']); |
|
|
|
|
|
|
|
gl.vertexAttribPointer(locations['a_xy'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Per-instance data
|
|
|
|
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']); |
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']); |
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, dot_instances, gl.STREAM_DRAW); |
|
|
|
|
|
|
|
gl.enableVertexAttribArray(locations['a_center']); |
|
|
|
gl.enableVertexAttribArray(locations['a_center']); |
|
|
|
gl.vertexAttribPointer(locations['a_center'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribPointer(locations['a_center'], 2, gl.FLOAT, false, 2 * 4, 0); |
|
|
|
gl.vertexAttribDivisor(locations['a_center'], 1); |
|
|
|
gl.vertexAttribDivisor(locations['a_center'], 1); |
|
|
@ -128,15 +115,38 @@ async function draw(state, context) { |
|
|
|
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); |
|
|
|
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_scale'], state.canvas.zoom, state.canvas.zoom); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); |
|
|
|
|
|
|
|
|
|
|
|
if (config.pattern_fadeout_min <= state.canvas.zoom && state.canvas.zoom <= config.pattern_fadeout_max) { |
|
|
|
const zoom = state.canvas.zoom; |
|
|
|
const t = (state.canvas.zoom - config.pattern_fadeout_min) / (config.pattern_fadeout_max - config.pattern_fadeout_min); |
|
|
|
const zoom_log2 = Math.log2(zoom); |
|
|
|
|
|
|
|
const zoom_previous = Math.pow(2, Math.floor(zoom_log2)); |
|
|
|
|
|
|
|
const zoom_next = Math.pow(2, Math.ceil(zoom_log2)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Previous level
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const one_dot = new Float32Array(geometry_gen_quad(0, 0, 1 / zoom_previous)); |
|
|
|
|
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, 32 / zoom_previous, 32 / zoom_previous)); |
|
|
|
|
|
|
|
const t = Math.min(1.0, 1.0 - (zoom / zoom_previous) / 2.0); |
|
|
|
|
|
|
|
|
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
|
} else { |
|
|
|
|
|
|
|
gl.uniform1f(locations['u_fadeout'], 1); |
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']); |
|
|
|
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, dot_instances, gl.STREAM_DRAW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, dot_instances.length / 2); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, one_dot.length / 2, dot_instances.length / 2); |
|
|
|
// Next level
|
|
|
|
|
|
|
|
if (zoom_previous != zoom_next) { |
|
|
|
|
|
|
|
const dot_instances = new Float32Array(geometry_gen_fullscreen_grid(state, context, 32 / zoom_next, 32 / zoom_next)); |
|
|
|
|
|
|
|
const t = Math.min(1.0, 1.0 - (zoom_next / zoom) / 2.0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.uniform1f(locations['u_fadeout'], t); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']); |
|
|
|
|
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, dot_instances, gl.STREAM_DRAW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, dot_instances.length / 2); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gl.clear(gl.DEPTH_BUFFER_BIT); |
|
|
|
gl.clear(gl.DEPTH_BUFFER_BIT); |
|
|
|