[shaders] added
This commit is contained in:
parent
9f971fe9f7
commit
7928c2b1f6
5
shaders/README.md
Normal file
5
shaders/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# shaders
|
||||
|
||||
A collection of GLSL shaders, built for [Shader Editor](https://github.com/markusfisch/ShaderEditor) on Android.
|
||||
|
||||
- `star-wars.glsl`: [Star Wars](https://quuxplusone.github.io/blog/2020/06/29/star-wars-ca/) cellular automata implementation, including tools to draw patterns.
|
251
shaders/star-wars.glsl
Normal file
251
shaders/star-wars.glsl
Normal file
@ -0,0 +1,251 @@
|
||||
// STAR WARS cellular automata
|
||||
// ===========================
|
||||
//
|
||||
// an implementation of star wars (https://quuxplusone.github.io/blog/2020/06/29/star-wars-ca/)
|
||||
//
|
||||
// based on code for http://www.vexorian.com/2015/05/cloudy-conway.html?m=1
|
||||
//
|
||||
// built for use in https://github.com/markusfisch/ShaderEditor
|
||||
//
|
||||
// controls: tap top left to switch tool, top right to switch brush
|
||||
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
#define TOOLZONE > 0.8
|
||||
|
||||
// S_ entries mark data addresses
|
||||
// x, chan, width, dec
|
||||
// see rstat for more info
|
||||
|
||||
#define S_TOOL 0., 0, 1., 10.
|
||||
#define T_FILL 0.
|
||||
#define T_DEL 1.
|
||||
#define T_ROTOR 2.
|
||||
#define T_LATTICE 3.
|
||||
#define T_WALLH 4.
|
||||
|
||||
#define S_BRUSH 0., 2, 1., 10.
|
||||
#define BR_FINE 0.
|
||||
#define BR_MED 1.
|
||||
#define BR_LARGE 2.
|
||||
#define BR_HUGE 3.
|
||||
|
||||
// ui fade out timer
|
||||
#define S_UI 0., 1, 10., 100.
|
||||
|
||||
|
||||
uniform vec2 resolution;
|
||||
uniform int pointerCount;
|
||||
uniform vec3 pointers[10];
|
||||
uniform sampler2D backbuffer;
|
||||
uniform int second;
|
||||
uniform int frame;
|
||||
|
||||
float oneIfZero(float value) {
|
||||
return step(abs(value), 0.05);
|
||||
}
|
||||
float oiz(float value) {
|
||||
// one if zero alias
|
||||
return step(abs(value), 0.05);
|
||||
}
|
||||
|
||||
vec4 get4(float x, float y) {
|
||||
return texture2D(backbuffer,
|
||||
mod(gl_FragCoord.xy + vec2(x, y), resolution) / resolution);
|
||||
}
|
||||
|
||||
vec4 get4abs(float x, float y) {
|
||||
return texture2D(backbuffer, vec2(x, y) / resolution);
|
||||
}
|
||||
|
||||
vec4 get4c(vec4 c) {
|
||||
return texture2D(backbuffer, c.xy / resolution);
|
||||
}
|
||||
|
||||
vec4 evaluate(float sum, float prev) {
|
||||
vec4 cell = get4(0.0, 0.0);
|
||||
float wasAlive = 1. - step(prev, 0.9);
|
||||
float has2 = oneIfZero(sum - 2.0);
|
||||
float has3 = oneIfZero(sum - 3.0);
|
||||
float has4 = oneIfZero(sum - 4.0);
|
||||
float has5 = oneIfZero(sum - 5.0);
|
||||
// In this rule, a state-0 cell will become state 1
|
||||
// iff it has two state-1 neighbours.
|
||||
// A state-1 cell does not change if it has 3, 4 or 5
|
||||
// state-1 neighbours, otherwise it will enter state 2
|
||||
// next tick and then state 3 before dying.
|
||||
|
||||
// use the a channel for representing: states are 1.0, 0.2, 0.1, 0.0.
|
||||
|
||||
// 1 -> 1, 1 -> 2
|
||||
float stay = wasAlive * max(min(has3 + has4 + has5, 1.), 0.2);
|
||||
// 0 -> 1
|
||||
float become = oneIfZero(prev) * has2;
|
||||
// 2 -> 3, 3 -> 0
|
||||
float decay = (1. - wasAlive) * max(prev - .1, 0.);
|
||||
|
||||
float state = max(stay, max(become, decay));
|
||||
return vec4(
|
||||
cell.g * 0.7,
|
||||
oneIfZero(state - 1.) * 0.03 + cell.g * 0.95 + oneIfZero(state - .1) * 0.1,
|
||||
oneIfZero(state - 0.2) * 0.2 + cell.g,
|
||||
state
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
float get(float x, float y) {
|
||||
return 1. - step(get4(x, y).a, 0.9);
|
||||
}
|
||||
|
||||
// store state in (x, 0)'s rgb channels.
|
||||
// different decimals for different state
|
||||
// avoid passing data like .99 because floating point imprecision
|
||||
|
||||
// pass in dec 10, 100, 1000, and so on
|
||||
// chan 0, 1, 2 for rgb
|
||||
// width 1., 10., 100. to control how many decimals for one datum
|
||||
|
||||
float rstat(float x, int chan, float width, float dec) {
|
||||
return floor(mod(get4abs(0.5 + x, 0.5)[chan] * dec, 10. * width));
|
||||
}
|
||||
|
||||
// return delta to modified state, set to v
|
||||
vec4 wstat(float x, int chan, float width, float dec, float v) {
|
||||
vec4 ret;
|
||||
ret[chan] = (v - rstat(x, chan, width, dec)) / dec;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// return a color for a state
|
||||
// prev is the a in the vec4 which we keep same
|
||||
vec4 colstat(float s, float prev) {
|
||||
return
|
||||
oiz(s - 0.) * vec4(0.5, 0., 0., prev) +
|
||||
oiz(s - 1.) * vec4(0.8, 0.5, 0., prev) +
|
||||
oiz(s - 2.) * vec4(0.8, 0.8, 0., prev) +
|
||||
oiz(s - 3.) * vec4(0., 0.5, 0., prev) +
|
||||
oiz(s - 4.) * vec4(0.0, 0., 0.5, prev) +
|
||||
oiz(s - 5.) * vec4(0.1, 0., 0.3, prev) +
|
||||
oiz(s - 6.) * vec4(0.5, 0., 0.5, prev) +
|
||||
oiz(s - 7.) * vec4(0.5, 0.5, 0.5, prev) +
|
||||
oiz(s - 8.) * vec4(0., 0.5, 0.5, prev) +
|
||||
oiz(s - 9.) * vec4(0., 0., 0., prev);
|
||||
}
|
||||
|
||||
// get brush size
|
||||
float getbrush() {
|
||||
float id = rstat(S_BRUSH);
|
||||
float side = max(resolution.x, resolution.y);
|
||||
return side * (
|
||||
oiz(id - 0.) * .02 +
|
||||
oiz(id - 1.) * .07 +
|
||||
oiz(id - 2.) * .15 +
|
||||
oiz(id - 3.) * .4
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
float sum =
|
||||
get(-1.0, -1.0) +
|
||||
get(-1.0, 0.0) +
|
||||
get(-1.0, 1.0) +
|
||||
get(0.0, -1.0) +
|
||||
get(0.0, 1.0) +
|
||||
get(1.0, -1.0) +
|
||||
get(1.0, 0.0) +
|
||||
get(1.0, 1.0);
|
||||
|
||||
vec2 center = resolution /2.;
|
||||
|
||||
float prev = get4(0., 0.).a;
|
||||
|
||||
bool switchTool = false;
|
||||
vec2 puv = vec2(1.);
|
||||
if (pointerCount > 0) {
|
||||
puv = pointers[0].xy / resolution;
|
||||
switchTool = puv.y TOOLZONE;
|
||||
}
|
||||
|
||||
float tapSize = getbrush();
|
||||
float tool = rstat(S_TOOL);
|
||||
for (int n = 0; n < pointerCount; ++n) {
|
||||
if (!switchTool && abs(pointers[n].y - gl_FragCoord.y) < tapSize && tool == T_WALLH) {
|
||||
prev = 0.;
|
||||
sum = 0.;
|
||||
float c = mod(gl_FragCoord.y - .5, 6.);
|
||||
if (
|
||||
c < 4.
|
||||
&& (mod(c, 3.) == 0. || mod(c + gl_FragCoord.x - .5, 2.) == 0.)
|
||||
)
|
||||
sum = 2.;
|
||||
break;
|
||||
} else if (!switchTool && distance(pointers[n].xy, gl_FragCoord.xy) < tapSize) {
|
||||
prev = 0.;
|
||||
sum = 0.;
|
||||
if (tool == T_ROTOR) {
|
||||
vec2 modc = mod(gl_FragCoord.xy, 9.) - 0.5;
|
||||
if (abs(modc.y - 2.) + abs(modc.x - 2.) <= 1.)
|
||||
sum = 2.0;
|
||||
} else if (tool == T_LATTICE) {
|
||||
// lattice: 01101101
|
||||
if (mod(mod(gl_FragCoord.x + gl_FragCoord.y, 8.), 3.) >= 1.)
|
||||
sum = 2.;
|
||||
} else if (tool == T_DEL)
|
||||
sum = 0.;
|
||||
else if (tool == T_FILL)
|
||||
sum = 2.;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame == 0)
|
||||
gl_FragColor = vec4(0.);
|
||||
else
|
||||
gl_FragColor = evaluate(sum, prev);
|
||||
|
||||
vec2 uv = gl_FragCoord.xy / resolution.xy;
|
||||
|
||||
float uiTimer = rstat(S_UI);
|
||||
if (gl_FragCoord.xy == vec2(0.5, 0.5)) {
|
||||
gl_FragColor = get4c(gl_FragCoord);
|
||||
|
||||
if (switchTool && puv.x < 0.5) {
|
||||
if (uiTimer < 94.) {
|
||||
// change tool
|
||||
float new = mod(rstat(S_TOOL) + 1., 5.);
|
||||
gl_FragColor += wstat(S_TOOL, new);
|
||||
// show ui
|
||||
gl_FragColor += wstat(S_UI, 96.);
|
||||
}
|
||||
} else if (switchTool && puv.x > 0.5) {
|
||||
if (uiTimer < 94.) {
|
||||
// change brush size
|
||||
float new = mod(rstat(S_BRUSH) + 1., 4.);
|
||||
gl_FragColor += wstat(S_BRUSH, new);
|
||||
// show ui
|
||||
gl_FragColor += wstat(S_UI, 96.);
|
||||
}
|
||||
} else if (uiTimer > 50.)
|
||||
gl_FragColor += wstat(S_UI, uiTimer - 1.);
|
||||
else if (uiTimer <= 50.)
|
||||
gl_FragColor += wstat(S_UI, max(0., uiTimer - 15.));
|
||||
} else if (uv.x < 0.5 && uv.y TOOLZONE) {
|
||||
gl_FragColor.rgb *= 1. - uiTimer / 100.;
|
||||
vec4 statCol = colstat(rstat(S_TOOL), gl_FragColor.a);
|
||||
gl_FragColor.a = 0.;
|
||||
statCol.rgb *= uiTimer / 100.;
|
||||
gl_FragColor += statCol;
|
||||
} else if (uv.x > 0.5 && uv.y TOOLZONE) {
|
||||
gl_FragColor.rgb *= 1. - uiTimer / 100.;
|
||||
vec4 statCol = colstat(rstat(S_BRUSH), gl_FragColor.a);
|
||||
gl_FragColor.a = 0.;
|
||||
statCol.rgb *= uiTimer / 100.;
|
||||
gl_FragColor += statCol;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user