Published
Edited
Jan 3, 2022
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
gl = {
const gl = canvas.getContext("webgl", {antialias: true, depth: false});
twgl.addExtensionsToContext(gl);
return gl;
}
Insert cell
zoom = {
d3.select(canvas)
.call(d3.zoom().on("zoom", ({transform}) => zoomed(transform)))
.call(d3.zoom().transform, d3.zoomIdentity.translate(0.6*width, 0.5*width).scale(0.3));
}
Insert cell
initialZoom={
zoomed({x:0.6*width,y:0.5*width,k:0.3})
}
Insert cell
mutable transX=0.6*width;
Insert cell
mutable transY=0.5*width;
Insert cell
mutable scale=0.3;
Insert cell
function zoomed(transform) {
mutable transX = transform.x;
mutable transY = transform.y;
mutable scale = transform.k;
}
Insert cell
programInfo = {
const programInfo = twgl.createProgramInfo(gl, [vertShader, fragShader]);
gl.useProgram(programInfo.program);
return programInfo;
}
Insert cell
render = {
const arrays = {
a_position: {numComponents: 2, data: vertices},
indices: {numComponents: 3, data: indices}
};
const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);

const uniforms =
{u_resolution: [gl.canvas.width, gl.canvas.height],
u_translate: [transX, transY],
u_scale: scale,
u_d: d}
twgl.setUniforms(programInfo, uniforms);
gl.drawElements(gl.TRIANGLES, 6 , gl.UNSIGNED_INT, 0);
}
Insert cell
vertShader = `
attribute vec2 a_position;

void main() {
gl_Position = vec4(a_position,0,1);
}
`
Insert cell
fragShader = `
precision highp float;

uniform vec2 u_resolution, u_translate;
uniform float u_scale;
uniform int u_d;

const int maxIters = ${maxIters};

vec3 colorScale( float t )
{
vec3 a,b,c,d;
a = vec3(0.5);
b = vec3(0.5);
c = vec3(1.);
d = vec3(0.,0.1,0.2);
return a + b*cos( 6.28318*(c*t+d) );
}

float mandelbrot(float x, float y) {
vec2 z, c;
float d = float(u_d);

c.x = x;
c.y = y;

z = c;
int iterCount = 0;
for(int i=0; i<maxIters; i++) {
float r = sqrt(z.x*z.x + z.y*z.y);
float theta = atan(z.y, z.x);
float rNew = pow(r,d);
float thetaNew = d*theta;
float x = rNew*cos(thetaNew) + c.x;
float y = rNew*sin(thetaNew) + c.y;
if((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
iterCount += 1;
}
return float(iterCount)/float(maxIters);
}

void main() {
float xpt = (gl_FragCoord.x - u_translate.x) / u_resolution.x / u_scale;
float ypt = (u_resolution.y - gl_FragCoord.y - u_translate.y) / u_resolution.y / u_scale;
float t = mandelbrot( xpt, ypt);
gl_FragColor = vec4(colorScale(fract(sqrt(t)+0.5)),1);
}
`
Insert cell
vertices=new Float32Array([-1.,-1.,1.,-1.,1.,1.,-1.,1.])
Insert cell
indices = new Uint32Array([0,1,2,0,2,3])
Insert cell
height=width
Insert cell
twgl = require("https://cdn.jsdelivr.net/npm/twgl-base.js@4.8.2/dist/4.x/twgl.min.js")
Insert cell
d3 = require("d3@6")
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