[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