added 3d game of life

This commit is contained in:
Sven Vogel 2023-06-16 23:08:05 +02:00
parent 0225da6050
commit 42c04603b0
5 changed files with 173 additions and 0 deletions

View File

@ -0,0 +1,9 @@
# John Conway's Game of Life: 3D
Multipass GPU implementation of the famous Game of Life. But in 3D!
The rules of this 3D version are as follows:
A cell lives if:
- it is alive and either 5 or 6 neighboors are alive
- or it has 4 alive neighboors
otherwise the cell dies.
![overview.png](https://git.teridax.de/teridax/Shadertoy-Shaders/raw/branch/main/John-Conway's-Game-of-Life:2D/overview.png)

Binary file not shown.

View File

@ -0,0 +1,41 @@
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
ivec3 xyz = to3d(ivec2(fragCoord));
if (xyz.x >= int(Size) || xyz.y >= int(Size) || xyz.z >= int(Size))
{
fragColor = vec4(0);
return;
}
if (iFrame == 0)
{
fragColor = vec4( step(0.99, sin(fragCoord.x * 4.0 * fragCoord.y)) );
return;
}
if (iFrame % 32 != 0)
{
fragColor = texture(iChannel0, fragCoord/iResolution.xy);
return;
}
int c = 0;
for (int x = -1; x < 2; x++)
for (int y = -1; y < 2; y++)
for (int z = -1; z < 2; z++)
{
if (x == 0 && y == 0 && z == 0)
continue;
c += int(texelFetch(iChannel0, to2d(to3d(ivec2(fragCoord)) + ivec3(x,y,z)), 0).r);
}
int m = int(texelFetch(iChannel0, to2d(to3d(ivec2(fragCoord))), 0).r);
vec3 live = vec3(0);
if (m == 1 && (c == 5 || c == 6) || c == 4)
live = vec3(1);
fragColor = vec4(live, 1);
}

View File

@ -0,0 +1,19 @@
const float Size = 16.;
vec2 pixelize(in vec2 xy)
{
return floor(xy*Size)/Size;
}
ivec3 to3d(in ivec2 xy)
{
return ivec3(xy.x, xy.y/int(Size), xy.y % int(Size)) + ivec3(4);
}
ivec2 to2d(in ivec3 xyz)
{
ivec3 stw = xyz - ivec3(4);
return ivec2(stw.x, stw.y*int(Size) + stw.z);
}

View File

@ -0,0 +1,104 @@
#define AA 2.
vec2 boxIntersection(in vec3 ro, in vec3 rd, in vec3 size)
{
vec3 m = 1.0/rd;
vec3 n = m*ro;
vec3 k = abs(m)*size;
vec3 t1 = -n - k;
vec3 t2 = -n + k;
float tN = max( max( t1.x, t1.y ), t1.z );
float tF = min( min( t2.x, t2.y ), t2.z );
if(tN > tF)
return vec2(-1.0);
return vec2( tN, tF );
}
mat2 rot(in float t)
{
float c = cos(t);
float s = sin(t);
return mat2(c, -s, s, c);
}
vec3 wavelengthToRGB(float wavelength) {
vec3 rgb;
if (wavelength < 380.0) {
rgb = vec3(0.0, 0.0, 0.0);
} else if (wavelength < 440.0) {
rgb = vec3(0.0, 0.0, 0.4 + 0.6 * (wavelength - 380.0) / (440.0 - 380.0));
} else if (wavelength < 490.0) {
rgb = vec3(0.0, (wavelength - 440.0) / (490.0 - 440.0), 1.0);
} else if (wavelength < 510.0) {
rgb = vec3((wavelength - 490.0) / (510.0 - 490.0), 1.0, 1.0 - (wavelength - 490.0) / (510.0 - 490.0));
} else if (wavelength < 580.0) {
rgb = vec3(1.0, 1.0 - (wavelength - 510.0) / (580.0 - 510.0), 0.0);
} else if (wavelength < 645.0) {
rgb = vec3(1.0 - (wavelength - 580.0) / (645.0 - 580.0), 0.0, (wavelength - 580.0) / (645.0 - 580.0));
} else if (wavelength < 781.0) {
rgb = vec3(0.0, 0.0, 0.4 + 0.6 * (780.0 - wavelength) / (780.0 - 645.0));
} else {
rgb = vec3(0.0, 0.0, 0.0);
}
return rgb;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec3 sum = vec3(0);
for (float x = 0.; x < AA; x++)
for (float y = 0.; y < AA; y++)
{
vec2 uv = (fragCoord+vec2(x,y)/AA-.5*iResolution.xy)/iResolution.y;
vec3 ro = vec3(0,0,-5);
vec3 rd = normalize(vec3(uv, 1));
mat2 r0 = rot( iTime *.1 );
mat2 r1 = rot(0.4);
ro.yz *= r1;
rd.yz *= r1;
ro.xz *= r0;
rd.xz *= r0;
vec2 dist = boxIntersection(ro, rd, vec3(1)) + vec2(1e-4,-1e-4);
vec3 col = vec3(0);
vec3 p = ro + rd * dist.x;
float S = 128.;
float d = (dist.y-dist.x)/S;
for (float i = 0.; dist.x > 0. && i < S; i++)
{
vec3 k = floor(p*Size)/Size;
ivec3 v = ivec3((k*.5+.5)*Size);
if (texelFetch(iChannel0, to2d(v), 0).r > 0.5)
{
float c = 0.;
for (int x = -1; x < 2; x++)
for (int y = -1; y < 2; y++)
for (int z = -1; z < 2; z++)
c += texelFetch(iChannel0, to2d(v + ivec3(x,y,z)), 0).r;
float b = 1.;
for (int y = 1; y < 9; y++)
b += texelFetch(iChannel0, to2d(v + ivec3(0,y,0)), 0).r;
col = wavelengthToRGB( c / 27.0 * (780.-440.) + 440. ) / b;
break;
}
p += rd * d;
}
sum += col;
}
sum /= AA * AA;
fragColor = vec4(sum, 1.0);
}