You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
6.6 KiB

2 years ago
const stroke_vs_src = `
2 years ago
attribute vec2 a_pos;
attribute vec3 a_color;
uniform vec2 u_scale;
uniform vec2 u_res;
uniform vec2 u_translation;
uniform int u_layer;
varying vec3 v_color;
void main() {
vec2 screen01 = (a_pos * u_scale + u_translation) / u_res;
vec2 screen02 = screen01 * 2.0;
screen02.y = 2.0 - screen02.y;
vec2 screen11 = screen02 - 1.0;
v_color = a_color;
gl_Position = vec4(screen11, u_layer, 1);
}
`;
2 years ago
const stroke_fs_src = `
2 years ago
precision mediump float;
varying vec3 v_color;
void main() {
2 years ago
gl_FragColor = vec4(v_color, 1.0);
2 years ago
}
`;
2 years ago
const tquad_vs_src = `
attribute vec2 a_pos;
attribute vec2 a_texcoord;
uniform vec2 u_scale;
uniform vec2 u_res;
uniform vec2 u_translation;
uniform int u_layer;
varying vec2 v_texcoord;
void main() {
vec2 screen01 = (a_pos * u_scale + u_translation) / u_res;
vec2 screen02 = screen01 * 2.0;
screen02.y = 2.0 - screen02.y;
vec2 screen11 = screen02 - 1.0;
v_texcoord = a_texcoord;
gl_Position = vec4(screen11, u_layer, 1);
}
`;
const tquad_fs_src = `
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
gl_FragColor = texture2D(u_texture, v_texcoord);
}
`;
2 years ago
function init_webgl(state, context) {
context.canvas = document.querySelector('#c');
context.gl = context.canvas.getContext('webgl', {
'preserveDrawingBuffer': true,
'desynchronized': true,
'antialias': true,
});
2 years ago
const gl = context.gl;
gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
const stroke_vs = create_shader(gl, gl.VERTEX_SHADER, stroke_vs_src);
const stroke_fs = create_shader(gl, gl.FRAGMENT_SHADER, stroke_fs_src);
const quad_vs = create_shader(gl, gl.VERTEX_SHADER, tquad_vs_src);
const quad_fs = create_shader(gl, gl.FRAGMENT_SHADER, tquad_fs_src);
context.programs['stroke'] = create_program(gl, stroke_vs, stroke_fs);
context.programs['quad'] = create_program(gl, quad_vs, quad_fs);
context.locations['stroke'] = {
'a_pos': gl.getAttribLocation(context.programs['stroke'], 'a_pos'),
'a_color': gl.getAttribLocation(context.programs['stroke'], 'a_color'),
'u_res': gl.getUniformLocation(context.programs['stroke'], 'u_res'),
'u_scale': gl.getUniformLocation(context.programs['stroke'], 'u_scale'),
'u_translation': gl.getUniformLocation(context.programs['stroke'], 'u_translation'),
'u_layer': gl.getUniformLocation(context.programs['stroke'], 'u_layer'),
};
context.locations['quad'] = {
'a_pos': gl.getAttribLocation(context.programs['quad'], 'a_pos'),
'a_texcoord': gl.getAttribLocation(context.programs['quad'], 'a_texcoord'),
'u_res': gl.getUniformLocation(context.programs['quad'], 'u_res'),
'u_scale': gl.getUniformLocation(context.programs['quad'], 'u_scale'),
'u_translation': gl.getUniformLocation(context.programs['quad'], 'u_translation'),
'u_layer': gl.getUniformLocation(context.programs['quad'], 'u_layer'),
};
context.buffers['stroke'] = {
'b_pos': context.gl.createBuffer(),
'b_color': context.gl.createBuffer(),
};
context.buffers['quad'] = {
'b_pos': context.gl.createBuffer(),
'b_texcoord': context.gl.createBuffer(),
};
context.textures['test'] = gl.createTexture();
// Fill the texture with a 1x1 blue pixel.
gl.bindTexture(gl.TEXTURE_2D, context.textures['test']);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
var image = new Image();
image.src = "http://192.168.100.2/images/3697505915";
image.addEventListener('load', function() {
// Now that the image has loaded make copy it to the texture.
context.quad_positions = [
100, 100,
100, 100 + image.height,
100 + image.width, 100 + image.height,
100 + image.width, 100,
100, 100,
100 + image.width, 100 + image.height,
];
context.quad_texcoords = [
0, 0,
0, 1,
1, 1,
1, 0,
0, 0,
1, 1,
];
context.quad_positions_f32 = new Float32Array(context.quad_positions);
context.quad_texcoords_f32 = new Float32Array(context.quad_texcoords);
gl.bindTexture(gl.TEXTURE_2D, context.textures['test']);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,gl.UNSIGNED_BYTE, image);
});
2 years ago
const resize_canvas = (entries) => {
// https://www.khronos.org/webgl/wiki/HandlingHighDPI
const entry = entries[0];
2 years ago
2 years ago
let width;
let height;
if (entry.devicePixelContentBoxSize) {
width = entry.devicePixelContentBoxSize[0].inlineSize;
height = entry.devicePixelContentBoxSize[0].blockSize;
} else if (entry.contentBoxSize) {
2 years ago
// fallback for Safari that will not always be correct
2 years ago
width = Math.round(entry.contentBoxSize[0].inlineSize * devicePixelRatio);
height = Math.round(entry.contentBoxSize[0].blockSize * devicePixelRatio);
}
context.canvas.width = width;
context.canvas.height = height;
window.requestAnimationFrame(() => draw(state, context));
}
const resize_observer = new ResizeObserver(resize_canvas);
resize_observer.observe(context.canvas);
}
function create_shader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader;
}
console.error(type, ':', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
function create_program(gl, vs, fs) {
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
return program;
}
console.error('link:', gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}