mirror of
https://github.com/seigler/generative
synced 2025-07-26 06:46:10 +00:00
Add sketch 5, "glow lines"
Fix an issue with the displacement fragment shader
This commit is contained in:
parent
1d2c6aa16a
commit
d8538524a8
8 changed files with 313 additions and 32 deletions
240
app/5/index.js
Normal file
240
app/5/index.js
Normal file
|
@ -0,0 +1,240 @@
|
|||
new p5(sketch => {
|
||||
sketch.disableFriendlyErrors = false;
|
||||
// reused dimensions and a seed
|
||||
let seed, width, height, noiseResolution, overdraw, blurQuality;
|
||||
const layers = {}; // offscreen layers
|
||||
const shaders = {}; // shaders
|
||||
const lib = {}; // libraries
|
||||
const assets = {}; // fonts, images, sound files
|
||||
|
||||
sketch.preload = () => {
|
||||
shaders.whiteNoise = sketch.loadShader(
|
||||
'../shaders/base.vert',
|
||||
'../shaders/white-noise.frag'
|
||||
);
|
||||
shaders.blurH = sketch.loadShader(
|
||||
'../shaders/base.vert',
|
||||
'../shaders/blur-two-pass.frag'
|
||||
);
|
||||
shaders.blurV = sketch.loadShader(
|
||||
'../shaders/base.vert',
|
||||
'../shaders/blur-two-pass.frag'
|
||||
);
|
||||
}
|
||||
|
||||
sketch.setup = () => {
|
||||
filenamePrefix = 'seigler-p5-5-glow_path-';
|
||||
overdraw = 0.1;
|
||||
width = Math.floor(sketch.windowWidth * (1 + overdraw));
|
||||
height = Math.floor(sketch.windowHeight * (1 + overdraw));
|
||||
noiseResolution = [0.2, 0.1, 0.05, 2];
|
||||
blurQuality = 2;
|
||||
|
||||
window.onhashchange = () => {
|
||||
seed = window.location.hash.substr(1);
|
||||
generate();
|
||||
};
|
||||
|
||||
seed = window.location.hash.substr(1);
|
||||
sketch.colorMode(sketch.HSL, 1);
|
||||
|
||||
sketch.createCanvas(sketch.windowWidth, sketch.windowHeight);
|
||||
|
||||
layers.buffer = sketch.createGraphics(width, height);
|
||||
layers.buffer.colorMode(sketch.HSL, 1);
|
||||
|
||||
layers.cells = sketch.createGraphics(width, height);
|
||||
layers.cells.colorMode(sketch.HSL, 1);
|
||||
layers.cells.noStroke();
|
||||
|
||||
layers.noise = sketch.createGraphics(width, height, sketch.WEBGL);
|
||||
|
||||
layers.blur1 = sketch.createGraphics(width, height, sketch.WEBGL);
|
||||
layers.blur2 = sketch.createGraphics(width, height, sketch.WEBGL);
|
||||
|
||||
generate();
|
||||
};
|
||||
|
||||
sketch.draw = () => {
|
||||
};
|
||||
|
||||
sketch.keyReleased = () => {
|
||||
if (sketch.key == ' ') {
|
||||
seed = null;
|
||||
generate();
|
||||
} else if (sketch.key == 's') {
|
||||
sketch.saveCanvas(filenamePrefix + seed + '.jpg', 'jpg');
|
||||
}
|
||||
};
|
||||
|
||||
sketch.doubleClicked = () => {
|
||||
seed = null;
|
||||
generate();
|
||||
};
|
||||
|
||||
let resizeTimer;
|
||||
sketch.windowResized = () => {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
function generate() {
|
||||
if (seed) {
|
||||
sketch.randomSeed(seed);
|
||||
} else {
|
||||
let seed = Math.floor(sketch.random(1000000000000));
|
||||
window.location.hash = seed;
|
||||
sketch.randomSeed(seed);
|
||||
}
|
||||
|
||||
sketch.noiseSeed(sketch.random(0, 1000000000));
|
||||
sketch.blendMode(sketch.BLEND);
|
||||
|
||||
let unit = Math.min(width, height) / Math.round(sketch.random(4, 6));
|
||||
|
||||
// doodle
|
||||
let glowPath = sketch.random(0, 1000000000);
|
||||
let glowHue = sketch.random();
|
||||
let pathCountMult = Math.round(unit / 15);
|
||||
|
||||
layers.buffer.background(sketch.random(), 0.1, 0.25);
|
||||
layers.buffer.blendMode(sketch.BLEND);
|
||||
layers.buffer.strokeCap(sketch.ROUND);
|
||||
layers.buffer.noFill();
|
||||
const doodle = (layer, seed = sketch.random(0, 1000000000)) => {
|
||||
sketch.randomSeed(seed);
|
||||
let doodlePoint = {
|
||||
x: sketch.random(width * overdraw * 0.4, width * (1 - overdraw * 0.4)),
|
||||
y: sketch.random(height * overdraw * 0.4, height * (1 - overdraw * 0.4))
|
||||
};
|
||||
if (sketch.random() > 0.5) {
|
||||
doodlePoint.y = sketch.random() > 0.5 ? height * overdraw * 0.4 : height * (1 - overdraw * 0.4);
|
||||
} else {
|
||||
doodlePoint.x = sketch.random() > 0.5 ? width * overdraw * 0.4 : width * (1 - overdraw * 0.4);
|
||||
}
|
||||
let doodleMaxTurn = sketch.random(Math.PI / 8, Math.PI);
|
||||
let doodleHeading = Math.atan2(height/2 - doodlePoint.y, width/2 - doodlePoint.x);
|
||||
doodleHeading += sketch.random(-0.25, 0.25) * doodleMaxTurn;
|
||||
layer.beginShape();
|
||||
layer.vertex(doodlePoint.x, doodlePoint.y);
|
||||
let steps = 0;
|
||||
do {
|
||||
const { x: ax, y: ay } = doodlePoint;
|
||||
const bx = doodlePoint.x + unit/2 * Math.cos(doodleHeading),
|
||||
by = doodlePoint.y + unit/2 * Math.sin(doodleHeading);
|
||||
doodleHeading += sketch.random(-1, 1) * doodleMaxTurn;
|
||||
layer.quadraticVertex(ax, ay, sketch.lerp(ax, bx, 0.5), sketch.lerp(ay, by, 0.5));
|
||||
doodlePoint = { x: bx, y: by };
|
||||
steps++;
|
||||
} while(
|
||||
steps < 80 ||
|
||||
doodlePoint.x > -unit/2 && doodlePoint.x < width + unit/2 &&
|
||||
doodlePoint.y > -unit/2 && doodlePoint.y < height + unit/2
|
||||
);
|
||||
layer.endShape();
|
||||
}
|
||||
|
||||
// dark fat doodles
|
||||
layers.buffer.blendMode(sketch.MULTIPLY);
|
||||
for (let i = 0; i < pathCountMult; i++) {
|
||||
layers.buffer.strokeWeight(sketch.random(0.5, 2) * pathCountMult);
|
||||
layers.buffer.stroke(sketch.random(0.2, 0.45));
|
||||
doodle(layers.buffer);
|
||||
}
|
||||
// glow path
|
||||
layers.buffer.blendMode(sketch.BLEND);
|
||||
layers.buffer.stroke(glowHue, 1, 0.5);
|
||||
layers.buffer.strokeWeight(25);
|
||||
doodle(layers.buffer, glowPath);
|
||||
|
||||
// blur the paths
|
||||
let blurSize = pathCountMult / 6;
|
||||
for (let pass = 0; pass < blurQuality; pass++) {
|
||||
let radius = (blurQuality - pass) * blurSize / blurQuality;
|
||||
layers.blur1.shader(shaders.blurH);
|
||||
shaders.blurH.setUniform('tex0', pass == 0 ? layers.buffer : layers.blur2);
|
||||
shaders.blurH.setUniform('texelSize', [radius/width, radius/height]);
|
||||
shaders.blurH.setUniform('direction', [1.0, 0.0]);
|
||||
layers.blur1.rect(0, 0, width, height);
|
||||
layers.blur2.shader(shaders.blurV);
|
||||
shaders.blurV.setUniform('tex0', layers.blur1);
|
||||
shaders.blurV.setUniform('texelSize', [radius/width, radius/height]);
|
||||
shaders.blurV.setUniform('direction', [0.0, 1.0]);
|
||||
layers.blur2.rect(0, 0, width, height);
|
||||
}
|
||||
layers.buffer.image(layers.blur2, 0, 0, width, height);
|
||||
|
||||
layers.buffer.strokeWeight(1);
|
||||
for (let i = 0; i < pathCountMult * 30; i++) {
|
||||
layers.buffer.stroke(sketch.random(0.05));
|
||||
doodle(layers.buffer);
|
||||
}
|
||||
layers.buffer.stroke(glowHue, 1, 0.9);
|
||||
layers.buffer.strokeWeight(5);
|
||||
doodle(layers.buffer, glowPath);
|
||||
sketch.image(layers.buffer, Math.round(-width * overdraw/2), Math.round(-height * overdraw/2));
|
||||
|
||||
// square pixels per circle, helps with gridding
|
||||
sketch.blendMode(sketch.BLEND);
|
||||
let rows = Math.max(1, Math.round(height / unit / Math.sin(Math.PI / 3))) + 1;
|
||||
let cols = Math.max(1, Math.round(width / unit)) + 1;
|
||||
let noiseOffset = unit * 200 + Math.SQRT2;
|
||||
let gridPoints = [];
|
||||
for (let index = 0; index < rows * cols; index++) {
|
||||
let col = index % cols;
|
||||
let row = Math.floor(index / cols);
|
||||
let noise = noiseResolution.map(
|
||||
(resolution, noiseIndex) => {
|
||||
// let gridScale = resolution / Math.min(rows, cols);
|
||||
return sketch.noise(
|
||||
noiseOffset * (noiseIndex + 1) + (row - rows / 2) * resolution,
|
||||
noiseOffset * (noiseIndex + 1) + (col - cols / 2) * resolution
|
||||
)
|
||||
}
|
||||
);
|
||||
gridPoints.push({
|
||||
row,
|
||||
col,
|
||||
noise,
|
||||
});
|
||||
}
|
||||
gridPoints.forEach(point => {
|
||||
let { col, row, noise: [n0, n1, n2, n3] } = point;
|
||||
point.x = (
|
||||
width / (cols - 1) * col
|
||||
+ (row % 2 - 0.5) * unit / 2
|
||||
+ 1 * n0 * unit * Math.cos(sketch.TWO_PI * flattenPerlin(n1))
|
||||
);
|
||||
point.y = (
|
||||
height / (rows - 1) * row
|
||||
+ 1 * n0 * unit * Math.sin(sketch.TWO_PI * flattenPerlin(n1))
|
||||
);
|
||||
});
|
||||
|
||||
layers.noise.shader(shaders.whiteNoise);
|
||||
shaders.whiteNoise.setUniform('u_resolution', [width, height]);
|
||||
shaders.whiteNoise.setUniform('u_alpha', 0.05);
|
||||
layers.noise.rect(0, 0, width, height);
|
||||
sketch.blendMode(sketch.OVERLAY);
|
||||
sketch.image(layers.noise, 0, 0);
|
||||
}
|
||||
|
||||
// give Perlin noise 0-1 a uniform distribution
|
||||
function flattenPerlin(x) {
|
||||
return 23.8615 * Math.pow(x, 5)
|
||||
- 59.6041 * Math.pow(x, 4)
|
||||
+ 47.2472 * Math.pow(x, 3)
|
||||
- 11.3053 * Math.pow(x, 2)
|
||||
+ 0.806219 * x - 0.00259101;
|
||||
}
|
||||
|
||||
// returns abs angle from a to b to c
|
||||
function three_point_angle(A,B,C) {
|
||||
var AB = Math.sqrt(Math.pow(B.x-A.x,2)+ Math.pow(B.y-A.y,2));
|
||||
var BC = Math.sqrt(Math.pow(B.x-C.x,2)+ Math.pow(B.y-C.y,2));
|
||||
var AC = Math.sqrt(Math.pow(C.x-A.x,2)+ Math.pow(C.y-A.y,2));
|
||||
return Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB));
|
||||
}
|
||||
});
|
7
app/5/index.static.hbs
Normal file
7
app/5/index.static.hbs
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Glow Path
|
||||
created: 2019-11-12
|
||||
index: 5
|
||||
_options:
|
||||
layout: app/layouts/sketch.hbs
|
||||
---
|
BIN
app/assets/5/example.jpg
Normal file
BIN
app/assets/5/example.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 319 KiB |
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Generative Art - seigler.github.io</title>
|
||||
<link rel="stylesheet" href="DIGEST(app.css)">
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>P5.js generative art</h1>
|
||||
<figure>
|
||||
<a class="sketch" href="4/"><img src="4/example.jpg" alt="colored pinstripes distorted by a field of smoothed lenses of varying strength"></a>
|
||||
<figcaption>2019-11-10 - lenses</figcaption>
|
||||
</figure>
|
||||
<figure>
|
||||
<a class="sketch" href="3/"><img src="3/example.jpg" alt="purple jelly stripes covered with swirling swarms of peanut butter colored lines"></a>
|
||||
<figcaption>2019-11-09 - peanut butter and jelly</figcaption>
|
||||
</figure>
|
||||
<figure>
|
||||
<a class="sketch" href="2/"><img src="2/example.jpg" alt="multicolored gradients revealing and concealing jungle leaves"></a>
|
||||
<figcaption>2019-11-07 - gradient jungle</figcaption>
|
||||
</figure>
|
||||
<figure>
|
||||
<a class="sketch" href="1/"><img src="1/example.jpg" alt="multicolored gradients revealing and concealing bars and circles"></a>
|
||||
<figcaption>2019-11-05 - gradient burst</figcaption>
|
||||
</figure>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -13,12 +13,14 @@ uniform float u_intensity;
|
|||
void main() {
|
||||
|
||||
vec2 uv = vTexCoord;
|
||||
// the texture is loaded upside down and backwards by default so lets flip it
|
||||
uv = 1.0 - uv;
|
||||
|
||||
// get the displacement map as a vec4 using texture2D
|
||||
vec4 mapTex = texture2D(u_map, uv);
|
||||
|
||||
// the texture is loaded upside down and backwards by default so lets flip it
|
||||
// uv = 1.0 - uv;
|
||||
uv[1] = 1.0 - uv[1];
|
||||
|
||||
// lets get the average color of the rgb values
|
||||
float avg = dot(mapTex.rgb, vec3(0.33333));
|
||||
|
||||
|
|
49
app/index.static.hbs
Normal file
49
app/index.static.hbs
Normal file
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
_options:
|
||||
partials:
|
||||
- app/partials/preview.hbs
|
||||
---
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Generative Art - seigler.github.io</title>
|
||||
<link rel="stylesheet" href="DIGEST(app.css)">
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>P5.js generative art</h1>
|
||||
{{> preview
|
||||
index="5"
|
||||
date="2019-11-12"
|
||||
name="glow path"
|
||||
alt="layers of meandering dark curves with one glowing, colored curve"
|
||||
}}
|
||||
{{> preview
|
||||
index="4"
|
||||
date="2019-11-10"
|
||||
name="lenses"
|
||||
alt="colored pinstripes distorted by a field of smoothed lenses of varying strength"
|
||||
}}
|
||||
{{> preview
|
||||
index="3"
|
||||
date="2019-11-09"
|
||||
name="peanut butter and jelly"
|
||||
alt="purple jelly stripes covered with swirling swarms of peanut butter colored lines"
|
||||
}}
|
||||
{{> preview
|
||||
index="2"
|
||||
date="2019-11-07"
|
||||
name="gradient jungle"
|
||||
alt="multicolored gradients revealing and concealing jungle leaves"
|
||||
}}
|
||||
{{> preview
|
||||
index="1"
|
||||
date="2019-11-05"
|
||||
name="gradient burst"
|
||||
alt="multicolored gradients revealing and concealing bars and circles"
|
||||
}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
4
app/partials/preview.hbs
Normal file
4
app/partials/preview.hbs
Normal file
|
@ -0,0 +1,4 @@
|
|||
<figure>
|
||||
<a class="sketch" href="{{index}}/"><img src="{{index}}/example.jpg" alt="{{alt}}"></a>
|
||||
<figcaption>{{date}} - {{name}}</figcaption>
|
||||
</figure>
|
|
@ -54,3 +54,12 @@ footer {
|
|||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 1em 0;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 1em;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue