Cellular automata in GLSL+PyQT. Various rulesets can be found by checking out individual commits. http://hut.pm/cellmade_gallery.html
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

182 lines
4.3 KiB

#version 120
float rand(vec2 co){
return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
}
uniform sampler2D tex;
uniform int t;
uniform int texwidth, texheight;
uniform bool b1, b2, hsvactive, diffH, diffV;
uniform float p1, p2;
varying vec4 pos;
mat3x3 r, g, b;
float rhood[8], ghood[8], bhood[8];
float neighbors[3];
int rneighbors, gneighbors, bneighbors;
vec4 color;
float alive_threshold = (p1 + 1) / 2;
int colors2int(float r, float g, float b) {
return int(round(r * 255) + round(g * 65535) + round(b * 16777215));
}
vec4 int2colors(int value) {
vec4 result;
result.a = 1;
result.b = floor(value / 65536) / 255.0;
result.g = mod(floor(value / 256), 256) / 255.0;
result.r = mod(value, 256) / 255.0;
return result;
}
const vec4 shifts = vec4(1, 256., 256. * 256., 0);
int unpack(vec4 rgb) {
return int(dot(round(rgb * 255), shifts));
}
vec4 pack(int value) {
return fract(value / shifts / 256.0);
}
void diffusion(float power) {
float tempColor = color.r;
vec4 other;
float sum = 0;
float thisFactor;
float diagFactor = 1/sqrt(2);
float averagingCoefficient = 1.0 / (4.0 + diagFactor * 4.0);
int unpacked_color = unpack(color);
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++) {
if (i != 1 || j != 1) {
other = vec4(r[i][j], g[i][j], b[i][j], 1);
thisFactor = ((i!=1&&j!=1) ? diagFactor : 1);
sum += (unpack(other) - unpacked_color) * thisFactor * averagingCoefficient;
}
}
}
color = pack(int(unpacked_color + sum/3));
}
void calcNeighbors() {
float dx = (1.0 / texwidth);
float dy = (1.0 / texheight);
vec4 tempColor;
neighbors[0] = 0;
neighbors[1] = 0;
neighbors[2] = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
tempColor = texture2D(tex, vec2(pos.x+dx*i, pos.y+dy*j));
r[i+1][j+1] = tempColor.r;
g[i+1][j+1] = tempColor.g;
b[i+1][j+1] = tempColor.b;
}
}
}
bool alive(float color) {
return color > alive_threshold;
}
void calcNeighborsGoL() {
float dx = (1.0 / texwidth);
float dy = (1.0 / texheight);
vec4 tempColor;
neighbors[0] = 0;
neighbors[1] = 0;
neighbors[2] = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
tempColor = texture2D(tex, vec2(pos.x+dx*(i-1), pos.y+dy*(j-1)));
r[i][j] = tempColor.r;
g[i][j] = tempColor.g;
b[i][j] = tempColor.b;
if (i != 1 || j != 1) {
if (alive(tempColor.r)) neighbors[0] += 1;
if (alive(tempColor.g)) neighbors[1] += 1;
if (alive(tempColor.b)) neighbors[2] += 1;
}
}
}
}
vec2 complex_mult(vec2 ab, vec2 cd) {
return vec2(
ab.x * cd.x - ab.y * cd.y,
ab.y * cd.x + ab.x * cd.y);
}
float mandelbrot(float x, float y) {
vec2 z = vec2(0, 0);
vec2 c = vec2(x, y);
const int maxi = 25;
for (int i = 1; i <= maxi; i++) {
z = complex_mult(z, z) + c;
if (length(z) > 2) {
if (b1)
return 1.0 - float(i) / maxi;
else
return float(i) / maxi;
}
}
return 0.0;
}
void gol(float stp, int i) {
if (alive(color[i])) {
if (neighbors[i] < 2 || neighbors[i] > 3) {
color[i] -= stp;
}
else {
color[i] += stp;
}
}
else {
if (neighbors[i] == 3) {
color[i] += stp;
}
}
}
void copyrule(float stp, int i) {
if (mod(neighbors[i], 2) == 0) {
color[i] += stp;
}
else {
color[i] -= stp;
}
}
void main() {
if (t == 1) {
color = vec4(0, 0, 0, 1);
/*color.r = mandelbrot(pos.x*3-2.2, pos.y*3-1.5);*/
//color = pack(int(pow(2, 24) * mandelbrot((pos.x+0.8)*0.3, pos.y*0.3-0.5)));
color = pack(int(pow(2, 24) * mandelbrot(pos.x*3-2.2, pos.y*3-1.5)));
}
else {
if (b2) {
calcNeighbors();
color = texture2D(tex, vec2(pos.x, pos.y));
diffusion(1);
}
else {
calcNeighborsGoL();
color = texture2D(tex, vec2(pos.x, pos.y));
int indx = int(mod(t, 3));
copyrule(1, indx);
}
}
gl_FragColor = color;
}