x
137
1
/*
2
transition of 3 CAs: Wolfram > Conway > Lenia
3
1st stage: Wolfram's elementary cellular automata, rule 30
4
2nd stage: Conway's Game of Life
5
3rd stage: Lenia (multi-kernel version)
6
based on example - https://smoothstep.io/anim/26d46785c1f6
7
https://chakazul.github.io/lenia.html
8
*/
9
10
const float R = 10.; // space resolution = kernel radius
11
const float T = 10.; // time resolution = number of divisions per unit time
12
const float dt = 1./T; // time step
13
const float ageRatio = 0.4;
14
15
// choose a species by uncommenting block (add/remove star at top)
16
17
/*/
18
// species: glider
19
const vec3 B = vec3( 3., 1., 1. ); // kernel ring number
20
const mat3 b = mat3( 0.66, 1., 1., 1., 0., 0., 0., 0., 0. ); // kernel ring heights
21
const vec3 m = vec3( 0.3, 0.23, 0.19 ); // growth center
22
const vec3 s = vec3( 0.03, 0.038, 0.027 ); // growth width
23
const vec3 h = vec3( 0.666, 0.666, 0.666 ); // growth strength
24
/**/
25
26
/**/
27
// species: ghost
28
const vec3 B = vec3( 2., 3., 1. ); // kernel ring number
29
const mat3 b = mat3( 0.25, 1., 1., 1., 0.75, 0., 0., 0.75, 0. ); // kernel ring heights
30
const vec3 m = vec3( 0.16, 0.22, 0.28 ); // growth center
31
const vec3 s = vec3( 0.025, 0.042, 0.025 ); // growth width
32
const vec3 h = vec3( 0.666, 0.666, 0.666 ); // growth strength
33
/**/
34
35
int getCell(in ivec2 p) {
36
// Get the value of the cell in the previous frame at position p. 0 or 1.
37
return (texelFetch(iPrevFrame, p, 0 ).x > 0.1 ) ? 1 : 0;
38
}
39
40
float getCellAge(in ivec2 p) {
41
// Get the y value of the cell, used to simulate the age of the cell, for coloring.
42
return texelFetch(iPrevFrame, p, 0 ).y;
43
}
44
45
int getCellWrapped(in ivec2 p) {
46
// getCell but with texture wrapping.
47
ivec2 r = ivec2(textureSize(iPrevFrame, 0));
48
p = (p + r) % r;
49
return (texelFetch(iPrevFrame, p, 0 ).x > 0.1 ) ? 1 : 0;
50
}
51
52
vec3 bell(vec3 x, vec3 m, vec3 s) {
53
return exp(-(x-m)*(x-m)/s/s/2.); // bell-shaped curve
54
}
55
56
vec3 getWeight(in float r) {
57
if (r > 1.) return vec3(0.);
58
vec3 Br = B * r;
59
ivec3 iBr = ivec3(Br);
60
vec3 height =
61
b[0] * vec3(equal(iBr, ivec3(0))) +
62
b[1] * vec3(equal(iBr, ivec3(1))) +
63
b[2] * vec3(equal(iBr, ivec3(2)));
64
return height * bell(mod(Br, 1.), vec3(0.5), vec3(0.15));
65
}
66
67
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
68
vec2 uv = fragCoord / iResolution;
69
ivec2 px = ivec2(fragCoord);
70
float newCell = 0.;
71
float age = 0.;
72
73
ivec3 c = ivec3(1, -1, 0);
74
75
if (px.y > int(iResolution.y) / 2) {
76
// Lenia (multi-kernel)
77
vec3 sum = vec3(0.), total = vec3(0.);
78
for (int x=-int(R); x<=int(R); x++)
79
for (int y=-int(R); y<=int(R); y++)
80
{
81
float r = sqrt(float(x*x + y*y)) / R;
82
vec3 weight = getWeight(r); //bell(r, 0.5, 0.15);
83
float cell = getCellAge(px + ivec2(x,y)) / ageRatio;
84
sum += cell * weight;
85
total += weight;
86
}
87
vec3 avg = sum / total;
88
vec3 growth = bell(avg, m, s) * 2. - 1.;
89
float weightedGrowth = dot(h, growth);
90
newCell = clamp(getCellAge(px) / ageRatio + dt * weightedGrowth, 0., 1.);
91
age = newCell * ageRatio;
92
93
} else if (px.y > int(iResolution.y) / 4) {
94
// Conway's Game of Life.
95
int numNeighbours = (
96
getCell(px+c.yy) + getCell(px+c.zy) + getCell(px+c.xy)
97
+ getCell(px+c.yz) + getCell(px+c.xz)
98
+ getCell(px+c.yx) + getCell(px+c.zx) + getCell(px+c.xx)
99
);
100
int thisCell = getCell(px);
101
newCell = (
102
((numNeighbours == 2) && (thisCell == 1)) || (numNeighbours == 3)
103
) ? 1.0 : 0.0;
104
age = getCellAge(px);
105
// Decay the age from 1.
106
age = newCell + 0.97 * (1. - newCell) * age;
107
} else if (px.y != 0) {
108
// Copy the row below.
109
newCell = float(getCell(px + c.zy));
110
age = newCell * 1.0 / (0.8 + 0.01 * fragCoord.y);
111
} else {
112
// Rule 30 automaton.
113
int left = getCellWrapped(px + c.yz);
114
int mid = getCellWrapped(px + c.zz);
115
int right = getCellWrapped(px + c.xz);
116
int val = 4 * left + 2 * mid + right;
117
118
if (1 <= val && val <= 4) {
119
newCell = 1.;
120
}
121
}
122
123
// Initialise.
124
if (iFrame < 2) {
125
newCell = 0.;
126
//newCell = fract(103.2 * sin(5102.2 * uv.x + 983.87 * uv.y + 23.1) * (7. * uv.x + 923.2 * uv.y));
127
age = 0.;
128
if (px.y == 0 && px.x == int(iResolution.x) / 2) {
129
newCell = 1.;
130
}
131
}
132
133
134
float blue = 0.5 - 0.5 * cos(2.0 * newCell + 3.0 * age);
135
fragColor = vec4(vec3(newCell, age, blue), 1.);
136
137
}
1264×1264px
0