Browse Source

HSV random colors, bring back fade, fix alpha in shader, rasterize numbers to separate texture, start with number quads

master
Aleksey Olokhtonov 4 months ago
parent
commit
31584dcf91
  1. 88
      geometry.js
  2. 48
      render.js

88
geometry.js

@ -1,6 +1,31 @@ @@ -1,6 +1,31 @@
let colors = {};
let rasterized = {};
// https://stackoverflow.com/a/17243070
function hsv_to_rgb(h, s, v) {
let r, g, b;
const i = Math.floor(h * 6);
const f = h * 6 - i;
const p = v * (1 - s);
const q = v * (1 - f * s);
const t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return [
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255)
];
}
function get_color(stage_name) {
if (stage_name in config.predefined_colors) {
return config.predefined_colors[stage_name];
@ -10,11 +35,7 @@ function get_color(stage_name) { @@ -10,11 +35,7 @@ function get_color(stage_name) {
return colors[stage_name];
}
const r = Math.floor(Math.random() * 155);
const g = Math.floor(Math.random() * 155);
const b = Math.floor(Math.random() * 155);
colors[stage_name] = [ 100 + r, 100 + g, 100 + b ];
colors[stage_name] = hsv_to_rgb(Math.random(), 0.56, 0.56);
return colors[stage_name];
}
@ -22,21 +43,12 @@ function get_color(stage_name) { @@ -22,21 +43,12 @@ function get_color(stage_name) {
function rasterize_and_pack(text, cycles) {
// TODO: handle texture is full or stuff don't fit (unlikely)
const key = text + '@' + cycles;
const key = text;
if (key in rasterized) {
return rasterized[key];
}
let cycles_total_padding = (cycles - 1) * config.padding;
let bonus_cells = Math.ceil(cycles_total_padding / config.w);
const tiles_needed = 1; // cycles - 1 + 1 + bonus_cells; // stage name + count cycles from one
if (tiles_needed > config.raster_texture_size / config.w - raster_tile.x) {
raster_tile.x = 0;
raster_tile.y += 1;
}
const u = raster_tile.x * config.w / config.raster_texture_size;
const v = raster_tile.y * config.h / config.raster_texture_size;
@ -50,18 +62,42 @@ function rasterize_and_pack(text, cycles) { @@ -50,18 +62,42 @@ function rasterize_and_pack(text, cycles) {
);
raster_tile.x += 1;
/*
raster_tile.x += cycles + bonus_cells;
if (raster_tile.x === config.raster_texture_size / config.w) {
raster_tile.x = 0;
raster_tile.y += 1;
}
*/
rasterized[key] = [u, v];
if (cycles > 1) {
gl.bindTexture(gl.TEXTURE_2D, textures['numbers']);
for (let i = numbers_rasterized + 1; i <= cycles; ++i) {
const u = number_tile.x * config.w / config.raster_texture_size;
const v = number_tile.y * config.h / config.raster_texture_size;
rasterize(i);
gl.texSubImage2D(gl.TEXTURE_2D, 0,
number_tile.x * config.w, number_tile.y * config.h,
config.w, config.h,
gl.RGBA, gl.UNSIGNED_BYTE,
c2d.canvas
);
number_tile.x += 1;
if (number_tile.x === config.raster_texture_size / config.w) {
number_tile.x = 0;
number_tile.y += 1;
}
rasterized[i] = [u, v];
}
if (cycles > numbers_rasterized) {
numbers_rasterized = cycles;
}
}
return [u, v];
}
@ -83,10 +119,7 @@ function pack_instruction(instruction, positions, sizes, colors, uvs, starts, y) @@ -83,10 +119,7 @@ function pack_instruction(instruction, positions, sizes, colors, uvs, starts, y)
let a = 255;
if (!instruction.retired) {
r = Math.max(50, r - 50);
g = Math.max(50, g - 50);
b = Math.max(50, b - 50);
a = 100;
a = 80;
}
const [u, v] = rasterize_and_pack(stage.name, stage_cycles);
@ -123,6 +156,7 @@ function generate(trace_id) { @@ -123,6 +156,7 @@ function generate(trace_id) {
for (let i = 0; i < instructions.length; ++i) {
const instruction = instructions[i];
// TODO: make all quads same size, abuse this fact
result.count += pack_instruction(instruction, positions, sizes, colors, uvs, starts, y);
if (config.limit > 0 && result.count >= config.limit) {
break;
@ -132,7 +166,7 @@ function generate(trace_id) { @@ -132,7 +166,7 @@ function generate(trace_id) {
starts.push(positions.length);
if (false) {
if (config.show_texture) {
result.pos = new Float32Array([0, 0]);
result.size = new Float32Array([config.raster_texture_size, config.raster_texture_size]);
result.color = new Uint8Array([0, 0, 0, 255]);
@ -158,6 +192,10 @@ function generate(trace_id) { @@ -158,6 +192,10 @@ function generate(trace_id) {
}
function clip(quads) {
if (config.show_texture) {
return quads;
}
const tl = screen_to_canvas({'x': 0, 'y': 0});
const br = screen_to_canvas({'x': 0, 'y': canvas.height});

48
render.js

@ -29,6 +29,7 @@ let config = { @@ -29,6 +29,7 @@ let config = {
zoom_delta: 0.05,
raster_texture_size: 4096,
max_zoom_level: 0,
show_texture: false,
};
let canvas = null;
@ -43,7 +44,9 @@ let zoom_screenp = { 'x': 0, 'y': 0 }; @@ -43,7 +44,9 @@ let zoom_screenp = { 'x': 0, 'y': 0 };
let last_frame_dt = 0;
let last_frame_ts = 0;
let raster_tile = { 'x': 0, 'y': 0 };
let number_tile = { 'x': 0, 'y': 0 };
let spacedown = false;
let numbers_rasterized = 0;
const tquad_vs_src = `#version 300 es
in vec2 a_pos;
@ -56,6 +59,7 @@ const tquad_vs_src = `#version 300 es @@ -56,6 +59,7 @@ const tquad_vs_src = `#version 300 es
uniform float u_scale;
uniform vec2 u_textile;
uniform vec2 u_tile;
uniform int u_single;
out vec4 v_color;
out vec2 v_uv;
@ -72,7 +76,11 @@ const tquad_vs_src = `#version 300 es @@ -72,7 +76,11 @@ const tquad_vs_src = `#version 300 es
}
vec2 cycles = a_size / u_tile;
vec2 tt = u_textile / u_tile;
vec2 size = a_size;
if (u_single != 0) {
size = u_tile;
}
if (vertex_index == 0) {
// "top left" aka "p1"
@ -80,16 +88,16 @@ const tquad_vs_src = `#version 300 es @@ -80,16 +88,16 @@ const tquad_vs_src = `#version 300 es
uv = a_uv;
} else if (vertex_index == 1 || vertex_index == 5) {
// "top right" aka "p2"
corner = a_pos + vec2(a_size.x, 0);
uv = a_uv + vec2(u_textile.x * cycles.x, 0);
corner = a_pos + vec2(size.x, 0);
uv = a_uv + vec2(u_textile.x, 0);
} else if (vertex_index == 2 || vertex_index == 4) {
// "bottom left" aka "p3"
corner = a_pos + vec2(0, a_size.y);
uv = a_uv + vec2(0, u_textile.y * cycles.y);
corner = a_pos + vec2(0, size.y);
uv = a_uv + vec2(0, u_textile.y);
} else {
// "bottom right" aka "p4"
corner = a_pos + a_size;
uv = a_uv + u_textile * cycles;
corner = a_pos + size;
uv = a_uv + u_textile;
}
vec2 screen02 = (corner.xy * vec2(u_scale) + u_translation) / u_res * 2.0;
@ -109,13 +117,18 @@ const tquad_fs_src = `#version 300 es @@ -109,13 +117,18 @@ const tquad_fs_src = `#version 300 es
uniform sampler2D u_texture;
uniform float u_fade;
uniform int u_solid;
layout(location = 0) out vec4 FragColor;
void main() {
if (u_solid != 0) {
FragColor = vec4(v_color.rgb * v_color.a, v_color.a);
} else {
vec4 text = texture(u_texture, v_uv);
text.a = min(min(text.a, v_color.a), u_fade);
FragColor = vec4(text.rgb * text.a + v_color.rgb, 1.0);
float a = min(u_fade, min(text.a, v_color.a));
FragColor = vec4(text.rgb * a, a);
}
}
`;
@ -177,6 +190,8 @@ function draw(ts, animation) { @@ -177,6 +190,8 @@ function draw(ts, animation) {
gl.uniform1i(program.locations['u_texture'], textures['raster']);
gl.uniform2f(program.locations['u_tile'], config.w, config.h);
gl.uniform1f(program.locations['u_fade'], fade);
gl.uniform1i(program.locations['u_solid'], 1);
gl.uniform1i(program.locations['u_single'], 0);
gl.enableVertexAttribArray(program.locations['a_pos']);
gl.enableVertexAttribArray(program.locations['a_size']);
@ -193,8 +208,14 @@ function draw(ts, animation) { @@ -193,8 +208,14 @@ function draw(ts, animation) {
gl.vertexAttribDivisor(program.locations['a_color'], 1);
gl.vertexAttribDivisor(program.locations['a_uv'], 1);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, clipped.count);
if (fade > 0) {
gl.bindTexture(gl.TEXTURE_2D, textures['raster']);
gl.uniform1i(program.locations['u_solid'], 0);
gl.uniform1i(program.locations['u_single'], 1);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, clipped.count);
}
gl.vertexAttribDivisor(program.locations['a_pos'], 0);
gl.vertexAttribDivisor(program.locations['a_size'], 0);
@ -278,8 +299,12 @@ function init_webgl() { @@ -278,8 +299,12 @@ function init_webgl() {
textures = {
'raster': gl.createTexture(),
'numbers': gl.createTexture(),
};
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
const zeroes = new Uint8Array(config.raster_texture_size * config.raster_texture_size * 4);
gl.bindTexture(gl.TEXTURE_2D, textures['raster']);
@ -287,6 +312,11 @@ function init_webgl() { @@ -287,6 +312,11 @@ function init_webgl() {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, config.raster_texture_size, config.raster_texture_size, 0, gl.RGBA, gl.UNSIGNED_BYTE, zeroes); // fill the whole texture once with zeroes to kill a warning about a partial upload
gl.bindTexture(gl.TEXTURE_2D, textures['numbers']);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, config.raster_texture_size, config.raster_texture_size, 0, gl.RGBA, gl.UNSIGNED_BYTE, zeroes); // fill the whole texture once with zeroes to kill a warning about a partial upload
const resize_canvas = (entries) => {
// https://www.khronos.org/webgl/wiki/HandlingHighDPI
const entry = entries[0];

Loading…
Cancel
Save