Public
Edited
Oct 29, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
grainResult = grainApp
.clear()
.uniform("noiseAmount", grainParam.noiseAmount)
.uniform("jitterAmount", grainParam.jitterAmount)
.uniform("noiseSeed", grainParam.noiseSeed)
.draw().canvas
Insert cell
grainApp = gl2helper({
fragmentShader: grainShader,
textures: {
tex: testImg
}
})
Insert cell
Insert cell
Insert cell
Insert cell
noiseGrainResult = noiseGrainApp
.clear()
.uniform("grainAmount", noiseGrainParam.grainAmount)
.uniform("jitterAmount", noiseGrainParam.jitterAmount)
.uniform("noiseSeed", noiseGrainParam.noiseSeed)
.uniform("grainScale", 2 ** noiseGrainParam.grainScale)
.uniform("jitterScale", 2 ** noiseGrainParam.jitterScale)
.draw().canvas
Insert cell
noiseGrainApp = gl2helper({
fragmentShader: noiseGrainShader,
textures: {
tex: testImg
}
})
Insert cell
viewof noiseGrainShader = shaderShow(
`#version 300 es
precision highp float;
uniform float noiseSeed;
uniform float grainAmount;
uniform float grainScale;
uniform float jitterAmount;
uniform float jitterScale;
uniform sampler2D tex;
out vec4 fragColor;


vec3 hash( vec3 p ) // replace this by something better
{
p = vec3( dot(p,vec3(127.1,311.7, 74.7)),
dot(p,vec3(269.5,183.3,246.1)),
dot(p,vec3(113.5,271.9,124.6)));

return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}

float noise( in vec3 p )
{
vec3 i = floor( p );
vec3 f = fract( p );
vec3 u = f*f*(3.0-2.0*f);
return mix( mix( mix( dot( hash( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ),
dot( hash( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),
mix( dot( hash( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ),
dot( hash( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),
mix( mix( dot( hash( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ),
dot( hash( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),
mix( dot( hash( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ),
dot( hash( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z );
}

void main() {
vec2 iResolution = vec2(textureSize(tex, 0));
vec3 n = grainAmount * (0.3 - vec3 (noise (grainScale * vec3(gl_FragCoord.xy, noiseSeed*1000.+1331.)),
noise (grainScale * vec3(gl_FragCoord.xy, noiseSeed*1139.+2135.)),
noise (grainScale * vec3(gl_FragCoord.xy, noiseSeed*1313.+7713.))));
float ang = 6.2832 * noise(jitterScale * vec3(gl_FragCoord.xy, noiseSeed*1831.+3762.));
float r = noise(jitterScale * vec3(gl_FragCoord.xy, noiseSeed*1385.+5137.));
vec2 uv = (gl_FragCoord.xy + jitterAmount * vec2(r*cos(ang),r*sin(ang))) / iResolution;
vec3 texColor = texture(tex,uv).xyz;
fragColor = vec4(texColor+n, 1.);
}

`,
{ label: "noiseGrainShader" }
)
Insert cell
Insert cell
Insert cell
toonResult = {
const canvas = toonApp.canvas;
canvas.onmousemove = canvas.onmousedown = (e) => {
if (e.buttons) mutable toonMouse = [e.offsetX, e.offsetY];
};
return canvas;
}
Insert cell
Insert cell
toonApp
.clear()
.uniform("mouse_x_offset", toonMouse[0] / 800)
.uniform("edge_thres", toonParam.edgeMin)
.uniform("edge_thres2", toonParam.edgeMax)
.draw()
Insert cell
toonApp = gl2helper({
fragmentShader: toonShader,
textures: {
tex0: testImg
}
})
Insert cell
Insert cell
Insert cell
Insert cell
barrelResult = {
const canvas = barrelApp.canvas;
canvas.onmousemove = canvas.onmousedown = (e) => {
if (e.buttons) mutable barrelMouse = [e.offsetX, e.offsetY];
};
return canvas;
}
Insert cell
mutable barrelMouse = [400, 300]
Insert cell
barrelApp
.clear()
.uniform("iResolution", [800, 600])
.uniform("barrelDistortion1", barrelParam.k1)
.uniform("barrelDistortion2", barrelParam.k2)
.uniform("iMouse", barrelMouse)
.uniform("zoom", 2 ** barrelParam.zoom)
.draw()
Insert cell
barrelApp = gl2helper({
fragmentShader: barrelShader,
textures: {
iChannel0: testImg
}
})
Insert cell
Insert cell
Insert cell
Insert cell
hatchingResult = hatchingApp.canvas
Insert cell
hatchingApp
.clear()
.uniform("grid_size", hatchingParam.grid_size)
.uniform("hatch_y_offset", hatchingParam.y_offset)
.draw()
Insert cell
hatchingApp = gl2helper({
fragmentShader: hatchingShader,
textures: {
tex: testImg
}
})
Insert cell
Insert cell
Insert cell
Insert cell
frostedResult = frostedApp
.clear()
.uniform("v1", frostedParam.v1)
.uniform("v2", frostedParam.v2)
.uniform("rnd_factor", frostedParam.rnd_factor)
.uniform("rnd_scale", frostedParam.rnd_scale)
.draw().canvas
Insert cell
frostedApp = gl2helper({
fragmentShader: frostedShader,
textures: {
tex: testImg
}
})
Insert cell
Insert cell
Insert cell
Insert cell
freiChenResult = freiChenApp
.clear()
.uniform("threshold1", freiChenParam.threshold1)
.uniform("threshold2", freiChenParam.threshold2)
.draw().canvas
Insert cell
freiChenApp = gl2helper({
fragmentShader: freiChenShader,
textures: {
image: testImg
}
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
gaussianBlurResult = {
const { vApp, hApp } = blurApps;
for (let i = 0; i < blurPasses; i++) {
if (i == 0) {
vApp.useFbo(0).texture("tex", vApp.textureObjects["tex"]).draw();
} else {
vApp
.useFbo(0)
.texture("tex", hApp.fboObjects[0].colorAttachments[0])
.draw();
}
if (i == blurPasses - 1) {
hApp
.useFbo(null)
.texture("tex", vApp.fboObjects[0].colorAttachments[0])
.draw();
} else {
hApp
.useFbo(0)
.texture("tex", vApp.fboObjects[0].colorAttachments[0])
.draw();
}
}
return blurApps.vApp.canvas;
}
Insert cell
blurApps = {
let vApp = gl2helper({
fragmentShader:
blurImplementation == "linear"
? verticalBlurShader
: verticalDiscreteShader,
textures: {
tex: testImg
},
fbos: [1] //
});

let hApp = gl2helper({
app: vApp.app,
fragmentShader:
blurImplementation == "linear"
? horizontalBlurShader
: horizontalDiscreteShader,
fbos: [1]
});

return { vApp, hApp };
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
illumResult = {
const { freichen, illum } = illumApps;
freichen
.uniform("threshold1", illumParam.threshold1)
.uniform("threshold2", illumParam.threshold2)
.useFbo(0)
.draw();
let lightVec = [...illumParam.lightDir, illumParam.lightHeight];
let norm = Math.hypot(...lightVec);
lightVec = lightVec.map((x) => x / norm);
illum
.useFbo(null)
.uniform("lightVec", lightVec)
.uniform("ambientCoef", illumParam.ambientCoef)
.uniform("diffuseCoef", illumParam.diffuseCoef)
.uniform("specularCoef", illumParam.specularCoef)
.uniform("specularShininess", illumParam.specularShininess)
.uniform("bumpFactor", illumParam.bumpFactor)
.draw();
yield illum.canvas;
}
Insert cell
illumApps = {
const freichen = gl2helper({
fragmentShader: freiChenShader,
fbos: [1],
textures: {
image: testImg
}
});

const illum = gl2helper({
app: freichen.app,
fragmentShader: illumShader,
textures: {
tex: testImg
}
});
illum.texture("bumpmap", freichen.fboObjects[0].colorAttachments[0]);
return { freichen, illum };
}
Insert cell
Insert cell
Insert cell
collage([
grainResult,
noiseGrainResult,
barrelResult,
hatchingResult,
frostedResult,
toonResult,
freiChenResult,
gaussianBlurResult,
illumResult
])
Insert cell
function collage(images, options = {}) {
const { width = 800, height = 600 } = options;
const canvas = DOM.canvas(width, height);
const ctx = canvas.getContext("2d");
ctx.shadowColor = "black";
ctx.shadowBlur = 20;
const delta = width / images.length;
let x = 0;
for (let img of images) {
ctx.drawImage(img, x, 0, width, height, x, 0, width, height);
x += delta;
}
return canvas;
}
Insert cell
Insert cell
testImg = FileAttachment("test.jpeg").image()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { toc } from "@harrystevens/toc@126"
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