Published
Edited
Nov 2, 2019
4 stars
Insert cell
Insert cell
Insert cell
viewof gl = {
const canvas = DOM.canvas(width, height);
canvas.style.maxWidth = "100%";
canvas.value = canvas.getContext("webgl");
return canvas;
}
Insert cell
image = Object.assign(await FileAttachment("solo.jpeg").image(), {height: 40})
Insert cell
fragmentShader = {
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, `
precision highp float;

uniform sampler2D u_image;
uniform vec2 u_size;
uniform vec3 u_weight;

float rgb_lrgb(float v) {
return v <= 0.04045 ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
}

float lrgb_rgb(float v) {
return v <= 0.0031308 ? 12.92 * v : 1.055 * pow(v, 1.0 / 2.4) - 0.055;
}

vec3 rgb_lrgb(vec3 v) {
return vec3(rgb_lrgb(v.r), rgb_lrgb(v.g), rgb_lrgb(v.b));
}

void main() {
float x = gl_FragCoord.x / u_size.x;
float y = 1.0 - gl_FragCoord.y / u_size.y;
vec3 rgb = u_weight * rgb_lrgb(texture2D(u_image, vec2(x, y)).rgb);
gl_FragColor = vec4(vec3(lrgb_rgb(rgb.r + rgb.g + rgb.b)), 1.0);
}
`);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(shader));
}
return shader;
}
Insert cell
init = {
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.enableVertexAttribArray(a_vertex);
gl.vertexAttribPointer(a_vertex, 2, gl.FLOAT, false, 0, 0);
gl.uniform2f(u_size, width, height);
}
Insert cell
draw = {
init;
gl.uniform3f(u_weight, config.r, config.g, config.b);
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
}
Insert cell
program = {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
return program;
}
Insert cell
u_size = gl.getUniformLocation(program, "u_size")
Insert cell
u_weight = gl.getUniformLocation(program, "u_weight")
Insert cell
u_gamma = gl.getUniformLocation(program, "u_gamma")
Insert cell
vertexBuffer = {
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, Float32Array.of(-1, -1, +1, -1, +1, +1, -1, +1), gl.STATIC_DRAW);
return buffer;
}
Insert cell
vertexShader = {
const shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, `
attribute vec2 a_vertex;

void main(void) {
gl_Position = vec4(a_vertex, 0.0, 1.0);
}
`);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(shader));
}
return shader;
}
Insert cell
a_vertex = gl.getAttribLocation(program, "a_vertex")
Insert cell
texture = {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
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);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
return texture;
}
Insert cell
width = image.naturalWidth
Insert cell
height = image.naturalHeight
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more