Public
Edited
Jan 15, 2024
Fork of Regl
1 fork
Insert cell
Insert cell
canvas = DOM.canvas(width, 600)
Insert cell
// Continuously updates
regl.frame(() => {
camera(function () {
regl.clear({ color: [0, 0.1, 0.26, 1] });
drawSDF();
// drawBunny();
});
})
Insert cell
camera = reglCamera(regl, {
element: regl._gl.canvas,
center: [0, 3.5, 0],
theta: (3.0 * Math.PI) / 4.0,
phi: Math.PI / 6.0,
distance: 20.0,
damping: 0,
noScroll: true,
renderOnDirty: true
})
Insert cell
drawSDF = {
const { triangle } = mkTriangle(20000);

return regl({
frag: `
#extension GL_OES_standard_derivatives : enable
precision mediump float;
${myRegl}
uniform mat4 projection, view, triangle;
varying vec2 vposition;
void main () {
mat4 a = projection * view * triangle;
float d = 0.0;
d = dist(vposition, vec2(a[0]));

vec4 center = (a[0] + a[1] + a[2]) / 3.0;
float d1 = sdf(vposition-vec2(a[0]), vec2(a[1]-a[0]), vec2(center-a[0]));
float d2 = sdf(vposition-vec2(a[1]), vec2(a[2]-a[1]), vec2(center-a[1]));
float d3 = sdf(vposition-vec2(a[2]), vec2(a[0]-a[2]), vec2(center-a[2]));

d = max(max(d1, d2), d3);
if (d > 0.0) {
if (d > d1 && d1 > 0.0) {d = d1;}
if (d > d2 && d2 > 0.0) {d = d2;}
if (d > d3 && d3 > 0.0) {d = d3;}
}

gl_FragColor = mix(vec4(vec3(d), 1.0), vec4(0.5 + d, 0.5, 0.5, 1.0), wireframe(d, 2.0, 0.1));
}`,
vert: `
precision mediump float;
uniform mat4 projection, view;
attribute vec2 position;
varying vec2 vposition;
void main () {
vposition = position;
gl_Position = vec4(position, 0.0, 1.0);
}`,
attributes: {
position: [
[-4, -1],
[1, -1],
[1, 4]
]
},
uniforms: {
triangle
},
blend: {
enable: true,
func: {
srcRGB: "src alpha",
srcAlpha: 1,
dstRGB: "one minus src alpha",
dstAlpha: 1
},
equation: {
rgb: "add",
alpha: "add"
},
color: [0, 0, 0, 0]
},
count: 3
});
}
Insert cell
myRegl = `
float dist(vec2 a, vec2 b) {
return sqrt(dot(a-b, a-b));
}

float sdf(vec2 p, vec2 v, vec2 c) {
vec2 u = vec2(v.y, -v.x);
if (dot(c, u) * dot(p, u) >= 0.0) {
return -abs(dot(p, u) / sqrt(dot(u, u)));
}

float vv = dot(v, v);
float pv = dot(p, v);
if (pv < 0.0) {
return sqrt(dot(p, p));
}
if (pv > vv) {
return sqrt(dot(p-v, p-v));
}
return abs(dot(p, u) / sqrt(dot(u, u)));
}

float wireframe (float parameter, float width, float feather) {
float w1 = width - feather * 0.5;
float d = fwidth(parameter);
float looped = 0.5 - abs(mod(parameter, 0.1) - 0.5);
return smoothstep(d * w1, d * (w1 + feather), looped);
}
`
Insert cell
mkTriangle(20000)
Insert cell
mkTriangle = (i = 0) => {
let triangle = [],
{ cells, positions4 } = obj;

cells[i % cells.length].map((j) => {
triangle = triangle.concat(positions4[j]);
});
triangle = triangle.concat([0, 0, 0, 1]);

return { triangle };
}
Insert cell
obj = {
Object.assign(bunny, {
positions4: bunny.positions.map((position) => position.concat(0))
});

return bunny;
}
Insert cell
Insert cell
drawBunny = regl({
frag: `
precision mediump float;
varying vec3 vnormal;
void main () {
gl_FragColor = vec4(vnormal * 0.75 + 0.25, 1.0);
}`,
vert: `
precision mediump float;
uniform mat4 projection, view;
attribute vec3 position, normal;
varying vec3 vnormal;
void main () {
vnormal = normal;
gl_Position = projection * view * vec4(position, 1.0);
}`,
attributes: {
position: bunny.positions,
normal: attrNormal
},
elements: bunny.cells
})
Insert cell
attrNormal = normals(bunny.cells, bunny.positions)
Insert cell
bunny = (await import("https://cdn.skypack.dev/bunny@1.0.1")).default
Insert cell
normals = (await import("https://cdn.skypack.dev/angle-normals")).default
Insert cell
regl = (await import("https://cdn.skypack.dev/regl@2")).default({
canvas,
pixelRatio: 2.0,
extensions: ["oes_standard_derivatives"]
})
Insert cell
reglCamera = (await import("https://cdn.skypack.dev/regl-camera@2.1.1")).default
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