Skip to content

Instantly share code, notes, and snippets.

@KrabCode
Last active March 29, 2020 14:47
Show Gist options
  • Select an option

  • Save KrabCode/d350549bfc55844e15f1589babb1407f to your computer and use it in GitHub Desktop.

Select an option

Save KrabCode/d350549bfc55844e15f1589babb1407f to your computer and use it in GitHub Desktop.
Reload your shaders on the fly with Processing using this code
// put this in the data folder
// when the sketch is running, change something here in a text editor and hit CTRL+S to see the changes
uniform sampler2D texture;
uniform vec2 resolution;
uniform float time;
void main(){
vec2 uv = (gl_FragCoord.xy-.5*resolution) / resolution.y;
vec3 col = 0.5 + 0.5*cos(time+uv.xyx+vec3(0,2,4));
gl_FragColor = vec4(col, 1.);
}
void setup() {
size(600, 600, P2D);
}
void draw() {
float t = radians(frameCount);
String testShader = "frag.glsl";
uniform(testShader).set("time", t);
hotFilter(testShader);
}
import static java.lang.System.currentTimeMillis;
ArrayList<ShaderSnapshot> snapshots = new ArrayList<ShaderSnapshot>();
int shaderRefreshRateInMillis = 100;
public PShader uniform(String fragPath) {
ShaderSnapshot snapshot = findSnapshotByPath(fragPath);
snapshot = initIfNull(snapshot, fragPath, null);
return snapshot.compiledShader;
}
public PShader uniform(String fragPath, String vertPath) {
ShaderSnapshot snapshot = findSnapshotByPath(fragPath);
snapshot = initIfNull(snapshot, fragPath, vertPath);
return snapshot.compiledShader;
}
public void hotFilter(String path, PGraphics canvas) {
hotShader(path, null, true, canvas);
}
public void hotFilter(String path) {
hotShader(path, null, true, g);
}
public void hotShader(String fragPath, String vertPath, PGraphics canvas) {
hotShader(fragPath, vertPath, false, canvas);
}
public void hotShader(String fragPath, String vertPath) {
hotShader(fragPath, vertPath, false, g);
}
public void hotShader(String fragPath, PGraphics canvas) {
hotShader(fragPath, null, false, canvas);
}
public void hotShader(String fragPath) {
hotShader(fragPath, null, false, g);
}
private void hotShader(String fragPath, String vertPath, boolean filter, PGraphics canvas) {
ShaderSnapshot snapshot = findSnapshotByPath(fragPath);
snapshot = initIfNull(snapshot, fragPath, vertPath);
snapshot.update(filter, canvas);
}
private ShaderSnapshot initIfNull(ShaderSnapshot snapshot, String fragPath, String vertPath) {
if (snapshot == null) {
snapshot = new ShaderSnapshot(fragPath, vertPath);
snapshots.add(snapshot);
}
return snapshot;
}
private ShaderSnapshot findSnapshotByPath(String path) {
for (ShaderSnapshot snapshot : snapshots) {
if (snapshot.fragPath.equals(path)) {
return snapshot;
}
}
return null;
}
private class ShaderSnapshot {
String fragPath;
String vertPath;
File fragFile;
File vertFile;
PShader compiledShader;
long fragLastKnownModified, vertLastKnownModified, lastChecked;
boolean compiledAtLeastOnce = false;
long lastKnownUncompilable = -shaderRefreshRateInMillis;
ShaderSnapshot(String fragPath, String vertPath) {
if (vertPath != null) {
compiledShader = loadShader(fragPath, vertPath);
vertFile = dataFile(vertPath);
vertLastKnownModified = vertFile.lastModified();
if (!vertFile.isFile()) {
println("Could not find shader at " + vertFile.getPath());
}
} else {
compiledShader = loadShader(fragPath);
}
fragFile = dataFile(fragPath);
fragLastKnownModified = fragFile.lastModified();
lastChecked = currentTimeMillis();
if (!fragFile.isFile()) {
println("Could not find shader at " + fragFile.getPath());
}
this.fragPath = fragPath;
this.vertPath = vertPath;
}
long max(long a, long b) {
if (a > b) {
return a;
}
return b;
}
void update(boolean filter, PGraphics pg) {
long currentTimeMillis = currentTimeMillis();
long lastModified = fragFile.lastModified();
if (vertFile != null) {
lastModified = max(lastModified, vertFile.lastModified());
}
if (compiledAtLeastOnce && currentTimeMillis < lastChecked + shaderRefreshRateInMillis) {
// println("compiled at least once, not checking, standard apply");
applyShader(compiledShader, filter, pg);
return;
}
if (!compiledAtLeastOnce && lastModified > lastKnownUncompilable) {
// println("first try");
tryCompileNewVersion(filter, pg, lastModified);
return;
}
lastChecked = currentTimeMillis;
if (lastModified > fragLastKnownModified && lastModified > lastKnownUncompilable) {
// println("file changed, repeat try");
tryCompileNewVersion(filter, pg, lastModified);
} else if (compiledAtLeastOnce) {
// println("file didn't change, standard apply");
applyShader(compiledShader, filter, pg);
}
}
private void applyShader(PShader shader, boolean filter, PGraphics pg) {
if (filter) {
pg.filter(shader);
} else {
pg.shader(shader);
}
}
private void tryCompileNewVersion(boolean filter, PGraphics pg, long lastModified) {
try {
PShader candidate;
if (vertFile == null) {
candidate = loadShader(fragPath);
} else {
candidate = loadShader(fragPath, vertPath);
}
// we need to call filter() or shader() here in order to catch any compilation errors and not halt
// the sketch
applyShader(candidate, filter, pg);
compiledShader = candidate;
compiledAtLeastOnce = true;
fragLastKnownModified = lastModified;
}
catch (Exception ex) {
lastKnownUncompilable = lastModified;
println("\n" + fragFile.getName() + ": " + ex.getMessage());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment