git-hash-art 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deploy-www.yml +47 -0
- package/ALGORITHM.md +212 -14
- package/CHANGELOG.md +18 -0
- package/dist/browser.js +758 -23
- package/dist/browser.js.map +1 -1
- package/dist/main.js +758 -23
- package/dist/main.js.map +1 -1
- package/dist/module.js +758 -23
- package/dist/module.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/archetypes.ts +51 -4
- package/src/lib/canvas/colors.ts +70 -0
- package/src/lib/canvas/draw.ts +115 -6
- package/src/lib/canvas/shapes/affinity.ts +3 -3
- package/src/lib/render.ts +423 -17
- package/src/lib/utils.ts +109 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Deploy git-hash-art-www
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
bump-www:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- name: Extract version from release tag
|
|
12
|
+
id: version
|
|
13
|
+
run: |
|
|
14
|
+
VERSION="${GITHUB_REF_NAME#v}"
|
|
15
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
16
|
+
|
|
17
|
+
- name: Clone git-hash-art-www
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
repository: gfargo/git-hash-art-www
|
|
21
|
+
token: ${{ secrets.WWW_DEPLOY_PAT }}
|
|
22
|
+
path: www
|
|
23
|
+
|
|
24
|
+
- name: Setup Node.js
|
|
25
|
+
uses: actions/setup-node@v4
|
|
26
|
+
with:
|
|
27
|
+
node-version: 20
|
|
28
|
+
|
|
29
|
+
- name: Install pnpm
|
|
30
|
+
uses: pnpm/action-setup@v4
|
|
31
|
+
with:
|
|
32
|
+
run_install: false
|
|
33
|
+
|
|
34
|
+
- name: Update git-hash-art dependency
|
|
35
|
+
working-directory: www
|
|
36
|
+
run: |
|
|
37
|
+
pnpm install git-hash-art@${{ steps.version.outputs.version }}
|
|
38
|
+
|
|
39
|
+
- name: Commit and push
|
|
40
|
+
working-directory: www
|
|
41
|
+
run: |
|
|
42
|
+
git config user.name "github-actions[bot]"
|
|
43
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
44
|
+
git add package.json pnpm-lock.yaml
|
|
45
|
+
git diff --cached --quiet && echo "No changes to commit" && exit 0
|
|
46
|
+
git commit -m "chore: bump git-hash-art to v${{ steps.version.outputs.version }}"
|
|
47
|
+
git push
|
package/ALGORITHM.md
CHANGED
|
@@ -9,10 +9,11 @@ Hash String
|
|
|
9
9
|
│
|
|
10
10
|
├─► Seed (mulberry32 PRNG)
|
|
11
11
|
│
|
|
12
|
-
├─► Archetype Selection (1 of 17 visual personalities)
|
|
12
|
+
├─► Archetype Selection (1 of 17 visual personalities, ~15% chance of blending two)
|
|
13
13
|
│
|
|
14
14
|
├─► Color Scheme (palette mode + temperature mode + contrast enforcement)
|
|
15
15
|
│ └─► Color Hierarchy (dominant 60% / secondary 25% / accent 15%)
|
|
16
|
+
│ └─► Per-Layer Palette Evolution (±20° hue drift across layers)
|
|
16
17
|
│
|
|
17
18
|
├─► Shape Palette (affinity-curated primary / supporting / accent shapes)
|
|
18
19
|
│
|
|
@@ -30,15 +31,19 @@ Hash String
|
|
|
30
31
|
1a. Background Luminance → contrast enforcement threshold
|
|
31
32
|
1b. Layered Background (archetype-coherent shapes + concentric rings)
|
|
32
33
|
1c. Background Pattern Layer (dot grid / diagonal lines / tessellation)
|
|
33
|
-
2. Composition Mode Selection
|
|
34
|
+
2. Composition Mode Selection (6 modes including golden-spiral)
|
|
34
35
|
2b. Symmetry Mode Selection (none / bilateral / quad)
|
|
35
36
|
3. Focal Points (rule-of-thirds biased) + Void Zones
|
|
36
|
-
|
|
37
|
+
3b. Void Zone Decoration (halos, scattered dots, concentric rings)
|
|
38
|
+
4. Flow Field Initialization (simplex noise FBM)
|
|
39
|
+
4a. Noise Size Modulation (terrain-like size variation from noise field)
|
|
37
40
|
4b. Hero Shape (palette-aware, affinity-styled)
|
|
38
41
|
5. Shape Layers (× N layers, archetype-tuned)
|
|
39
42
|
│ ├─ Blend Mode (per-layer compositing)
|
|
40
43
|
│ ├─ Render Style (affinity-aware per shape)
|
|
41
44
|
│ ├─ Depth-of-Field (stroke thinning + contrast reduction on far layers)
|
|
45
|
+
│ ├─ Color Palette Evolution (per-layer hue drift via evolveHierarchy)
|
|
46
|
+
│ ├─ Focal Depth Boost (nesting/constellation chance ↑ near focal points)
|
|
42
47
|
│ ├─ Position (composition mode + focal bias + density check)
|
|
43
48
|
│ ├─ Shape Selection (palette-driven with size constraints)
|
|
44
49
|
│ ├─ Hero Avoidance Field (nearby shapes orient toward hero)
|
|
@@ -46,21 +51,29 @@ Hash String
|
|
|
46
51
|
│ ├─ Atmospheric Depth (desaturation on later layers)
|
|
47
52
|
│ ├─ Temperature Contrast (foreground opposite to background)
|
|
48
53
|
│ ├─ Styling (transparency, glow, gradients, HSL jitter)
|
|
54
|
+
│ ├─ Shadow & Highlight (drop shadow + specular highlight per shape)
|
|
49
55
|
│ ├─ Organic Edges (~15% watercolor bleed)
|
|
56
|
+
│ ├─ Edge Erosion (watercolor + hand-drawn styles get irregular boundary bites)
|
|
50
57
|
│ ├─ 5a. Tangent Placement (~25% nudge toward nearest shape edge)
|
|
51
58
|
│ ├─ 5b. Shape Mirroring (~40% of basic shapes get reflected copies)
|
|
52
59
|
│ ├─ 5c. Size Echo (~20% of large shapes spawn trailing copies)
|
|
53
60
|
│ ├─ 5d. Recursive Nesting (~15% of large shapes, palette-aware)
|
|
54
61
|
│ └─ 5e. Shape Constellations (~12% of large shapes, pre-composed groups)
|
|
62
|
+
5f. Layered Masking / Cutout Portals (~18% of images)
|
|
55
63
|
6. Flow-Line Pass (variable color, pressure, branching)
|
|
56
|
-
6b.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
6b. Motion/Energy Lines (directional bursts from shapes)
|
|
65
|
+
6c. Layered Transparency / Glazing (~20% of shapes get multi-pass redraws)
|
|
66
|
+
7. Symmetry Mirroring (bilateral-x, bilateral-y, or quad)
|
|
67
|
+
8. Noise Texture Overlay
|
|
68
|
+
9. Vignette (radial edge darkening)
|
|
69
|
+
10. Organic Connecting Curves
|
|
70
|
+
11. Post-Processing
|
|
61
71
|
├─ Color Grading (unified tone overlay)
|
|
62
72
|
├─ Chromatic Aberration (neon/cosmic/ethereal only)
|
|
63
|
-
|
|
73
|
+
├─ Bloom (neon/cosmic only)
|
|
74
|
+
└─ Gradient Map (~35% chance, luminance-mapped two-color overlay)
|
|
75
|
+
11b. Generative Borders (archetype-driven decorative frames)
|
|
76
|
+
12. Signature Mark (deterministic geometric chop mark)
|
|
64
77
|
```
|
|
65
78
|
|
|
66
79
|
## 1. Deterministic RNG
|
|
@@ -74,6 +87,16 @@ rng() → float in [0, 1)
|
|
|
74
87
|
|
|
75
88
|
The old approach extracted 2-char hex pairs from the hash (only ~20 unique values in a 40-char hash). Mulberry32 produces a full 32-bit uniform stream from any seed, eliminating correlation artifacts.
|
|
76
89
|
|
|
90
|
+
### Simplex Noise Field
|
|
91
|
+
|
|
92
|
+
In addition to the scalar RNG, the pipeline creates a **2D simplex noise** function seeded from the hash (with a separate salt so it's independent of the main RNG stream). This produces smooth, organic spatial variation across the canvas.
|
|
93
|
+
|
|
94
|
+
The raw simplex noise is layered into **Fractal Brownian Motion (FBM)** with 3 octaves (lacunarity 2.0, gain 0.5), which adds multi-scale detail — large sweeping gradients overlaid with finer turbulence.
|
|
95
|
+
|
|
96
|
+
The noise field drives two systems:
|
|
97
|
+
- **Flow field angles:** `flowAngle(x, y)` samples the FBM at each position, producing organic, non-repeating directional fields. This replaces the old sinusoidal field which produced visible periodic patterns.
|
|
98
|
+
- **Size modulation:** `noiseSizeModulation(x, y)` samples the raw simplex noise to create terrain-like size variation (0.7×–1.3×). Shapes in "high noise" regions are larger; shapes in "low noise" regions are smaller. This creates natural density clusters without explicit clustering logic.
|
|
99
|
+
|
|
77
100
|
## 2. Archetype System
|
|
78
101
|
|
|
79
102
|
Before any rendering begins, the hash deterministically selects one of 17 **visual archetypes** — fundamentally different rendering personalities that override key parameters. This is the primary mechanism for visual diversity: two hashes that select different archetypes will look like they came from entirely different generators.
|
|
@@ -126,6 +149,18 @@ Each archetype controls:
|
|
|
126
149
|
|
|
127
150
|
**celestial** — Boosts sacred geometry and cosmic shapes (crescent, geodesicDome, mandala, flowerOfLife, spirograph, fibonacciSpiral). Neon palette on dark background with heavy glow (2.5×) and deep layering (5 layers) creates a starfield-like composition with luminous geometric forms.
|
|
128
151
|
|
|
152
|
+
### Archetype Blending
|
|
153
|
+
|
|
154
|
+
~15% of hashes trigger **archetype blending**, where two archetypes are interpolated to create a hybrid personality. `blendArchetypes(primary, secondary, ratio)` works as follows:
|
|
155
|
+
|
|
156
|
+
- **Blend ratio:** 25–50% (the secondary archetype never dominates)
|
|
157
|
+
- **Numeric parameters** (`gridSize`, `layers`, `baseOpacity`, `minShapeSize`, etc.) are linearly interpolated between the two archetypes
|
|
158
|
+
- **Style arrays** (`preferredStyles`) are merged — the primary's styles come first, then any unique styles from the secondary
|
|
159
|
+
- **Categorical parameters** (`backgroundStyle`, `paletteMode`) use the primary's value when the blend ratio is below 50%, otherwise the secondary's
|
|
160
|
+
- **Boolean parameters** (`heroShape`) use the primary's value
|
|
161
|
+
|
|
162
|
+
This creates subtle hybrid personalities — e.g., a blend of `neon-glow` and `organic-flow` might produce glowing shapes with heavy flow lines and earth-toned neon outlines.
|
|
163
|
+
|
|
129
164
|
## 3. Color Scheme
|
|
130
165
|
|
|
131
166
|
Color generation uses the `color-scheme` library seeded from the hash, then applies archetype-specific palette modes.
|
|
@@ -141,6 +176,17 @@ Color generation uses the `color-scheme` library seeded from the hash, then appl
|
|
|
141
176
|
| pastel-light | Soft pastels on light backgrounds |
|
|
142
177
|
| earth | Muted warm naturals |
|
|
143
178
|
| high-contrast | Black + white + one accent color |
|
|
179
|
+
| split-complementary | Base hue + two colors flanking the complement (±30°) |
|
|
180
|
+
| analogous-accent | Tight cluster of 3 analogous hues + 1 distant accent |
|
|
181
|
+
| limited-palette | Only 3 colors — risograph-print feel |
|
|
182
|
+
|
|
183
|
+
### New Harmony Mode Details
|
|
184
|
+
|
|
185
|
+
**split-complementary** — Instead of a single complement (180° opposite), this mode uses two colors at ±30° from the complement. This creates strong contrast like complementary schemes but with more nuance and less visual tension. The base hue gets a tint variant for 5 total colors.
|
|
186
|
+
|
|
187
|
+
**analogous-accent** — Three hues within a tight 30–70° arc (15–35° step between each) create a harmonious, low-contrast base. A single accent color at 150–210° away provides a pop of contrast. This produces compositions that feel cohesive with one surprising element.
|
|
188
|
+
|
|
189
|
+
**limited-palette** — Only 3 colors total, spaced roughly 120° apart with slight randomization. Mimics the look of risograph or screen-printed art where ink colors are limited. The constraint forces the hierarchy system to work harder, producing bold, graphic compositions.
|
|
144
190
|
|
|
145
191
|
### Color Hierarchy
|
|
146
192
|
|
|
@@ -173,6 +219,16 @@ The scheme detects whether the background leans warm or cool, then shifts foregr
|
|
|
173
219
|
|
|
174
220
|
Every shape color is checked against the background luminance. If the contrast ratio is too low, the color is lightened or darkened to ensure visibility.
|
|
175
221
|
|
|
222
|
+
### Color Palette Evolution
|
|
223
|
+
|
|
224
|
+
Colors aren't static across layers — they evolve. `evolveHierarchy(hierarchy, layerFraction)` applies a progressive hue rotation to the entire color hierarchy as rendering moves through layers:
|
|
225
|
+
|
|
226
|
+
- **Total drift:** ±20° across the full layer stack (direction determined by the dominant color's initial hue)
|
|
227
|
+
- **Per-layer rotation:** `layerFraction × 20°` applied via `hueRotate(color, degrees)`, which converts to HSL, shifts the hue, and converts back
|
|
228
|
+
- **Effect:** Early layers lean toward the original palette; later layers drift toward adjacent hues on the color wheel
|
|
229
|
+
|
|
230
|
+
This creates a subtle color journey across the depth of the image — warm reds in the background might shift toward orange-gold in the foreground, giving the composition a sense of temporal progression without breaking palette coherence.
|
|
231
|
+
|
|
176
232
|
## 4. Shape Affinity System
|
|
177
233
|
|
|
178
234
|
Not all shapes look equally good at all sizes or in all combinations. The affinity system replaces naive random shape selection with intentional curation.
|
|
@@ -281,6 +337,13 @@ Each image uses one of 5 composition strategies for shape placement:
|
|
|
281
337
|
| grid-subdivision | Canvas divided into 3–5 cells; shapes placed within random cells |
|
|
282
338
|
| clustered | 3–5 cluster centers; shapes scatter around the nearest cluster |
|
|
283
339
|
| flow-field | Uniform random placement (rotation driven by flow field) |
|
|
340
|
+
| golden-spiral | Shapes placed along a logarithmic golden-angle spiral from center outward |
|
|
341
|
+
|
|
342
|
+
### Golden Spiral Detail
|
|
343
|
+
|
|
344
|
+
The `golden-spiral` mode uses the **golden angle** (~137.5°) to space shapes around the center. Each shape's angular position is `index × goldenAngle` with slight random jitter (±0.3 radians). The radial distance uses a square-root distribution (`√(t) × maxRadius`) which ensures even area coverage — shapes don't bunch up at the center or leave gaps at the edges.
|
|
345
|
+
|
|
346
|
+
This produces the same phyllotactic pattern seen in sunflower seed heads and pinecone spirals. Combined with the size power curve, it creates compositions where large shapes anchor the center and smaller shapes spiral outward in a naturally pleasing arrangement.
|
|
284
347
|
|
|
285
348
|
### Symmetry
|
|
286
349
|
|
|
@@ -297,6 +360,16 @@ Symmetry is applied by drawing the canvas image onto itself with `scale(-1, 1)`
|
|
|
297
360
|
|
|
298
361
|
1–2 **void zones** are placed randomly. Shapes landing inside a void zone have an 85% chance of being skipped, creating breathing room in the composition.
|
|
299
362
|
|
|
363
|
+
### Void Zone Decoration
|
|
364
|
+
|
|
365
|
+
Void zones aren't left completely empty — they receive subtle decorative elements that acknowledge the negative space:
|
|
366
|
+
|
|
367
|
+
- **Halo ring:** A thin circular stroke at the void zone's boundary using the accent color at 6–12% opacity
|
|
368
|
+
- **Scattered dots (~50% chance):** 5–12 tiny dots (1–3px) scattered randomly inside the void zone at 4–10% opacity, creating a dust-like texture
|
|
369
|
+
- **Inner concentric ring (~30% chance):** A smaller ring at 40–70% of the void zone radius at 3–8% opacity
|
|
370
|
+
|
|
371
|
+
These decorations are subtle enough to preserve the breathing room while preventing void zones from feeling like rendering errors.
|
|
372
|
+
|
|
300
373
|
## 8. Hero Shape
|
|
301
374
|
|
|
302
375
|
When the archetype enables `heroShape` and the RNG roll passes (60% chance), a dominant focal element is drawn at the first focal point:
|
|
@@ -321,6 +394,16 @@ The core of the image: `layers` passes (archetype-controlled, typically 2–5),
|
|
|
321
394
|
- **Atmospheric desaturation:** Later layers are progressively desaturated (up to 30%) to simulate depth
|
|
322
395
|
- **Depth-of-field:** Later layers get thinner strokes (down to 40% of base width) and reduced contrast (up to 20% opacity reduction), simulating camera focus falloff
|
|
323
396
|
|
|
397
|
+
### Focal Depth Boost
|
|
398
|
+
|
|
399
|
+
Shapes near focal points receive enhanced detail via `focalDetailBoost()`:
|
|
400
|
+
|
|
401
|
+
- **Nesting chance:** Boosted from the base 15% up to 15–30% for shapes within 25% of canvas size from a focal point
|
|
402
|
+
- **Constellation chance:** Boosted from the base 12% up to 12–22% near focal points
|
|
403
|
+
- **Boost strength:** Proportional to proximity — shapes right at the focal point get the full boost, shapes at the edge of the influence radius get minimal boost
|
|
404
|
+
|
|
405
|
+
This creates a natural depth-of-detail effect where the areas your eye is drawn to (focal points) contain the most intricate shape compositions.
|
|
406
|
+
|
|
324
407
|
### Per-Shape Pipeline
|
|
325
408
|
|
|
326
409
|
For each shape in a layer:
|
|
@@ -336,7 +419,27 @@ For each shape in a layer:
|
|
|
336
419
|
9. **Contrast enforcement:** Fill and stroke colors checked against background luminance
|
|
337
420
|
10. **Styling:** Affinity-aware render style, optional glow (sacred shapes 45% base chance × archetype multiplier), optional radial gradient fill (30% chance)
|
|
338
421
|
11. **Organic edges:** 15% of `fill-and-stroke` shapes are promoted to `watercolor` style
|
|
339
|
-
12. **
|
|
422
|
+
12. **Shadow & highlight:** Each shape receives a directional drop shadow and specular highlight based on the consistent light angle (see below)
|
|
423
|
+
|
|
424
|
+
### Shadow & Highlight System
|
|
425
|
+
|
|
426
|
+
Every shape receives lighting effects based on a single consistent light direction (random angle, fixed for the entire image):
|
|
427
|
+
|
|
428
|
+
**Drop Shadow:**
|
|
429
|
+
- Offset: 3.5% of shape size along the opposite of the light direction
|
|
430
|
+
- Blur radius: 6% of shape size
|
|
431
|
+
- Color: `rgba(0,0,0,0.12)` — subtle enough to add depth without muddying colors
|
|
432
|
+
- Applied via Canvas `shadowOffset` + `shadowBlur` properties before the shape is drawn
|
|
433
|
+
- Shapes with glow effects use the glow instead (no double-shadow)
|
|
434
|
+
|
|
435
|
+
**Specular Highlight:**
|
|
436
|
+
- Position: 15% of shape size along the light direction from center
|
|
437
|
+
- Radius: 35% of shape size
|
|
438
|
+
- Gradient: white at 18% opacity → 5% → 0% (radial falloff)
|
|
439
|
+
- Composited via `soft-light` to interact naturally with the shape's fill color
|
|
440
|
+
- Only applied to shapes larger than 15px (tiny shapes don't benefit)
|
|
441
|
+
|
|
442
|
+
The combination creates a subtle 3D effect where shapes appear to float above the background, with consistent lighting across the entire composition.
|
|
340
443
|
|
|
341
444
|
### 5a. Tangent Placement
|
|
342
445
|
|
|
@@ -377,9 +480,23 @@ The mirror copy is drawn at 70% opacity and 95% size (decreasing for radial-4),
|
|
|
377
480
|
|
|
378
481
|
Each member shape uses hierarchy colors with HSL jitter and affinity-aware render styles. Members that fall outside the canvas bounds are skipped.
|
|
379
482
|
|
|
483
|
+
### 5f. Layered Masking / Cutout Portals
|
|
484
|
+
|
|
485
|
+
~18% of images receive 1–3 **portal cutouts** — shape-sized windows that paint over the foreground layers with a background wash, creating a "peek through" depth effect.
|
|
486
|
+
|
|
487
|
+
The process for each portal:
|
|
488
|
+
|
|
489
|
+
1. **Position:** Biased toward an existing placed shape (with slight random offset), so portals appear in visually active areas rather than empty space
|
|
490
|
+
2. **Shape:** Selected from the shape palette at the portal's size fraction, so the cutout shape is palette-coherent
|
|
491
|
+
3. **Clip and fill:** The shape is used as a clip region, then a radial gradient (derived from the background colors with HSL jitter) is painted over the foreground at 60–95% opacity. This "erases" the foreground shapes within the portal boundary and replaces them with a soft background wash
|
|
492
|
+
4. **Inner texture (~50%):** Tiny scattered dots inside the portal at low opacity add subtle depth to the wash
|
|
493
|
+
5. **Border ring:** A subtle stroke outline at 106% of the portal size (15–35% opacity) frames the window, drawn outside the clip so it sits on top of everything
|
|
494
|
+
|
|
495
|
+
The variable opacity (60–95%) means some portals are translucent peeks while others fully reveal the background, creating varied depth effects without punching actual transparent holes in the canvas.
|
|
496
|
+
|
|
380
497
|
## 10. Render Styles
|
|
381
498
|
|
|
382
|
-
Each shape is drawn using one of
|
|
499
|
+
Each shape is drawn using one of 15 render styles:
|
|
383
500
|
|
|
384
501
|
| Style | Description |
|
|
385
502
|
| ----- | ----------- |
|
|
@@ -397,6 +514,7 @@ Each shape is drawn using one of 14 render styles:
|
|
|
397
514
|
| wood-grain | 20% base tint + clipped parallel wavy lines at a random angle, simulating wood texture |
|
|
398
515
|
| marble-vein | 35% soft base + clipped branching vein lines that drift and fork, simulating marble stone |
|
|
399
516
|
| fabric-weave | 15% ghost base + clipped interlocking horizontal and vertical thread lines at alternating opacities |
|
|
517
|
+
| hand-drawn | Fill + 2–3 wobbly offset stroke passes simulating a hand-drawn sketch |
|
|
400
518
|
|
|
401
519
|
### Texture Fill Details
|
|
402
520
|
|
|
@@ -414,17 +532,57 @@ The 4 new texture fills (noise-grain, wood-grain, marble-vein, fabric-weave) all
|
|
|
414
532
|
|
|
415
533
|
**fabric-weave** draws horizontal threads at full spacing, then vertical threads at half-spacing offsets, creating an over-under weave pattern. The two thread directions use different opacities (55% vs 45%) and colors (stroke vs fill) for visual distinction.
|
|
416
534
|
|
|
535
|
+
### Hand-Drawn Style
|
|
536
|
+
|
|
537
|
+
The `hand-drawn` style simulates a sketchy, imprecise outline:
|
|
538
|
+
|
|
539
|
+
1. **Base fill:** Standard fill of the shape
|
|
540
|
+
2. **Wobbly strokes (2–3 passes):** Each pass redraws the shape's outline with a small random offset (1–3px) and slightly varied line width, creating the impression of a hand tracing the same line multiple times
|
|
541
|
+
3. **Opacity variation:** Each pass uses 40–70% opacity so the overlapping strokes build up naturally
|
|
542
|
+
|
|
543
|
+
This style works particularly well on organic shapes (circle, triangle, blob) where the wobble feels intentional rather than broken.
|
|
544
|
+
|
|
545
|
+
### Layered Transparency / Glazing
|
|
546
|
+
|
|
547
|
+
~20% of shapes receive **glazing** — 2–3 additional fill-only passes drawn immediately after the main shape:
|
|
548
|
+
|
|
549
|
+
- Each pass is progressively smaller (85% → 72% → 61% of the original size)
|
|
550
|
+
- Each pass is progressively more opaque (adding 5–10% opacity per pass)
|
|
551
|
+
- Only the fill is redrawn (no stroke), creating a pigment-pooling effect where the center of the shape appears richer and more saturated
|
|
552
|
+
|
|
553
|
+
This simulates the traditional oil painting technique of building up translucent layers to create depth and luminosity.
|
|
554
|
+
|
|
555
|
+
### Motion / Energy Lines
|
|
556
|
+
|
|
557
|
+
Short directional line bursts radiate from shapes to suggest movement and energy:
|
|
558
|
+
|
|
559
|
+
- **Trigger:** Always for `dense-chaotic`, `cosmic`, `neon-glow`, and `bold-graphic` archetypes; ~25% random chance for others
|
|
560
|
+
- **Count:** 3–6 lines per shape
|
|
561
|
+
- **Length:** 8–20% of the shape's size
|
|
562
|
+
- **Direction:** Radiating outward from the shape center at evenly-spaced angles with ±15° jitter
|
|
563
|
+
- **Style:** Thin lines (0.5–1.5px) using the shape's stroke color at 15–35% opacity, tapering toward the ends
|
|
564
|
+
|
|
565
|
+
Motion lines are drawn after the main shape layers but before symmetry mirroring, so they participate in any bilateral/quad reflections.
|
|
566
|
+
|
|
417
567
|
### Watercolor Detail
|
|
418
568
|
|
|
419
|
-
The watercolor style simulates wet media through
|
|
569
|
+
The watercolor style simulates wet media through 5 passes:
|
|
420
570
|
1. **Base wash:** Shape drawn at 108% scale, 15% opacity — soft bleed beyond the boundary
|
|
421
571
|
2. **Offset washes:** 4–5 passes with radial displacement (random angle, up to 5% of size) — organic edge irregularity
|
|
422
572
|
3. **Edge darkening:** Shape drawn at 85–93% scale with lightened fill — simulates pigment pooling at boundaries where the inner area dries lighter
|
|
423
|
-
4. **
|
|
573
|
+
4. **Edge erosion:** 6–14 small circular bites erased along the shape boundary using `destination-out` compositing at 60–90% opacity. Bites are placed at 85–110% of the shape's edge radius with sizes 2–6% of the shape, creating the irregular, feathered edges characteristic of real watercolor on textured paper
|
|
574
|
+
5. **Delicate stroke:** Thin outline (60% of normal width) at 25% opacity
|
|
575
|
+
|
|
576
|
+
### Hand-Drawn Edge Erosion
|
|
577
|
+
|
|
578
|
+
The `hand-drawn` style also receives organic edge erosion after its wobbly stroke passes:
|
|
579
|
+
- 4–10 small circular bites erased along the boundary at 90–110% of the edge radius
|
|
580
|
+
- Bite sizes are slightly smaller than watercolor (1.5–4.5% of shape size) for a rougher, torn-paper feel
|
|
581
|
+
- Combined with the wobbly multi-pass strokes, this creates shapes that look like they were drawn on rough paper with a slightly dry pen
|
|
424
582
|
|
|
425
583
|
## 11. Flow Lines
|
|
426
584
|
|
|
427
|
-
Flow lines follow a
|
|
585
|
+
Flow lines follow a **simplex noise** vector field defined by `flowAngle(x, y)`. The field is generated from a seeded 2D simplex noise function layered with 3-octave Fractal Brownian Motion (FBM) for organic, non-repeating patterns. The archetype's `flowLineMultiplier` controls count (0× = none, up to 4× = heavy).
|
|
428
586
|
|
|
429
587
|
Each flow line:
|
|
430
588
|
- Starts at a random position
|
|
@@ -461,3 +619,43 @@ Only for `neon-glow`, `cosmic`, and `ethereal` archetypes. The canvas is drawn o
|
|
|
461
619
|
### Bloom
|
|
462
620
|
|
|
463
621
|
Only for `neon-glow` and `cosmic` archetypes. The canvas is redrawn with `shadowBlur` at 30px (scaled) and white shadow color, composited via `screen` at 8% opacity. This creates a soft glow around bright areas.
|
|
622
|
+
|
|
623
|
+
### Gradient Map
|
|
624
|
+
|
|
625
|
+
~35% of images receive a **gradient map** post-processing pass — a technique borrowed from Photoshop that maps the image's luminance through a two-color gradient:
|
|
626
|
+
|
|
627
|
+
- **Dark color:** The hierarchy's dominant color
|
|
628
|
+
- **Light color:** The hierarchy's accent color
|
|
629
|
+
- **Application:** A linear gradient (top = dark, bottom = light) is painted over the entire canvas using `color` compositing mode at 6–12% opacity
|
|
630
|
+
- **Effect:** Shadows take on the dominant color's hue while highlights shift toward the accent, creating a cohesive tonal relationship across the entire image
|
|
631
|
+
|
|
632
|
+
The `color` blend mode only affects hue and saturation (not luminance), so the gradient map tints the image without changing its brightness structure. At 6–12% opacity, the effect is subtle — it unifies the color temperature without overpowering the original palette.
|
|
633
|
+
|
|
634
|
+
### Generative Borders
|
|
635
|
+
|
|
636
|
+
After all post-processing, archetype-appropriate decorative borders are drawn to frame the composition. The border style is keyed on the archetype name, with a separate RNG (seeded with salt 314) for deterministic border patterns:
|
|
637
|
+
|
|
638
|
+
| Archetype Group | Border Style |
|
|
639
|
+
| --------------- | ------------ |
|
|
640
|
+
| geometric, op-art, shattered-glass | Clean ruled double lines with corner ornaments (small squares with diagonal crosses) |
|
|
641
|
+
| botanical, organic-flow, watercolor-wash | Organic vine tendrils curling inward from edges, with small leaf dots at tendril ends |
|
|
642
|
+
| celestial, cosmic, neon-glow | Subtle arcs along top/bottom edges + scattered 4-point stars in the border region |
|
|
643
|
+
| minimal, monochrome-ink, stipple-portrait | Single thin rule — understated elegance |
|
|
644
|
+
| Others | No border (intentional — not every image needs framing) |
|
|
645
|
+
|
|
646
|
+
Border elements use hierarchy colors at very low opacity (10–25%) so they frame without competing with the main composition. The border padding is 2.5% of the shorter canvas dimension.
|
|
647
|
+
|
|
648
|
+
## 13. Signature Mark
|
|
649
|
+
|
|
650
|
+
The final rendering step places a small deterministic **chop mark** (inspired by East Asian seal stamps) in the bottom-right corner of the canvas:
|
|
651
|
+
|
|
652
|
+
- **RNG isolation:** Uses a separate RNG seeded with a salt of 42, so the signature is independent of all other rendering decisions
|
|
653
|
+
- **Position:** Bottom-right corner with a small margin (3% of canvas size)
|
|
654
|
+
- **Size:** 1.5–2.5% of the shorter canvas dimension
|
|
655
|
+
- **Structure:**
|
|
656
|
+
1. Outer circle ring (stroke-only) at 12–20% opacity
|
|
657
|
+
2. 2–4 inner lines crossing the circle at unique angles derived from the hash, creating a distinctive geometric pattern
|
|
658
|
+
3. Center dot at slightly higher opacity
|
|
659
|
+
- **Color:** Uses the accent color from the hierarchy at very low opacity so it's visible but never distracting
|
|
660
|
+
|
|
661
|
+
The signature is unique per hash (different inner line patterns) but always recognizable as a chop mark, giving each generated image a subtle artist's stamp.
|
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,30 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [0.10.1](https://github.com/gfargo/git-hash-art/compare/0.10.0...0.10.1)
|
|
8
|
+
|
|
9
|
+
- feat: shadow/highlight system, generative borders, gradient map, edge erosion [`#19`](https://github.com/gfargo/git-hash-art/pull/19)
|
|
10
|
+
- feat: simplex noise flow fields, color harmony modes, golden spiral composition, layered masking [`#18`](https://github.com/gfargo/git-hash-art/pull/18)
|
|
11
|
+
- fix: portal cutouts use clip-and-fill instead of destination-out [`aecdd14`](https://github.com/gfargo/git-hash-art/commit/aecdd14c0d5ddf52d0394c714d2815679263b961)
|
|
12
|
+
- add GitHub Actions workflow for deployment [`4a6ac42`](https://github.com/gfargo/git-hash-art/commit/4a6ac426d1678f5ff83cbe4c4ddc9ce2a2a0c260)
|
|
13
|
+
|
|
14
|
+
#### [0.10.0](https://github.com/gfargo/git-hash-art/compare/0.9.0...0.10.0)
|
|
15
|
+
|
|
16
|
+
> 19 March 2026
|
|
17
|
+
|
|
18
|
+
- feat: color palette evolution, edge treatment, glazing, motion lines, archetype blending, focal depth, signature mark [`#17`](https://github.com/gfargo/git-hash-art/pull/17)
|
|
19
|
+
- feat: color palette evolution, edge treatment, negative space, glazing, motion lines, archetype blending, focal depth, signature mark [`b496771`](https://github.com/gfargo/git-hash-art/commit/b49677108ae170fef9c1108d40d7db6995efb48c)
|
|
20
|
+
- chore: release v0.10.0 [`38f1d2e`](https://github.com/gfargo/git-hash-art/commit/38f1d2e3b60c921b651be9319e685f77df1ad93b)
|
|
21
|
+
|
|
7
22
|
#### [0.9.0](https://github.com/gfargo/git-hash-art/compare/0.8.0...0.9.0)
|
|
8
23
|
|
|
24
|
+
> 19 March 2026
|
|
25
|
+
|
|
9
26
|
- feat: new archetypes, depth-of-field, texture fills, constellations, background patterns [`#16`](https://github.com/gfargo/git-hash-art/pull/16)
|
|
10
27
|
- docs: update ALGORITHM.md with visual quality improvements [`#15`](https://github.com/gfargo/git-hash-art/pull/15)
|
|
11
28
|
- feat: add 4 archetypes, depth-of-field, texture fills, constellations, background patterns [`7f9b0fc`](https://github.com/gfargo/git-hash-art/commit/7f9b0fcbc4a17272dd6a62371e037fb0555c830b)
|
|
12
29
|
- add version comparison script [`9301176`](https://github.com/gfargo/git-hash-art/commit/9301176b4f1fe0af85d5d7f85e58db9be10ec382)
|
|
30
|
+
- chore: release v0.9.0 [`32311c2`](https://github.com/gfargo/git-hash-art/commit/32311c2fda12dbcb388e77d9e2faba380d3b0c29)
|
|
13
31
|
|
|
14
32
|
#### [0.8.0](https://github.com/gfargo/git-hash-art/compare/0.7.0...0.8.0)
|
|
15
33
|
|